| // Copyright (c) 2021 The Chromium Authors. All rights reserved. |
| // 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(); |
| |
| #if BUILDFLAG(IS_WIN) |
| // MeasureTPMAvailability records UMA metrics of TPM availability. |
| CRYPTO_EXPORT void MeasureTPMAvailabilityWin(); |
| #endif // BUILDFLAG(IS_WIN) |
| |
| namespace internal { |
| |
| CRYPTO_EXPORT void SetUnexportableKeyProviderForTesting( |
| std::unique_ptr<UnexportableKeyProvider> (*func)()); |
| |
| } // namespace internal |
| |
| } // namespace crypto |
| |
| #endif // CRYPTO_UNEXPORTABLE_KEY_H_ |