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