| // Copyright 2024 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef CRYPTO_USER_VERIFYING_KEY_H_ |
| #define CRYPTO_USER_VERIFYING_KEY_H_ |
| |
| #include <memory> |
| #include <optional> |
| #include <string> |
| #include <variant> |
| #include <vector> |
| |
| #include "base/containers/span.h" |
| #include "base/functional/callback.h" |
| #include "base/memory/ref_counted.h" |
| #include "build/build_config.h" |
| #include "crypto/crypto_export.h" |
| #include "crypto/scoped_lacontext.h" |
| #include "crypto/signature_verifier.h" |
| #include "crypto/unexportable_key.h" |
| |
| namespace crypto { |
| |
| typedef std::string UserVerifyingKeyLabel; |
| |
| // UserVerifyingSigningKey is a hardware-backed key that triggers a user |
| // verification by the platform before a signature will be provided. |
| // |
| // Notes: |
| // - This is currently only supported on Windows and Mac. |
| // - This does not export a wrapped key because the Windows implementation uses |
| // the WinRT KeyCredentialManager which addresses stored keys by name. |
| // - The interface for this class will likely need to be generalized as support |
| // for other platforms is added. |
| class CRYPTO_EXPORT UserVerifyingSigningKey { |
| public: |
| virtual ~UserVerifyingSigningKey(); |
| |
| // Sign invokes |callback| to provide a signature of |data|, or |nullopt| if |
| // an error occurs during signing. |
| virtual void Sign( |
| base::span<const uint8_t> data, |
| base::OnceCallback<void(std::optional<std::vector<uint8_t>>)> |
| callback) = 0; |
| |
| // Provides the SPKI public key. |
| virtual std::vector<uint8_t> GetPublicKey() const = 0; |
| |
| // Get a reference to the label used to create or retrieve this key. |
| virtual const UserVerifyingKeyLabel& GetKeyLabel() const = 0; |
| }; |
| |
| // Reference-counted wrapper for UserVeriyingSigningKey. |
| class CRYPTO_EXPORT RefCountedUserVerifyingSigningKey |
| : public base::RefCountedThreadSafe<RefCountedUserVerifyingSigningKey> { |
| public: |
| explicit RefCountedUserVerifyingSigningKey( |
| std::unique_ptr<crypto::UserVerifyingSigningKey> key); |
| |
| RefCountedUserVerifyingSigningKey(const RefCountedUserVerifyingSigningKey&) = |
| delete; |
| RefCountedUserVerifyingSigningKey& operator=( |
| const RefCountedUserVerifyingSigningKey&) = delete; |
| |
| crypto::UserVerifyingSigningKey& key() const { return *key_; } |
| |
| private: |
| friend class base::RefCountedThreadSafe<RefCountedUserVerifyingSigningKey>; |
| ~RefCountedUserVerifyingSigningKey(); |
| |
| const std::unique_ptr<crypto::UserVerifyingSigningKey> key_; |
| }; |
| |
| // UserVerifyingKeyProvider creates |UserVerifyingSigningKey|s. |
| class CRYPTO_EXPORT UserVerifyingKeyProvider { |
| public: |
| struct CRYPTO_EXPORT Config { |
| Config(); |
| Config(const Config& config) = delete; |
| Config& operator=(const Config& config) = delete; |
| Config(Config&& config); |
| Config& operator=(Config&& config); |
| ~Config(); |
| |
| #if BUILDFLAG(IS_MAC) |
| // The keychain access group the key is shared with. The binary must be |
| // codesigned with the corresponding entitlement. |
| // https://developer.apple.com/documentation/bundleresources/entitlements/keychain-access-groups?language=objc |
| // This must be set to a non empty value when using user verifying keys on |
| // macOS. |
| std::string keychain_access_group; |
| |
| // Optional LAContext to be used when retrieving and storing keys. Passing |
| // an authenticated LAContext lets you call UserVerifyingSigningKey::Sign() |
| // without triggering a macOS local authentication prompt. |
| std::optional<ScopedLAContext> lacontext; |
| #endif // BUILDFLAG(IS_MAC) |
| }; |
| |
| virtual ~UserVerifyingKeyProvider(); |
| |
| // Similar to |GenerateSigningKeySlowly| but the resulting signing key can |
| // only be used with a local user authentication by the platform. This can be |
| // called from any thread as the work is done asynchronously on a |
| // high-priority thread when the underlying platform is slow. |
| // Invokes |callback| with the resulting key, or nullptr on error. |
| virtual void GenerateUserVerifyingSigningKey( |
| base::span<const SignatureVerifier::SignatureAlgorithm> |
| acceptable_algorithms, |
| base::OnceCallback<void(std::unique_ptr<UserVerifyingSigningKey>)> |
| callback) = 0; |
| |
| // Similar to |FromWrappedSigningKey| but uses a wrapped key that was |
| // generated from |GenerateUserVerifyingSigningKey|. This can be called from |
| // any thread as the work is done asynchronously on a high-priority thread |
| // when the underlying platform is slow. |
| // Invokes |callback| with the resulting key, or nullptr on error. |
| virtual void GetUserVerifyingSigningKey( |
| UserVerifyingKeyLabel key_label, |
| base::OnceCallback<void(std::unique_ptr<UserVerifyingSigningKey>)> |
| callback) = 0; |
| |
| // Deletes a user verifying signing key. Work is be done asynchronously on a |
| // low-priority thread when the underlying platform is slow. |
| // Invokes |callback| with `true` if the key was found and deleted, `false` |
| // otherwise. |
| virtual void DeleteUserVerifyingKey( |
| UserVerifyingKeyLabel key_label, |
| base::OnceCallback<void(bool)> callback) = 0; |
| }; |
| |
| // GetUserVerifyingKeyProvider returns |UserVerifyingKeyProvider| for the |
| // current platform, or nullptr if this is not implemented on the current |
| // platform. |
| // Note that this will return non null if keys are supported but not available, |
| // i.e. if |AreUserVerifyingKeysSupported| returns false. In that case, |
| // operations would fail. |
| CRYPTO_EXPORT std::unique_ptr<UserVerifyingKeyProvider> |
| GetUserVerifyingKeyProvider(UserVerifyingKeyProvider::Config config); |
| |
| // Invokes the callback with true if UV keys can be used on the current |
| // platform, and false otherwise. `callback` can be invoked synchronously or |
| // asynchronously. |
| CRYPTO_EXPORT void AreUserVerifyingKeysSupported( |
| UserVerifyingKeyProvider::Config config, |
| base::OnceCallback<void(bool)> callback); |
| |
| namespace internal { |
| |
| CRYPTO_EXPORT void SetUserVerifyingKeyProviderForTesting( |
| std::unique_ptr<UserVerifyingKeyProvider> (*func)()); |
| |
| } // namespace internal |
| |
| } // namespace crypto |
| |
| #endif // CRYPTO_USER_VERIFYING_KEY_H_ |