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