// Copyright 2021 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_UNEXPORTABLE_KEY_H_ #define CRYPTO_UNEXPORTABLE_KEY_H_ #include <memory> #include "crypto/crypto_export.h" #include "crypto/signature_verifier.h" #include "third_party/abseil-cpp/absl/types/optional.h" namespace crypto { // UnexportableSigningKey provides a hardware-backed signing oracle on platforms // that support it. Current support is: // Windows: RSA_PKCS1_SHA256 via TPM 1.2+ and ECDSA_SHA256 via TPM 2.0. // Tests: ECDSA_SHA256 via ScopedMockUnexportableSigningKeyForTesting. class CRYPTO_EXPORT UnexportableSigningKey { public: virtual ~UnexportableSigningKey(); // Algorithm returns the algorithm of the key in this object. virtual SignatureVerifier::SignatureAlgorithm Algorithm() const = 0; // GetSubjectPublicKeyInfo returns an SPKI that contains the public key of // this object. virtual std::vector<uint8_t> GetSubjectPublicKeyInfo() const = 0; // GetWrappedKey returns the encrypted private key of this object. It is // encrypted to a key that is kept in hardware and the unencrypted private // key never exists in the CPU's memory. // // A wrapped key may be used with a future instance of this code to recreate // the key so long as it's running on the same computer. // // Note: it is possible to export this wrapped key off machine, but it must be // sealed with an AEAD first. The wrapped key may contain machine identifiers // and other values that you wouldn't want to export. Additionally // |UnexportableKeyProvider::FromWrappedSigningKey| should not be presented // attacked-controlled input and the AEAD would serve to authenticate the // wrapped key. virtual std::vector<uint8_t> GetWrappedKey() const = 0; // SignSlowly returns a signature of |data|, or |nullopt| if an error occurs // during signing. // // Note: this may take a second or more to run. virtual absl::optional<std::vector<uint8_t>> SignSlowly( base::span<const uint8_t> data) = 0; }; // UnexportableKeyProvider creates |UnexportableSigningKey|s. class CRYPTO_EXPORT UnexportableKeyProvider { public: virtual ~UnexportableKeyProvider(); // SelectAlgorithm returns which signature algorithm from // |acceptable_algorithms| would be used if |acceptable_algorithms| was passed // to |GenerateSigningKeySlowly|. virtual absl::optional<SignatureVerifier::SignatureAlgorithm> SelectAlgorithm( base::span<const SignatureVerifier::SignatureAlgorithm> acceptable_algorithms) = 0; // GenerateSigningKeySlowly creates a new opaque signing key in hardware. The // first supported value of |acceptable_algorithms| determines the type of the // key. Returns nullptr if no supported hardware exists, if no value in // |acceptable_algorithms| is supported, or if there was an error creating the // key. // // Note: this may take one or two seconds to run. virtual std::unique_ptr<UnexportableSigningKey> GenerateSigningKeySlowly( base::span<const SignatureVerifier::SignatureAlgorithm> acceptable_algorithms) = 0; // FromWrappedSigningKey creates an |UnexportableSigningKey| from // |wrapped_key|, which must have resulted from calling |GetWrappedKey| on a // previous instance of |UnexportableSigningKey|. Returns nullptr if // |wrapped_key| cannot be imported. // // Note: this may take up to a second. // // Note: do not call this with attacker-controlled data. The underlying // interfaces to the secure hardware may not be robust. See |GetWrappedKey|. virtual std::unique_ptr<UnexportableSigningKey> FromWrappedSigningKeySlowly( base::span<const uint8_t> wrapped_key) = 0; }; // GetUnexportableKeyProvider returns an |UnexportableKeyProvider| // for the current platform, or nullptr if there isn't one. This can be called // from any thread but, in tests, but be sequenced with // |SetUnexportableSigningKeyProvider|. CRYPTO_EXPORT std::unique_ptr<UnexportableKeyProvider> GetUnexportableKeyProvider(); namespace internal { CRYPTO_EXPORT void SetUnexportableKeyProviderForTesting( std::unique_ptr<UnexportableKeyProvider> (*func)()); } // namespace internal } // namespace crypto #endif // CRYPTO_UNEXPORTABLE_KEY_H_