• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2021 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_UNEXPORTABLE_KEY_H_
6 #define CRYPTO_UNEXPORTABLE_KEY_H_
7 
8 #include <memory>
9 
10 #include "crypto/crypto_export.h"
11 #include "crypto/signature_verifier.h"
12 #include "third_party/abseil-cpp/absl/types/optional.h"
13 
14 namespace crypto {
15 
16 // UnexportableSigningKey provides a hardware-backed signing oracle on platforms
17 // that support it. Current support is:
18 //   Windows: RSA_PKCS1_SHA256 via TPM 1.2+ and ECDSA_SHA256 via TPM 2.0.
19 //   Tests: ECDSA_SHA256 via ScopedMockUnexportableSigningKeyForTesting.
20 //
21 // See also //components/unexportable_keys for a higher-level key management
22 // API.
23 class CRYPTO_EXPORT UnexportableSigningKey {
24  public:
25   virtual ~UnexportableSigningKey();
26 
27   // Algorithm returns the algorithm of the key in this object.
28   virtual SignatureVerifier::SignatureAlgorithm Algorithm() const = 0;
29 
30   // GetSubjectPublicKeyInfo returns an SPKI that contains the public key of
31   // this object.
32   virtual std::vector<uint8_t> GetSubjectPublicKeyInfo() const = 0;
33 
34   // GetWrappedKey returns the encrypted private key of this object. It is
35   // encrypted to a key that is kept in hardware and the unencrypted private
36   // key never exists in the CPU's memory.
37   //
38   // A wrapped key may be used with a future instance of this code to recreate
39   // the key so long as it's running on the same computer.
40   //
41   // Note: it is possible to export this wrapped key off machine, but it must be
42   // sealed with an AEAD first. The wrapped key may contain machine identifiers
43   // and other values that you wouldn't want to export. Additionally
44   // |UnexportableKeyProvider::FromWrappedSigningKey| should not be presented
45   // attacked-controlled input and the AEAD would serve to authenticate the
46   // wrapped key.
47   virtual std::vector<uint8_t> GetWrappedKey() const = 0;
48 
49   // SignSlowly returns a signature of |data|, or |nullopt| if an error occurs
50   // during signing.
51   //
52   // Note: this may take a second or more to run.
53   virtual absl::optional<std::vector<uint8_t>> SignSlowly(
54       base::span<const uint8_t> data) = 0;
55 };
56 
57 // UnexportableKeyProvider creates |UnexportableSigningKey|s.
58 class CRYPTO_EXPORT UnexportableKeyProvider {
59  public:
60   virtual ~UnexportableKeyProvider();
61 
62   // SelectAlgorithm returns which signature algorithm from
63   // |acceptable_algorithms| would be used if |acceptable_algorithms| was passed
64   // to |GenerateSigningKeySlowly|.
65   virtual absl::optional<SignatureVerifier::SignatureAlgorithm> SelectAlgorithm(
66       base::span<const SignatureVerifier::SignatureAlgorithm>
67           acceptable_algorithms) = 0;
68 
69   // GenerateSigningKeySlowly creates a new opaque signing key in hardware. The
70   // first supported value of |acceptable_algorithms| determines the type of the
71   // key. Returns nullptr if no supported hardware exists, if no value in
72   // |acceptable_algorithms| is supported, or if there was an error creating the
73   // key.
74   //
75   // Note: this may take one or two seconds to run.
76   virtual std::unique_ptr<UnexportableSigningKey> GenerateSigningKeySlowly(
77       base::span<const SignatureVerifier::SignatureAlgorithm>
78           acceptable_algorithms) = 0;
79 
80   // FromWrappedSigningKey creates an |UnexportableSigningKey| from
81   // |wrapped_key|, which must have resulted from calling |GetWrappedKey| on a
82   // previous instance of |UnexportableSigningKey|. Returns nullptr if
83   // |wrapped_key| cannot be imported.
84   //
85   // Note: this may take up to a second.
86   //
87   // Note: do not call this with attacker-controlled data. The underlying
88   // interfaces to the secure hardware may not be robust. See |GetWrappedKey|.
89   virtual std::unique_ptr<UnexportableSigningKey> FromWrappedSigningKeySlowly(
90       base::span<const uint8_t> wrapped_key) = 0;
91 };
92 
93 // This is an experimental API as it uses an unofficial Windows API.
94 // The current implementation is here to gather metrics only. It should not be
95 // used outside of metrics gathering without knowledge of crypto OWNERS.
96 //
97 // UnexportableSigningKey provides a software-backed signing oracle based in a
98 // specialized virtual machine on platforms that support it. Current support is:
99 //   Windows: RSA_PKCS1_SHA256 and ECDSA_SHA256.
100 //
101 // These keys differs from UnexportableSigningKey in several ways:
102 // - They are backed not by hardware, but by a specialized limited virtual
103 // machine resistant to attacks.
104 // - The latency of operations are expected to be about 100 times less, making
105 // them much more practical in cases that would otherwise disrupt the user
106 // experience.
107 // - The keys are stored in the virtual machine by name, this namespace is
108 // shared by all applications and there is a limited number of available keys
109 // (~65k from testing).
110 //
111 // For more info see:
112 // https://learn.microsoft.com/en-us/windows/security/identity-protection/credential-guard/credential-guard
113 class CRYPTO_EXPORT VirtualUnexportableSigningKey {
114  public:
115   virtual ~VirtualUnexportableSigningKey();
116 
117   // Algorithm returns the algorithm of the key in this object.
118   virtual SignatureVerifier::SignatureAlgorithm Algorithm() const = 0;
119 
120   // GetSubjectPublicKeyInfo returns an SPKI that contains the public key of
121   // this object.
122   virtual std::vector<uint8_t> GetSubjectPublicKeyInfo() const = 0;
123 
124   // GetKeyName may be used with a future instance of this code to recreate
125   // the key so long as it's running on the same computer.
126   //
127   // Note: All local applications can enumerate all keys on device and
128   // recreate them. Private keys can also be exported with the first HANDLE
129   // after creation.
130   virtual std::string GetKeyName() const = 0;
131 
132   // Sign returns a signature of |data|, or |nullopt| if an error occurs
133   // during signing.
134   //
135   // Note: this is expected to be under 10ms.
136   virtual absl::optional<std::vector<uint8_t>> Sign(
137       base::span<const uint8_t> data) = 0;
138 
139   // Deletes the key from storage in the virtual machine. As the virtual machine
140   // has limited storage shared by all applications it is important to delete
141   // keys no longer in use.
142   virtual bool DeleteKey() = 0;
143 };
144 
145 // VirtualUnexportableKeyProvider creates |VirtualUnexportableSigningKey|s.
146 class CRYPTO_EXPORT VirtualUnexportableKeyProvider {
147  public:
148   virtual ~VirtualUnexportableKeyProvider();
149 
150   // SelectAlgorithm returns which signature algorithm from
151   // |acceptable_algorithms| would be used if |acceptable_algorithms| was passed
152   // to |GenerateSigningKeySlowly|.
153   virtual absl::optional<SignatureVerifier::SignatureAlgorithm> SelectAlgorithm(
154       base::span<const SignatureVerifier::SignatureAlgorithm>
155           acceptable_algorithms) = 0;
156 
157   // GenerateSigningKey creates a new opaque signing key in a virtual machine.
158   // The first supported value of |acceptable_algorithms| determines the type of
159   // the key. Returns nullptr if it is not supported in the operating system,
160   // if no value in |acceptable_algorithms| is supported, or if there was an
161   // error creating the key.
162   // As the namespace is shared between all applications care should be taken to
163   // use a name that will not already be used by other applications. If a new
164   // key is created with the same name as a current key the creation will fail.
165   // Do not create a key with NULL or empty string as the name.
166   //
167   // Note: This may take milliseconds to run.
168   virtual std::unique_ptr<VirtualUnexportableSigningKey> GenerateSigningKey(
169       base::span<const SignatureVerifier::SignatureAlgorithm>
170           acceptable_algorithms,
171       std::string name) = 0;
172 
173   // FromKeyName creates an |UnexportableSigningKey| from |name|, which is the
174   // name used to create the key. Returns nullptr if |name| cannot be imported.
175   //
176   // Note: This may take milliseconds to run.
177   virtual std::unique_ptr<VirtualUnexportableSigningKey> FromKeyName(
178       std::string name) = 0;
179 };
180 
181 // GetUnexportableKeyProvider returns an |UnexportableKeyProvider|
182 // for the current platform, or nullptr if there isn't one. This can be called
183 // from any thread but, in tests, but be sequenced with
184 // |SetUnexportableSigningKeyProvider|.
185 CRYPTO_EXPORT std::unique_ptr<UnexportableKeyProvider>
186 GetUnexportableKeyProvider();
187 
188 // GetVirtualUnexportableKeyProvider_DO_NOT_USE_METRICS_ONLY returns a
189 // |VirtualUnexportableKeyProvider| for the current platform, or nullptr if
190 // there isn't one. This should currently only be used for metrics gathering.
191 CRYPTO_EXPORT std::unique_ptr<VirtualUnexportableKeyProvider>
192 GetVirtualUnexportableKeyProvider_DO_NOT_USE_METRICS_ONLY();
193 
194 namespace internal {
195 
196 CRYPTO_EXPORT void SetUnexportableKeyProviderForTesting(
197     std::unique_ptr<UnexportableKeyProvider> (*func)());
198 
199 }  // namespace internal
200 
201 }  // namespace crypto
202 
203 #endif  // CRYPTO_UNEXPORTABLE_KEY_H_
204