[email protected] | 9fc4416 | 2012-01-23 22:56:41 | [diff] [blame] | 1 | // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
[email protected] | bc1e07c7 | 2008-09-16 14:32:44 | [diff] [blame] | 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
[email protected] | 4b559b4d | 2011-04-14 17:37:14 | [diff] [blame] | 5 | #include "crypto/nss_util.h" |
[email protected] | bc1e07c7 | 2008-09-16 14:32:44 | [diff] [blame] | 6 | |
[email protected] | bc1e07c7 | 2008-09-16 14:32:44 | [diff] [blame] | 7 | #include <nss.h> |
[email protected] | ea1a3f6 | 2012-11-16 20:34:23 | [diff] [blame] | 8 | #include <pk11pub.h> |
[email protected] | c72f16a | 2009-03-19 16:02:31 | [diff] [blame] | 9 | #include <plarena.h> |
[email protected] | 6e7e806 | 2009-04-13 17:35:09 | [diff] [blame] | 10 | #include <prerror.h> |
[email protected] | c72f16a | 2009-03-19 16:02:31 | [diff] [blame] | 11 | #include <prinit.h> |
[email protected] | 1b1a264a | 2010-01-14 22:36:35 | [diff] [blame] | 12 | #include <prtime.h> |
[email protected] | ea22458 | 2008-12-07 20:25:46 | [diff] [blame] | 13 | #include <secmod.h> |
thakis | d1a1847 | 2016-04-08 22:30:41 | [diff] [blame] | 14 | |
| 15 | #include <memory> |
dcheng | cf738a9 | 2015-12-31 16:11:45 | [diff] [blame] | 16 | #include <utility> |
[email protected] | f6a67b4 | 2011-03-17 23:49:21 | [diff] [blame] | 17 | |
[email protected] | 6bdc5227 | 2014-05-27 00:12:33 | [diff] [blame] | 18 | #include "base/base_paths.h" |
[email protected] | 716fb11 | 2012-11-15 05:41:25 | [diff] [blame] | 19 | #include "base/debug/alias.h" |
[email protected] | 5799981 | 2013-02-24 05:40:52 | [diff] [blame] | 20 | #include "base/files/file_path.h" |
thestig | c9e38a2 | 2014-09-13 01:02:11 | [diff] [blame] | 21 | #include "base/files/file_util.h" |
[email protected] | f615bda3 | 2010-11-21 01:04:56 | [diff] [blame] | 22 | #include "base/lazy_instance.h" |
[email protected] | c1444fe | 2008-09-17 09:42:51 | [diff] [blame] | 23 | #include "base/logging.h" |
[email protected] | 6bdc5227 | 2014-05-27 00:12:33 | [diff] [blame] | 24 | #include "base/path_service.h" |
[email protected] | 0d8db08 | 2013-06-11 07:27:01 | [diff] [blame] | 25 | #include "base/strings/stringprintf.h" |
Gabriel Charette | 44db142 | 2018-08-06 11:19:33 | [diff] [blame] | 26 | #include "base/task/post_task.h" |
Francois Doray | a4d445c | 2017-08-28 16:36:28 | [diff] [blame] | 27 | #include "base/threading/scoped_blocking_call.h" |
[email protected] | 34b9963 | 2011-01-01 01:01:06 | [diff] [blame] | 28 | #include "base/threading/thread_restrictions.h" |
[email protected] | 26661c2 | 2011-10-07 01:33:58 | [diff] [blame] | 29 | #include "build/build_config.h" |
[email protected] | 99e5e952 | 2013-12-16 13:05:27 | [diff] [blame] | 30 | #include "crypto/nss_crypto_module_delegate.h" |
David Benjamin | 839b74b | 2017-06-26 21:45:22 | [diff] [blame] | 31 | #include "crypto/nss_util_internal.h" |
| 32 | |
[email protected] | 4b559b4d | 2011-04-14 17:37:14 | [diff] [blame] | 33 | namespace crypto { |
[email protected] | f163393 | 2010-08-17 23:05:28 | [diff] [blame] | 34 | |
[email protected] | bc1e07c7 | 2008-09-16 14:32:44 | [diff] [blame] | 35 | namespace { |
| 36 | |
[email protected] | 6a89ef2 | 2011-04-07 17:34:21 | [diff] [blame] | 37 | #if defined(OS_CHROMEOS) |
[email protected] | 6a89ef2 | 2011-04-07 17:34:21 | [diff] [blame] | 38 | // Fake certificate authority database used for testing. |
[email protected] | 9e27571 | 2013-02-10 19:20:14 | [diff] [blame] | 39 | static const base::FilePath::CharType kReadOnlyCertDB[] = |
[email protected] | 6a89ef2 | 2011-04-07 17:34:21 | [diff] [blame] | 40 | FILE_PATH_LITERAL("/etc/fake_root_ca/nssdb"); |
| 41 | #endif // defined(OS_CHROMEOS) |
| 42 | |
[email protected] | 4071e6ac | 2014-07-12 12:46:17 | [diff] [blame] | 43 | #if !defined(OS_CHROMEOS) |
[email protected] | 9e27571 | 2013-02-10 19:20:14 | [diff] [blame] | 44 | base::FilePath GetDefaultConfigDirectory() { |
[email protected] | 6bdc5227 | 2014-05-27 00:12:33 | [diff] [blame] | 45 | base::FilePath dir; |
Avi Drissman | ea15ea0 | 2018-05-07 18:55:12 | [diff] [blame] | 46 | base::PathService::Get(base::DIR_HOME, &dir); |
[email protected] | a8b58f4 | 2010-07-14 20:21:35 | [diff] [blame] | 47 | if (dir.empty()) { |
| 48 | LOG(ERROR) << "Failed to get home directory."; |
| 49 | return dir; |
[email protected] | 8691334 | 2009-05-25 02:14:34 | [diff] [blame] | 50 | } |
[email protected] | 8691334 | 2009-05-25 02:14:34 | [diff] [blame] | 51 | dir = dir.AppendASCII(".pki").AppendASCII("nssdb"); |
[email protected] | 426d1c9 | 2013-12-03 20:08:54 | [diff] [blame] | 52 | if (!base::CreateDirectory(dir)) { |
[email protected] | 948a707b | 2011-06-07 22:51:44 | [diff] [blame] | 53 | LOG(ERROR) << "Failed to create " << dir.value() << " directory."; |
[email protected] | a8b58f4 | 2010-07-14 20:21:35 | [diff] [blame] | 54 | dir.clear(); |
[email protected] | 8691334 | 2009-05-25 02:14:34 | [diff] [blame] | 55 | } |
[email protected] | 557737f7 | 2013-12-06 22:24:07 | [diff] [blame] | 56 | DVLOG(2) << "DefaultConfigDirectory: " << dir.value(); |
[email protected] | a8b58f4 | 2010-07-14 20:21:35 | [diff] [blame] | 57 | return dir; |
[email protected] | 8691334 | 2009-05-25 02:14:34 | [diff] [blame] | 58 | } |
Michael Giuffrida | dc8030c | 2017-08-02 13:22:44 | [diff] [blame] | 59 | #endif // !defined(OS_CHROMEOS) |
[email protected] | 8691334 | 2009-05-25 02:14:34 | [diff] [blame] | 60 | |
[email protected] | 259c42f | 2013-09-12 20:32:22 | [diff] [blame] | 61 | // On non-Chrome OS platforms, return the default config directory. On Chrome OS |
| 62 | // test images, return a read-only directory with fake root CA certs (which are |
| 63 | // used by the local Google Accounts server mock we use when testing our login |
| 64 | // code). On Chrome OS non-test images (where the read-only directory doesn't |
| 65 | // exist), return an empty path. |
[email protected] | 9e27571 | 2013-02-10 19:20:14 | [diff] [blame] | 66 | base::FilePath GetInitialConfigDirectory() { |
[email protected] | dcce6cf | 2010-04-29 17:50:06 | [diff] [blame] | 67 | #if defined(OS_CHROMEOS) |
[email protected] | 259c42f | 2013-09-12 20:32:22 | [diff] [blame] | 68 | base::FilePath database_dir = base::FilePath(kReadOnlyCertDB); |
| 69 | if (!base::PathExists(database_dir)) |
| 70 | database_dir.clear(); |
| 71 | return database_dir; |
[email protected] | dcce6cf | 2010-04-29 17:50:06 | [diff] [blame] | 72 | #else |
| 73 | return GetDefaultConfigDirectory(); |
| 74 | #endif // defined(OS_CHROMEOS) |
| 75 | } |
| 76 | |
[email protected] | 88b9db7 | 2011-01-13 01:48:43 | [diff] [blame] | 77 | // This callback for NSS forwards all requests to a caller-specified |
[email protected] | 3f1f841 | 2011-01-19 03:01:23 | [diff] [blame] | 78 | // CryptoModuleBlockingPasswordDelegate object. |
| 79 | char* PKCS11PasswordFunc(PK11SlotInfo* slot, PRBool retry, void* arg) { |
[email protected] | 4b559b4d | 2011-04-14 17:37:14 | [diff] [blame] | 80 | crypto::CryptoModuleBlockingPasswordDelegate* delegate = |
| 81 | reinterpret_cast<crypto::CryptoModuleBlockingPasswordDelegate*>(arg); |
[email protected] | 88b9db7 | 2011-01-13 01:48:43 | [diff] [blame] | 82 | if (delegate) { |
| 83 | bool cancelled = false; |
| 84 | std::string password = delegate->RequestPassword(PK11_GetTokenName(slot), |
| 85 | retry != PR_FALSE, |
| 86 | &cancelled); |
| 87 | if (cancelled) |
rsleevi | ffe5a13 | 2016-06-28 01:51:52 | [diff] [blame] | 88 | return nullptr; |
[email protected] | 88b9db7 | 2011-01-13 01:48:43 | [diff] [blame] | 89 | char* result = PORT_Strdup(password.c_str()); |
| 90 | password.replace(0, password.size(), password.size(), 0); |
| 91 | return result; |
| 92 | } |
rsleevi | ffe5a13 | 2016-06-28 01:51:52 | [diff] [blame] | 93 | DLOG(ERROR) << "PK11 password requested with nullptr arg"; |
| 94 | return nullptr; |
[email protected] | 88b9db7 | 2011-01-13 01:48:43 | [diff] [blame] | 95 | } |
| 96 | |
[email protected] | 730fb13 | 2009-09-02 22:50:25 | [diff] [blame] | 97 | // A singleton to initialize/deinitialize NSPR. |
| 98 | // Separate from the NSS singleton because we initialize NSPR on the UI thread. |
[email protected] | f615bda3 | 2010-11-21 01:04:56 | [diff] [blame] | 99 | // Now that we're leaking the singleton, we could merge back with the NSS |
| 100 | // singleton. |
[email protected] | 730fb13 | 2009-09-02 22:50:25 | [diff] [blame] | 101 | class NSPRInitSingleton { |
[email protected] | f615bda3 | 2010-11-21 01:04:56 | [diff] [blame] | 102 | private: |
scottmg | 5e65e3a | 2017-03-08 08:48:46 | [diff] [blame] | 103 | friend struct base::LazyInstanceTraitsBase<NSPRInitSingleton>; |
[email protected] | f615bda3 | 2010-11-21 01:04:56 | [diff] [blame] | 104 | |
[email protected] | 730fb13 | 2009-09-02 22:50:25 | [diff] [blame] | 105 | NSPRInitSingleton() { |
| 106 | PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); |
| 107 | } |
| 108 | |
Matt Mueller | e82b3a54 | 2017-07-21 17:44:55 | [diff] [blame] | 109 | // NOTE(willchan): We don't actually cleanup on destruction since we leak NSS |
| 110 | // to prevent non-joinable threads from using NSS after it's already been |
| 111 | // shut down. |
| 112 | ~NSPRInitSingleton() = delete; |
[email protected] | 730fb13 | 2009-09-02 22:50:25 | [diff] [blame] | 113 | }; |
| 114 | |
[email protected] | 9fc4416 | 2012-01-23 22:56:41 | [diff] [blame] | 115 | base::LazyInstance<NSPRInitSingleton>::Leaky |
[email protected] | 6de0fd1d | 2011-11-15 13:31:49 | [diff] [blame] | 116 | g_nspr_singleton = LAZY_INSTANCE_INITIALIZER; |
[email protected] | f615bda3 | 2010-11-21 01:04:56 | [diff] [blame] | 117 | |
[email protected] | 007f512 | 2012-11-21 16:00:21 | [diff] [blame] | 118 | // Force a crash with error info on NSS_NoDB_Init failure. |
| 119 | void CrashOnNSSInitFailure() { |
| 120 | int nss_error = PR_GetError(); |
| 121 | int os_error = PR_GetOSError(); |
[email protected] | 716fb11 | 2012-11-15 05:41:25 | [diff] [blame] | 122 | base::debug::Alias(&nss_error); |
| 123 | base::debug::Alias(&os_error); |
[email protected] | 007f512 | 2012-11-21 16:00:21 | [diff] [blame] | 124 | LOG(ERROR) << "Error initializing NSS without a persistent database: " |
| 125 | << GetNSSErrorMessage(); |
[email protected] | 2b12459a | 2012-11-16 03:45:32 | [diff] [blame] | 126 | LOG(FATAL) << "nss_error=" << nss_error << ", os_error=" << os_error; |
[email protected] | 716fb11 | 2012-11-15 05:41:25 | [diff] [blame] | 127 | } |
| 128 | |
[email protected] | bc1e07c7 | 2008-09-16 14:32:44 | [diff] [blame] | 129 | class NSSInitSingleton { |
[email protected] | f615bda3 | 2010-11-21 01:04:56 | [diff] [blame] | 130 | private: |
scottmg | 5e65e3a | 2017-03-08 08:48:46 | [diff] [blame] | 131 | friend struct base::LazyInstanceTraitsBase<NSSInitSingleton>; |
[email protected] | f615bda3 | 2010-11-21 01:04:56 | [diff] [blame] | 132 | |
David Benjamin | 87ccc99 | 2019-10-12 01:09:03 | [diff] [blame] | 133 | NSSInitSingleton() { |
Matt Mueller | 7858f42 | 2018-03-27 03:25:02 | [diff] [blame] | 134 | // Initializing NSS causes us to do blocking IO. |
| 135 | // Temporarily allow it until we fix |
| 136 | // http://code.google.com/p/chromium/issues/detail?id=59847 |
| 137 | base::ThreadRestrictions::ScopedAllowIO allow_io; |
| 138 | |
[email protected] | f615bda3 | 2010-11-21 01:04:56 | [diff] [blame] | 139 | EnsureNSPRInit(); |
[email protected] | 730fb13 | 2009-09-02 22:50:25 | [diff] [blame] | 140 | |
rsleevi | b52a2df | 2017-06-08 18:28:11 | [diff] [blame] | 141 | // We *must* have NSS >= 3.26 at compile time. |
| 142 | static_assert((NSS_VMAJOR == 3 && NSS_VMINOR >= 26) || (NSS_VMAJOR > 3), |
| 143 | "nss version check failed"); |
[email protected] | dc36c9c | 2010-01-20 20:45:00 | [diff] [blame] | 144 | // Also check the run-time NSS version. |
| 145 | // NSS_VersionCheck is a >= check, not strict equality. |
rsleevi | b52a2df | 2017-06-08 18:28:11 | [diff] [blame] | 146 | if (!NSS_VersionCheck("3.26")) { |
| 147 | LOG(FATAL) << "NSS_VersionCheck(\"3.26\") failed. NSS >= 3.26 is " |
[email protected] | 805acdc | 2013-08-07 22:57:00 | [diff] [blame] | 148 | "required. Please upgrade to the latest NSS, and if you " |
[email protected] | 1b8082d | 2010-02-19 12:21:48 | [diff] [blame] | 149 | "still get this error, contact your distribution " |
| 150 | "maintainer."; |
| 151 | } |
[email protected] | dc36c9c | 2010-01-20 20:45:00 | [diff] [blame] | 152 | |
[email protected] | 897f520 | 2009-09-08 17:40:27 | [diff] [blame] | 153 | SECStatus status = SECFailure; |
rsleevi | a3ad8d0 | 2016-06-07 18:22:33 | [diff] [blame] | 154 | base::FilePath database_dir = GetInitialConfigDirectory(); |
| 155 | if (!database_dir.empty()) { |
rsleevi | a3ad8d0 | 2016-06-07 18:22:33 | [diff] [blame] | 156 | // Initialize with a persistent database (likely, ~/.pki/nssdb). |
| 157 | // Use "sql:" which can be shared by multiple processes safely. |
| 158 | std::string nss_config_dir = |
| 159 | base::StringPrintf("sql:%s", database_dir.value().c_str()); |
| 160 | #if defined(OS_CHROMEOS) |
| 161 | status = NSS_Init(nss_config_dir.c_str()); |
| 162 | #else |
| 163 | status = NSS_InitReadWrite(nss_config_dir.c_str()); |
[email protected] | dcce6cf | 2010-04-29 17:50:06 | [diff] [blame] | 164 | #endif |
rsleevi | a3ad8d0 | 2016-06-07 18:22:33 | [diff] [blame] | 165 | if (status != SECSuccess) { |
| 166 | LOG(ERROR) << "Error initializing NSS with a persistent " |
| 167 | "database (" << nss_config_dir |
| 168 | << "): " << GetNSSErrorMessage(); |
| 169 | } |
| 170 | } |
| 171 | if (status != SECSuccess) { |
| 172 | VLOG(1) << "Initializing NSS without a persistent database."; |
rsleevi | ffe5a13 | 2016-06-28 01:51:52 | [diff] [blame] | 173 | status = NSS_NoDB_Init(nullptr); |
[email protected] | 897f520 | 2009-09-08 17:40:27 | [diff] [blame] | 174 | if (status != SECSuccess) { |
[email protected] | 007f512 | 2012-11-21 16:00:21 | [diff] [blame] | 175 | CrashOnNSSInitFailure(); |
[email protected] | 716fb11 | 2012-11-15 05:41:25 | [diff] [blame] | 176 | return; |
[email protected] | 897f520 | 2009-09-08 17:40:27 | [diff] [blame] | 177 | } |
[email protected] | 6e7e806 | 2009-04-13 17:35:09 | [diff] [blame] | 178 | } |
[email protected] | fa2d3dc | 2012-11-20 07:58:44 | [diff] [blame] | 179 | |
rsleevi | a3ad8d0 | 2016-06-07 18:22:33 | [diff] [blame] | 180 | PK11_SetPasswordFunc(PKCS11PasswordFunc); |
| 181 | |
| 182 | // If we haven't initialized the password for the NSS databases, |
| 183 | // initialize an empty-string password so that we don't need to |
| 184 | // log in. |
| 185 | PK11SlotInfo* slot = PK11_GetInternalKeySlot(); |
| 186 | if (slot) { |
| 187 | // PK11_InitPin may write to the keyDB, but no other thread can use NSS |
| 188 | // yet, so we don't need to lock. |
| 189 | if (PK11_NeedUserInit(slot)) |
rsleevi | ffe5a13 | 2016-06-28 01:51:52 | [diff] [blame] | 190 | PK11_InitPin(slot, nullptr, nullptr); |
rsleevi | a3ad8d0 | 2016-06-07 18:22:33 | [diff] [blame] | 191 | PK11_FreeSlot(slot); |
| 192 | } |
| 193 | |
David Benjamin | e838004a | 2019-10-13 08:03:08 | [diff] [blame] | 194 | // Load nss's built-in root certs. |
| 195 | // |
| 196 | // TODO(mattm): DCHECK this succeeded when crbug.com/310972 is fixed. |
| 197 | // Failing to load root certs will it hard to talk to anybody via https. |
David Benjamin | 2f2cb36 | 2019-10-15 22:51:05 | [diff] [blame] | 198 | LoadNSSModule("Root Certs", "libnssckbi.so", nullptr); |
rsleevi | a3ad8d0 | 2016-06-07 18:22:33 | [diff] [blame] | 199 | |
[email protected] | fa2d3dc | 2012-11-20 07:58:44 | [diff] [blame] | 200 | // Disable MD5 certificate signatures. (They are disabled by default in |
| 201 | // NSS 3.14.) |
| 202 | NSS_SetAlgorithmPolicy(SEC_OID_MD5, 0, NSS_USE_ALG_IN_CERT_SIGNATURE); |
| 203 | NSS_SetAlgorithmPolicy(SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION, |
| 204 | 0, NSS_USE_ALG_IN_CERT_SIGNATURE); |
[email protected] | bc1e07c7 | 2008-09-16 14:32:44 | [diff] [blame] | 205 | } |
| 206 | |
Matt Mueller | e82b3a54 | 2017-07-21 17:44:55 | [diff] [blame] | 207 | // NOTE(willchan): We don't actually cleanup on destruction since we leak NSS |
| 208 | // to prevent non-joinable threads from using NSS after it's already been |
| 209 | // shut down. |
| 210 | ~NSSInitSingleton() = delete; |
[email protected] | bc1e07c7 | 2008-09-16 14:32:44 | [diff] [blame] | 211 | }; |
| 212 | |
[email protected] | 9fc4416 | 2012-01-23 22:56:41 | [diff] [blame] | 213 | base::LazyInstance<NSSInitSingleton>::Leaky |
[email protected] | 6de0fd1d | 2011-11-15 13:31:49 | [diff] [blame] | 214 | g_nss_singleton = LAZY_INSTANCE_INITIALIZER; |
[email protected] | bc1e07c7 | 2008-09-16 14:32:44 | [diff] [blame] | 215 | } // namespace |
| 216 | |
[email protected] | 190933f | 2014-07-28 09:56:51 | [diff] [blame] | 217 | ScopedPK11Slot OpenSoftwareNSSDB(const base::FilePath& path, |
| 218 | const std::string& description) { |
| 219 | const std::string modspec = |
| 220 | base::StringPrintf("configDir='sql:%s' tokenDescription='%s'", |
| 221 | path.value().c_str(), |
| 222 | description.c_str()); |
| 223 | PK11SlotInfo* db_slot = SECMOD_OpenUserDB(modspec.c_str()); |
| 224 | if (db_slot) { |
| 225 | if (PK11_NeedUserInit(db_slot)) |
rsleevi | ffe5a13 | 2016-06-28 01:51:52 | [diff] [blame] | 226 | PK11_InitPin(db_slot, nullptr, nullptr); |
[email protected] | 190933f | 2014-07-28 09:56:51 | [diff] [blame] | 227 | } else { |
| 228 | LOG(ERROR) << "Error opening persistent database (" << modspec |
| 229 | << "): " << GetNSSErrorMessage(); |
| 230 | } |
| 231 | return ScopedPK11Slot(db_slot); |
| 232 | } |
| 233 | |
[email protected] | 730fb13 | 2009-09-02 22:50:25 | [diff] [blame] | 234 | void EnsureNSPRInit() { |
[email protected] | f615bda3 | 2010-11-21 01:04:56 | [diff] [blame] | 235 | g_nspr_singleton.Get(); |
[email protected] | 730fb13 | 2009-09-02 22:50:25 | [diff] [blame] | 236 | } |
| 237 | |
[email protected] | bc1e07c7 | 2008-09-16 14:32:44 | [diff] [blame] | 238 | void EnsureNSSInit() { |
[email protected] | f615bda3 | 2010-11-21 01:04:56 | [diff] [blame] | 239 | g_nss_singleton.Get(); |
[email protected] | bc1e07c7 | 2008-09-16 14:32:44 | [diff] [blame] | 240 | } |
| 241 | |
[email protected] | f61c397 | 2010-12-23 09:54:15 | [diff] [blame] | 242 | bool CheckNSSVersion(const char* version) { |
| 243 | return !!NSS_VersionCheck(version); |
| 244 | } |
| 245 | |
[email protected] | dd24ffc | 2011-06-08 19:46:42 | [diff] [blame] | 246 | AutoSECMODListReadLock::AutoSECMODListReadLock() |
| 247 | : lock_(SECMOD_GetDefaultModuleListLock()) { |
| 248 | SECMOD_GetReadLock(lock_); |
| 249 | } |
| 250 | |
| 251 | AutoSECMODListReadLock::~AutoSECMODListReadLock() { |
| 252 | SECMOD_ReleaseReadLock(lock_); |
| 253 | } |
[email protected] | 6913847 | 2010-06-25 22:44:48 | [diff] [blame] | 254 | |
[email protected] | 4b559b4d | 2011-04-14 17:37:14 | [diff] [blame] | 255 | base::Time PRTimeToBaseTime(PRTime prtime) { |
[email protected] | ca929ed3 | 2011-12-15 20:37:28 | [diff] [blame] | 256 | return base::Time::FromInternalValue( |
| 257 | prtime + base::Time::UnixEpoch().ToInternalValue()); |
| 258 | } |
[email protected] | 1b1a264a | 2010-01-14 22:36:35 | [diff] [blame] | 259 | |
[email protected] | ca929ed3 | 2011-12-15 20:37:28 | [diff] [blame] | 260 | PRTime BaseTimeToPRTime(base::Time time) { |
| 261 | return time.ToInternalValue() - base::Time::UnixEpoch().ToInternalValue(); |
[email protected] | 1b1a264a | 2010-01-14 22:36:35 | [diff] [blame] | 262 | } |
| 263 | |
David Benjamin | 2f2cb36 | 2019-10-15 22:51:05 | [diff] [blame] | 264 | SECMODModule* LoadNSSModule(const char* name, |
| 265 | const char* library_path, |
| 266 | const char* params) { |
| 267 | std::string modparams = |
| 268 | base::StringPrintf("name=\"%s\" library=\"%s\" %s", name, library_path, |
| 269 | params ? params : ""); |
| 270 | |
| 271 | // Shouldn't need to const_cast here, but SECMOD doesn't properly declare |
| 272 | // input string arguments as const. Bug |
| 273 | // https://bugzilla.mozilla.org/show_bug.cgi?id=642546 was filed on NSS |
| 274 | // codebase to address this. |
| 275 | SECMODModule* module = SECMOD_LoadUserModule( |
| 276 | const_cast<char*>(modparams.c_str()), nullptr, PR_FALSE); |
| 277 | if (!module) { |
| 278 | LOG(ERROR) << "Error loading " << name |
| 279 | << " module into NSS: " << GetNSSErrorMessage(); |
| 280 | return nullptr; |
| 281 | } |
| 282 | if (!module->loaded) { |
| 283 | LOG(ERROR) << "After loading " << name |
| 284 | << ", loaded==false: " << GetNSSErrorMessage(); |
| 285 | SECMOD_DestroyModule(module); |
| 286 | return nullptr; |
| 287 | } |
| 288 | return module; |
| 289 | } |
| 290 | |
| 291 | std::string GetNSSErrorMessage() { |
| 292 | std::string result; |
| 293 | if (PR_GetErrorTextLength()) { |
| 294 | std::unique_ptr<char[]> error_text(new char[PR_GetErrorTextLength() + 1]); |
| 295 | PRInt32 copied = PR_GetErrorText(error_text.get()); |
| 296 | result = std::string(error_text.get(), copied); |
| 297 | } else { |
| 298 | result = base::StringPrintf("NSS error code: %d", PR_GetError()); |
| 299 | } |
| 300 | return result; |
| 301 | } |
| 302 | |
[email protected] | 4b559b4d | 2011-04-14 17:37:14 | [diff] [blame] | 303 | } // namespace crypto |