1 // Copyright 2021 The Chromium Authors 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_UNEXPORTABLE_KEY_H_ 6 #define CRYPTO_UNEXPORTABLE_KEY_H_ 7 8 #include <memory> 9 #include <optional> 10 11 #include "build/build_config.h" 12 #include "crypto/crypto_export.h" 13 #include "crypto/signature_verifier.h" 14 15 #if BUILDFLAG(IS_MAC) 16 #import <Security/Security.h> 17 #endif // BUILDFLAG(IS_MAC) 18 19 namespace crypto { 20 21 // UnexportableSigningKey provides a hardware-backed signing oracle on platforms 22 // that support it. Current support is: 23 // Windows: RSA_PKCS1_SHA256 via TPM 1.2+ and ECDSA_SHA256 via TPM 2.0. 24 // macOS: ECDSA_SHA256 via the Secure Enclave. 25 // Tests: ECDSA_SHA256 via ScopedMockUnexportableSigningKeyForTesting. 26 // 27 // See also //components/unexportable_keys for a higher-level key management 28 // API. 29 class CRYPTO_EXPORT UnexportableSigningKey { 30 public: 31 virtual ~UnexportableSigningKey(); 32 33 // Algorithm returns the algorithm of the key in this object. 34 virtual SignatureVerifier::SignatureAlgorithm Algorithm() const = 0; 35 36 // GetSubjectPublicKeyInfo returns an SPKI that contains the public key of 37 // this object. 38 virtual std::vector<uint8_t> GetSubjectPublicKeyInfo() const = 0; 39 40 // GetWrappedKey returns a handle to the private key of this object. Usually, 41 // it is the private key encrypted to a key that is kept in hardware and the 42 // unencrypted private key never exists in the CPU's memory, hence the name. 43 // On Mac, this is instead a hash of the public key and the wrapped key 44 // material is stored in the Keychain. 45 // 46 // A key handle may be used with a future instance of this code to recreate 47 // the key so long as it's running on the same computer. 48 // 49 // Note: on Windows it is possible to export this wrapped key off machine, but 50 // it must be sealed with an AEAD first. The wrapped key may contain machine 51 // identifiers and other values that you wouldn't want to export. Additionally 52 // |UnexportableKeyProvider::FromWrappedSigningKey| should not be presented 53 // attacked-controlled input and the AEAD would serve to authenticate the 54 // wrapped key. 55 virtual std::vector<uint8_t> GetWrappedKey() const = 0; 56 57 // SignSlowly returns a signature of |data|, or |nullopt| if an error occurs 58 // during signing. 59 // 60 // Note: this may take a second or more to run. 61 virtual std::optional<std::vector<uint8_t>> SignSlowly( 62 base::span<const uint8_t> data) = 0; 63 64 #if BUILDFLAG(IS_MAC) 65 // Returns the underlying reference to a Keychain key owned by the current 66 // instance. 67 virtual SecKeyRef GetSecKeyRef() const = 0; 68 #endif // BUILDFLAG(IS_MAC) 69 }; 70 71 // UnexportableKeyProvider creates |UnexportableSigningKey|s. 72 class CRYPTO_EXPORT UnexportableKeyProvider { 73 public: 74 virtual ~UnexportableKeyProvider(); 75 76 // Platform-specific configuration parameters for the provider. 77 struct Config { 78 #if BUILDFLAG(IS_MAC) 79 // Determines the level of user verification needed to sign with the key. 80 // https://developer.apple.com/documentation/security/secaccesscontrolcreateflags?language=objc 81 enum class AccessControl { 82 // No access control. User presence is not required to access this secret. 83 kNone, 84 85 // Either biometry or the local account password are required to access 86 // this secret. This is equivalent to kSecAccessControlUserPresence. 87 // Note that if you set this and choose not to pass an authenticated 88 // LAContext when signing, macOS will prompt the user for biometrics and 89 // the thread will block until that resolves. 90 kUserPresence, 91 }; 92 93 // The keychain access group the key is shared with. The binary must be 94 // codesigned with the corresponding entitlement. 95 // https://developer.apple.com/documentation/bundleresources/entitlements/keychain-access-groups?language=objc 96 // This must be set to a non empty value when using unexportable keys on 97 // macOS. 98 std::string keychain_access_group; 99 100 // An optional application tag that will be set for all keys created by this 101 // provider. If non empty, this should uniquely identify a group of related 102 // keys, and can be used to query or delete all credentials with the same 103 // tag. 104 // https://developer.apple.com/documentation/security/ksecattrapplicationtag?language=objc 105 std::string application_tag; 106 107 // The access control set for keys created by the provider. 108 AccessControl access_control = AccessControl::kNone; 109 #endif // BUILDFLAG(IS_MAC) 110 }; 111 112 // SelectAlgorithm returns which signature algorithm from 113 // |acceptable_algorithms| would be used if |acceptable_algorithms| was passed 114 // to |GenerateSigningKeySlowly|. 115 virtual std::optional<SignatureVerifier::SignatureAlgorithm> SelectAlgorithm( 116 base::span<const SignatureVerifier::SignatureAlgorithm> 117 acceptable_algorithms) = 0; 118 119 // GenerateSigningKeySlowly creates a new opaque signing key in hardware. The 120 // first supported value of |acceptable_algorithms| determines the type of the 121 // key. Returns nullptr if no supported hardware exists, if no value in 122 // |acceptable_algorithms| is supported, or if there was an error creating the 123 // key. 124 // 125 // Note: this may take one or two seconds to run. 126 virtual std::unique_ptr<UnexportableSigningKey> GenerateSigningKeySlowly( 127 base::span<const SignatureVerifier::SignatureAlgorithm> 128 acceptable_algorithms) = 0; 129 130 // FromWrappedSigningKey creates an |UnexportableSigningKey| from 131 // |wrapped_key|, which must have resulted from calling |GetWrappedKey| on a 132 // previous instance of |UnexportableSigningKey|. Returns nullptr if 133 // |wrapped_key| cannot be imported. 134 // 135 // Note: this may take up to a second. 136 // 137 // Note: do not call this with attacker-controlled data. The underlying 138 // interfaces to the secure hardware may not be robust. See |GetWrappedKey|. 139 virtual std::unique_ptr<UnexportableSigningKey> FromWrappedSigningKeySlowly( 140 base::span<const uint8_t> wrapped_key) = 0; 141 142 // Unexportable key implementations may be stateful. This is the case for 143 // macOS. |DeleteSigningKey| deletes all state associated with a given signing 144 // key on such implementations. For stateless implementations, this is a 145 // no-op. 146 // Returns true on successful deletion, false otherwise. 147 virtual bool DeleteSigningKey(base::span<const uint8_t> wrapped_key) = 0; 148 }; 149 150 // This is an experimental API as it uses an unofficial Windows API. 151 // The current implementation is here to gather metrics only. It should not be 152 // used outside of metrics gathering without knowledge of crypto OWNERS. 153 // 154 // UnexportableSigningKey provides a software-backed signing oracle based in a 155 // specialized virtual machine on platforms that support it. Current support is: 156 // Windows: RSA_PKCS1_SHA256 and ECDSA_SHA256. 157 // 158 // These keys differs from UnexportableSigningKey in several ways: 159 // - They are backed not by hardware, but by a specialized limited virtual 160 // machine resistant to attacks. 161 // - The latency of operations are expected to be about 100 times less, making 162 // them much more practical in cases that would otherwise disrupt the user 163 // experience. 164 // - The keys are stored in the virtual machine by name, this namespace is 165 // shared by all applications and there is a limited number of available keys 166 // (~65k from testing). 167 // 168 // For more info see: 169 // https://learn.microsoft.com/en-us/windows/security/identity-protection/credential-guard/credential-guard 170 class CRYPTO_EXPORT VirtualUnexportableSigningKey { 171 public: 172 virtual ~VirtualUnexportableSigningKey(); 173 174 // Algorithm returns the algorithm of the key in this object. 175 virtual SignatureVerifier::SignatureAlgorithm Algorithm() const = 0; 176 177 // GetSubjectPublicKeyInfo returns an SPKI that contains the public key of 178 // this object. 179 virtual std::vector<uint8_t> GetSubjectPublicKeyInfo() const = 0; 180 181 // GetKeyName may be used with a future instance of this code to recreate 182 // the key so long as it's running on the same computer. 183 // 184 // Note: All local applications can enumerate all keys on device and 185 // recreate them. Private keys can also be exported with the first HANDLE 186 // after creation. 187 virtual std::string GetKeyName() const = 0; 188 189 // Sign returns a signature of |data|, or |nullopt| if an error occurs 190 // during signing. 191 // 192 // Note: this is expected to be under 10ms. 193 virtual std::optional<std::vector<uint8_t>> Sign( 194 base::span<const uint8_t> data) = 0; 195 196 // Deletes the key from storage in the virtual machine. As the virtual machine 197 // has limited storage shared by all applications it is important to delete 198 // keys no longer in use. 199 virtual void DeleteKey() = 0; 200 }; 201 202 // VirtualUnexportableKeyProvider creates |VirtualUnexportableSigningKey|s. 203 class CRYPTO_EXPORT VirtualUnexportableKeyProvider { 204 public: 205 virtual ~VirtualUnexportableKeyProvider(); 206 207 // SelectAlgorithm returns which signature algorithm from 208 // |acceptable_algorithms| would be used if |acceptable_algorithms| was passed 209 // to |GenerateSigningKeySlowly|. 210 virtual std::optional<SignatureVerifier::SignatureAlgorithm> SelectAlgorithm( 211 base::span<const SignatureVerifier::SignatureAlgorithm> 212 acceptable_algorithms) = 0; 213 214 // GenerateSigningKey creates a new opaque signing key in a virtual machine. 215 // The first supported value of |acceptable_algorithms| determines the type of 216 // the key. Returns nullptr if it is not supported in the operating system, 217 // if no value in |acceptable_algorithms| is supported, or if there was an 218 // error creating the key. 219 // As the namespace is shared between all applications care should be taken to 220 // use a name that will not already be used by other applications. If a new 221 // key is created with the same name as a current key the creation will fail. 222 // Do not create a key with NULL or empty string as the name. 223 // 224 // Note: This may take milliseconds to run. 225 virtual std::unique_ptr<VirtualUnexportableSigningKey> GenerateSigningKey( 226 base::span<const SignatureVerifier::SignatureAlgorithm> 227 acceptable_algorithms, 228 std::string name) = 0; 229 230 // FromKeyName creates an |UnexportableSigningKey| from |name|, which is the 231 // name used to create the key. Returns nullptr if |name| cannot be imported. 232 // 233 // Note: This may take milliseconds to run. 234 virtual std::unique_ptr<VirtualUnexportableSigningKey> FromKeyName( 235 std::string name) = 0; 236 }; 237 238 // GetUnexportableKeyProvider returns an |UnexportableKeyProvider| 239 // for the current platform, or nullptr if there isn't one. This can be called 240 // from any thread but, in tests, but be sequenced with 241 // |SetUnexportableSigningKeyProvider|. 242 CRYPTO_EXPORT std::unique_ptr<UnexportableKeyProvider> 243 GetUnexportableKeyProvider(UnexportableKeyProvider::Config config); 244 245 // GetVirtualUnexportableKeyProvider_DO_NOT_USE_METRICS_ONLY returns a 246 // |VirtualUnexportableKeyProvider| for the current platform, or nullptr if 247 // there isn't one. This should currently only be used for metrics gathering. 248 CRYPTO_EXPORT std::unique_ptr<VirtualUnexportableKeyProvider> 249 GetVirtualUnexportableKeyProvider_DO_NOT_USE_METRICS_ONLY(); 250 251 // `GetSoftwareUnsecureUnexportableKeyProvider()` returns a mock software 252 // implementation of `UnexportableKeyProvider` that can be used on platforms 253 // that do not have a native secure implementation. 254 // This should be used for development purposes only since these keys are not 255 // backed by hardware and are not stored securely. 256 CRYPTO_EXPORT std::unique_ptr<UnexportableKeyProvider> 257 GetSoftwareUnsecureUnexportableKeyProvider(); 258 259 namespace internal { 260 261 CRYPTO_EXPORT void SetUnexportableKeyProviderForTesting( 262 std::unique_ptr<UnexportableKeyProvider> (*func)()); 263 264 } // namespace internal 265 266 } // namespace crypto 267 268 #endif // CRYPTO_UNEXPORTABLE_KEY_H_ 269