1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef CRYPTO_NSS_UTIL_H_ 6 #define CRYPTO_NSS_UTIL_H_ 7 8 #include <string> 9 #include "base/basictypes.h" 10 #include "base/callback.h" 11 #include "base/compiler_specific.h" 12 #include "base/files/scoped_temp_dir.h" 13 #include "crypto/crypto_export.h" 14 15 namespace base { 16 class FilePath; 17 class Lock; 18 class Time; 19 } // namespace base 20 21 // This file specifically doesn't depend on any NSS or NSPR headers because it 22 // is included by various (non-crypto) parts of chrome to call the 23 // initialization functions. 24 namespace crypto { 25 26 // The TPMToken name used for the NSS slot opened by ScopedTestNSSDB. 27 CRYPTO_EXPORT extern const char kTestTPMTokenName[]; 28 29 #if defined(USE_NSS) 30 // EarlySetupForNSSInit performs lightweight setup which must occur before the 31 // process goes multithreaded. This does not initialise NSS. For test, see 32 // EnsureNSSInit. 33 CRYPTO_EXPORT void EarlySetupForNSSInit(); 34 #endif 35 36 // Initialize NRPR if it isn't already initialized. This function is 37 // thread-safe, and NSPR will only ever be initialized once. 38 CRYPTO_EXPORT void EnsureNSPRInit(); 39 40 // Initialize NSS safely for strict sandboxing. This function tells NSS to not 41 // load user security modules, and makes sure NSS will have proper entropy in a 42 // restricted, sandboxed environment. 43 // 44 // As a defense in depth measure, this function should be called in a sandboxed 45 // environment. That way, in the event of a bug, NSS will still not be able to 46 // load security modules that could expose private data and keys. 47 // 48 // Make sure to get an LGTM from the Chrome Security Team if you use this. 49 CRYPTO_EXPORT void InitNSSSafely(); 50 51 // Initialize NSS if it isn't already initialized. This must be called before 52 // any other NSS functions. This function is thread-safe, and NSS will only 53 // ever be initialized once. 54 CRYPTO_EXPORT void EnsureNSSInit(); 55 56 // Call this before calling EnsureNSSInit() will force NSS to initialize 57 // without a persistent DB. This is used for the special case where access of 58 // persistent DB is prohibited. 59 // 60 // TODO(hclam): Isolate loading default root certs. 61 // 62 // NSS will be initialized without loading any user security modules, including 63 // the built-in root certificates module. User security modules need to be 64 // loaded manually after NSS initialization. 65 // 66 // If EnsureNSSInit() is called before then this function has no effect. 67 // 68 // Calling this method only has effect on Linux. 69 // 70 // WARNING: Use this with caution. 71 CRYPTO_EXPORT void ForceNSSNoDBInit(); 72 73 // This method is used to disable checks in NSS when used in a forked process. 74 // NSS checks whether it is running a forked process to avoid problems when 75 // using user security modules in a forked process. However if we are sure 76 // there are no modules loaded before the process is forked then there is no 77 // harm disabling the check. 78 // 79 // This method must be called before EnsureNSSInit() to take effect. 80 // 81 // WARNING: Use this with caution. 82 CRYPTO_EXPORT void DisableNSSForkCheck(); 83 84 // Load NSS library files. This function has no effect on Mac and Windows. 85 // This loads the necessary NSS library files so that NSS can be initialized 86 // after loading additional library files is disallowed, for example when the 87 // sandbox is active. 88 // 89 // Note that this does not load libnssckbi.so which contains the root 90 // certificates. 91 CRYPTO_EXPORT void LoadNSSLibraries(); 92 93 // Check if the current NSS version is greater than or equals to |version|. 94 // A sample version string is "3.12.3". 95 bool CheckNSSVersion(const char* version); 96 97 #if defined(OS_CHROMEOS) 98 // Open the r/w nssdb that's stored inside the user's encrypted home 99 // directory. This is the default slot returned by 100 // GetPublicNSSKeySlot(). 101 CRYPTO_EXPORT void OpenPersistentNSSDB(); 102 103 // Indicates that NSS should load the Chaps library so that we 104 // can access the TPM through NSS. Once this is called, 105 // GetPrivateNSSKeySlot() will return the TPM slot if one was found. 106 CRYPTO_EXPORT void EnableTPMTokenForNSS(); 107 108 // Returns true if EnableTPMTokenForNSS has been called. 109 CRYPTO_EXPORT bool IsTPMTokenEnabledForNSS(); 110 111 // Returns true if the TPM is owned and PKCS#11 initialized with the 112 // user and security officer PINs, and has been enabled in NSS by 113 // calling EnableTPMForNSS, and Chaps has been successfully 114 // loaded into NSS. 115 // If |callback| is non-null and the function returns false, the |callback| will 116 // be run once the TPM is ready. |callback| will never be run if the function 117 // returns true. 118 CRYPTO_EXPORT bool IsTPMTokenReady(const base::Closure& callback) 119 WARN_UNUSED_RESULT; 120 121 // Initialize the TPM token. The |callback| will run on the same thread with 122 // true if the token and slot were successfully loaded or were already 123 // initialized. |callback| will be passed false if loading failed. 124 // Once called, InitializeTPMToken must not be called again until the |callback| 125 // has been run. 126 CRYPTO_EXPORT void InitializeTPMToken( 127 int token_slot_id, 128 const base::Callback<void(bool)>& callback); 129 130 // Exposed for unittests only. 131 class CRYPTO_EXPORT_PRIVATE ScopedTestNSSChromeOSUser { 132 public: 133 explicit ScopedTestNSSChromeOSUser(const std::string& username_hash); 134 ~ScopedTestNSSChromeOSUser(); 135 136 std::string username_hash() const { return username_hash_; } 137 bool constructed_successfully() const { return constructed_successfully_; } 138 139 // Completes initialization of user. Causes any waiting private slot callbacks 140 // to run. 141 void FinishInit(); 142 143 private: 144 const std::string username_hash_; 145 base::ScopedTempDir temp_dir_; 146 bool constructed_successfully_; 147 DISALLOW_COPY_AND_ASSIGN(ScopedTestNSSChromeOSUser); 148 }; 149 #endif 150 151 // Convert a NSS PRTime value into a base::Time object. 152 // We use a int64 instead of PRTime here to avoid depending on NSPR headers. 153 CRYPTO_EXPORT base::Time PRTimeToBaseTime(int64 prtime); 154 155 // Convert a base::Time object into a PRTime value. 156 // We use a int64 instead of PRTime here to avoid depending on NSPR headers. 157 CRYPTO_EXPORT int64 BaseTimeToPRTime(base::Time time); 158 159 #if defined(USE_NSS) 160 // Exposed for unittests only. 161 // TODO(mattm): When NSS 3.14 is the minimum version required, 162 // switch back to using a separate user DB for each test. 163 // Because of https://bugzilla.mozilla.org/show_bug.cgi?id=588269 , the 164 // opened user DB is not automatically closed. 165 class CRYPTO_EXPORT_PRIVATE ScopedTestNSSDB { 166 public: 167 ScopedTestNSSDB(); 168 ~ScopedTestNSSDB(); 169 170 bool is_open() { return is_open_; } 171 172 private: 173 bool is_open_; 174 DISALLOW_COPY_AND_ASSIGN(ScopedTestNSSDB); 175 }; 176 177 // NSS has a bug which can cause a deadlock or stall in some cases when writing 178 // to the certDB and keyDB. It also has a bug which causes concurrent key pair 179 // generations to scribble over each other. To work around this, we synchronize 180 // writes to the NSS databases with a global lock. The lock is hidden beneath a 181 // function for easy disabling when the bug is fixed. Callers should allow for 182 // it to return NULL in the future. 183 // 184 // See https://bugzilla.mozilla.org/show_bug.cgi?id=564011 185 base::Lock* GetNSSWriteLock(); 186 187 // A helper class that acquires the NSS write Lock while the AutoNSSWriteLock 188 // is in scope. 189 class CRYPTO_EXPORT AutoNSSWriteLock { 190 public: 191 AutoNSSWriteLock(); 192 ~AutoNSSWriteLock(); 193 private: 194 base::Lock *lock_; 195 DISALLOW_COPY_AND_ASSIGN(AutoNSSWriteLock); 196 }; 197 198 #endif // defined(USE_NSS) 199 200 } // namespace crypto 201 202 #endif // CRYPTO_NSS_UTIL_H_ 203