1 // Copyright 2024 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_USER_VERIFYING_KEY_H_ 6 #define CRYPTO_USER_VERIFYING_KEY_H_ 7 8 #include <memory> 9 #include <optional> 10 #include <string> 11 #include <variant> 12 #include <vector> 13 14 #include "base/containers/span.h" 15 #include "base/functional/callback.h" 16 #include "base/memory/ref_counted.h" 17 #include "base/types/expected.h" 18 #include "build/build_config.h" 19 #include "crypto/crypto_export.h" 20 #include "crypto/scoped_lacontext.h" 21 #include "crypto/signature_verifier.h" 22 #include "crypto/unexportable_key.h" 23 24 namespace crypto { 25 26 typedef std::string UserVerifyingKeyLabel; 27 28 // Error values supplied to the callbacks for creating and retrieving 29 // user-verifying keys, upon failure. 30 enum class UserVerifyingKeyCreationError { 31 kPlatformApiError = 0, 32 kDuplicateCredential = 1, 33 kNotFound = 2, 34 kUserCancellation = 3, 35 kNoMatchingAlgorithm = 4, 36 kUnknownError = 5, 37 }; 38 39 // Error values supplied to the callback for signing with a user-verifying key, 40 // upon failure. 41 enum class UserVerifyingKeySigningError { 42 kPlatformApiError = 0, 43 kUserCancellation = 1, 44 kUnknownError = 2, 45 }; 46 47 // UserVerifyingSigningKey is a hardware-backed key that triggers a user 48 // verification by the platform before a signature will be provided. 49 // 50 // Notes: 51 // - This is currently only supported on Windows and Mac. 52 // - This does not export a wrapped key because the Windows implementation uses 53 // the WinRT KeyCredentialManager which addresses stored keys by name. 54 // - The interface for this class will likely need to be generalized as support 55 // for other platforms is added. 56 class CRYPTO_EXPORT UserVerifyingSigningKey { 57 public: 58 virtual ~UserVerifyingSigningKey(); 59 using UserVerifyingKeySignatureCallback = base::OnceCallback<void( 60 base::expected<std::vector<uint8_t>, UserVerifyingKeySigningError>)>; 61 62 // Sign invokes |callback| to provide a signature of |data|, or |nullopt| if 63 // an error occurs during signing. 64 virtual void Sign(base::span<const uint8_t> data, 65 UserVerifyingKeySignatureCallback callback) = 0; 66 67 // Provides the SPKI public key. 68 virtual std::vector<uint8_t> GetPublicKey() const = 0; 69 70 // Get a reference to the label used to create or retrieve this key. 71 virtual const UserVerifyingKeyLabel& GetKeyLabel() const = 0; 72 73 // Returns true if the underlying key is stored in "hardware". Something like 74 // ARM TrustZone would count as hardware for these purposes. 75 virtual bool IsHardwareBacked() const; 76 }; 77 78 // Reference-counted wrapper for UserVeriyingSigningKey. 79 class CRYPTO_EXPORT RefCountedUserVerifyingSigningKey 80 : public base::RefCountedThreadSafe<RefCountedUserVerifyingSigningKey> { 81 public: 82 explicit RefCountedUserVerifyingSigningKey( 83 std::unique_ptr<crypto::UserVerifyingSigningKey> key); 84 85 RefCountedUserVerifyingSigningKey(const RefCountedUserVerifyingSigningKey&) = 86 delete; 87 RefCountedUserVerifyingSigningKey& operator=( 88 const RefCountedUserVerifyingSigningKey&) = delete; 89 key()90 crypto::UserVerifyingSigningKey& key() const { return *key_; } 91 92 private: 93 friend class base::RefCountedThreadSafe<RefCountedUserVerifyingSigningKey>; 94 ~RefCountedUserVerifyingSigningKey(); 95 96 const std::unique_ptr<crypto::UserVerifyingSigningKey> key_; 97 }; 98 99 // UserVerifyingKeyProvider creates |UserVerifyingSigningKey|s. 100 class CRYPTO_EXPORT UserVerifyingKeyProvider { 101 public: 102 struct CRYPTO_EXPORT Config { 103 Config(); 104 Config(const Config& config) = delete; 105 Config& operator=(const Config& config) = delete; 106 Config(Config&& config); 107 Config& operator=(Config&& config); 108 ~Config(); 109 110 #if BUILDFLAG(IS_MAC) 111 // The keychain access group the key is shared with. The binary must be 112 // codesigned with the corresponding entitlement. 113 // https://developer.apple.com/documentation/bundleresources/entitlements/keychain-access-groups?language=objc 114 // This must be set to a non empty value when using user verifying keys on 115 // macOS. 116 std::string keychain_access_group; 117 118 // Optional LAContext to be used when retrieving and storing keys. Passing 119 // an authenticated LAContext lets you call UserVerifyingSigningKey::Sign() 120 // without triggering a macOS local authentication prompt. 121 std::optional<ScopedLAContext> lacontext; 122 #endif // BUILDFLAG(IS_MAC) 123 }; 124 125 using UserVerifyingKeyCreationCallback = base::OnceCallback<void( 126 base::expected<std::unique_ptr<UserVerifyingSigningKey>, 127 UserVerifyingKeyCreationError>)>; 128 129 virtual ~UserVerifyingKeyProvider(); 130 131 // Similar to |GenerateSigningKeySlowly| but the resulting signing key can 132 // only be used with a local user authentication by the platform. This can be 133 // called from any thread as the work is done asynchronously on a 134 // high-priority thread when the underlying platform is slow. 135 // Invokes |callback| with the resulting key, or nullptr on error. 136 virtual void GenerateUserVerifyingSigningKey( 137 base::span<const SignatureVerifier::SignatureAlgorithm> 138 acceptable_algorithms, 139 UserVerifyingKeyCreationCallback callback) = 0; 140 141 // Similar to |FromWrappedSigningKey| but uses a wrapped key that was 142 // generated from |GenerateUserVerifyingSigningKey|. This can be called from 143 // any thread as the work is done asynchronously on a high-priority thread 144 // when the underlying platform is slow. 145 // Invokes |callback| with the resulting key, or nullptr on error. 146 virtual void GetUserVerifyingSigningKey( 147 UserVerifyingKeyLabel key_label, 148 UserVerifyingKeyCreationCallback callback) = 0; 149 150 // Deletes a user verifying signing key. Work is be done asynchronously on a 151 // low-priority thread when the underlying platform is slow. 152 // Invokes |callback| with `true` if the key was found and deleted, `false` 153 // otherwise. 154 virtual void DeleteUserVerifyingKey( 155 UserVerifyingKeyLabel key_label, 156 base::OnceCallback<void(bool)> callback) = 0; 157 }; 158 159 // GetUserVerifyingKeyProvider returns |UserVerifyingKeyProvider| for the 160 // current platform, or nullptr if this is not implemented on the current 161 // platform. 162 // Note that this will return non null if keys are supported but not available, 163 // i.e. if |AreUserVerifyingKeysSupported| returns false. In that case, 164 // operations would fail. 165 CRYPTO_EXPORT std::unique_ptr<UserVerifyingKeyProvider> 166 GetUserVerifyingKeyProvider(UserVerifyingKeyProvider::Config config); 167 168 // Invokes the callback with true if UV keys can be used on the current 169 // platform, and false otherwise. `callback` can be invoked synchronously or 170 // asynchronously. 171 CRYPTO_EXPORT void AreUserVerifyingKeysSupported( 172 UserVerifyingKeyProvider::Config config, 173 base::OnceCallback<void(bool)> callback); 174 175 namespace internal { 176 177 CRYPTO_EXPORT void SetUserVerifyingKeyProviderForTesting( 178 std::unique_ptr<UserVerifyingKeyProvider> (*func)()); 179 180 } // namespace internal 181 182 } // namespace crypto 183 184 #endif // CRYPTO_USER_VERIFYING_KEY_H_ 185