• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2015 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 #ifdef UNSAFE_BUFFERS_BUILD
6 // TODO(crbug.com/40284755): Remove this and spanify to fix the errors.
7 #pragma allow_unsafe_buffers
8 #endif
9 
10 #include "net/ssl/ssl_platform_key_win.h"
11 
12 #include <memory>
13 #include <string>
14 #include <utility>
15 #include <vector>
16 
17 #include "base/logging.h"
18 #include "base/ranges/algorithm.h"
19 #include "base/strings/utf_string_conversions.h"
20 #include "crypto/openssl_util.h"
21 #include "crypto/scoped_capi_types.h"
22 #include "crypto/scoped_cng_types.h"
23 #include "crypto/unexportable_key_win.h"
24 #include "net/base/net_errors.h"
25 #include "net/cert/x509_certificate.h"
26 #include "net/ssl/ssl_platform_key_util.h"
27 #include "net/ssl/ssl_private_key.h"
28 #include "net/ssl/threaded_ssl_private_key.h"
29 #include "third_party/boringssl/src/include/openssl/bn.h"
30 #include "third_party/boringssl/src/include/openssl/ecdsa.h"
31 #include "third_party/boringssl/src/include/openssl/evp.h"
32 #include "third_party/boringssl/src/include/openssl/ssl.h"
33 
34 namespace net {
35 
36 namespace {
37 
ProbeSHA256(ThreadedSSLPrivateKey::Delegate * delegate)38 bool ProbeSHA256(ThreadedSSLPrivateKey::Delegate* delegate) {
39   // This input is chosen to avoid colliding with other signing inputs used in
40   // TLS 1.2 or TLS 1.3. We use the construct in RFC 8446, section 4.4.3, but
41   // change the context string. The context string ensures we don't collide with
42   // TLS 1.3 and any future version. The 0x20 (space) prefix ensures we don't
43   // collide with TLS 1.2 ServerKeyExchange or CertificateVerify.
44   static const uint8_t kSHA256ProbeInput[] = {
45       0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
46       0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
47       0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
48       0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
49       0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
50       0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 'C',  'h',
51       'r',  'o',  'm',  'i',  'u',  'm',  ',',  ' ',  'S',  'H',  'A',
52       '2',  ' ',  'P',  'r',  'o',  'b',  'e',  0x00,
53   };
54   std::vector<uint8_t> signature;
55   return delegate->Sign(SSL_SIGN_RSA_PKCS1_SHA256, kSHA256ProbeInput,
56                         &signature) == OK;
57 }
58 
GetCAPIProviderName(HCRYPTPROV provider)59 std::string GetCAPIProviderName(HCRYPTPROV provider) {
60   DWORD name_len;
61   if (!CryptGetProvParam(provider, PP_NAME, nullptr, &name_len, 0)) {
62     return "(error getting name)";
63   }
64   std::vector<BYTE> name(name_len);
65   if (!CryptGetProvParam(provider, PP_NAME, name.data(), &name_len, 0)) {
66     return "(error getting name)";
67   }
68   // Per Microsoft's documentation, PP_NAME is NUL-terminated. However,
69   // smartcard drivers are notoriously buggy, so check this.
70   auto nul = base::ranges::find(name, 0);
71   if (nul != name.end()) {
72     name_len = nul - name.begin();
73   }
74   return std::string(reinterpret_cast<const char*>(name.data()), name_len);
75 }
76 
77 class SSLPlatformKeyCAPI : public ThreadedSSLPrivateKey::Delegate {
78  public:
79   // Takes ownership of |provider|.
SSLPlatformKeyCAPI(crypto::ScopedHCRYPTPROV provider,DWORD key_spec)80   SSLPlatformKeyCAPI(crypto::ScopedHCRYPTPROV provider, DWORD key_spec)
81       : provider_name_(GetCAPIProviderName(provider.get())),
82         provider_(std::move(provider)),
83         key_spec_(key_spec) {
84     // Check for SHA-256 support. The CAPI service provider may only be able to
85     // sign pre-TLS-1.2 and SHA-1 hashes. If SHA-256 doesn't work, prioritize
86     // SHA-1 as a workaround. See https://crbug.com/278370.
87     prefer_sha1_ = !ProbeSHA256(this);
88   }
89 
90   SSLPlatformKeyCAPI(const SSLPlatformKeyCAPI&) = delete;
91   SSLPlatformKeyCAPI& operator=(const SSLPlatformKeyCAPI&) = delete;
92 
93   ~SSLPlatformKeyCAPI() override = default;
94 
GetProviderName()95   std::string GetProviderName() override { return "CAPI: " + provider_name_; }
96 
GetAlgorithmPreferences()97   std::vector<uint16_t> GetAlgorithmPreferences() override {
98     if (prefer_sha1_) {
99       return {SSL_SIGN_RSA_PKCS1_SHA1, SSL_SIGN_RSA_PKCS1_SHA256,
100               SSL_SIGN_RSA_PKCS1_SHA384, SSL_SIGN_RSA_PKCS1_SHA512};
101     }
102     return {SSL_SIGN_RSA_PKCS1_SHA256, SSL_SIGN_RSA_PKCS1_SHA384,
103             SSL_SIGN_RSA_PKCS1_SHA512, SSL_SIGN_RSA_PKCS1_SHA1};
104   }
105 
Sign(uint16_t algorithm,base::span<const uint8_t> input,std::vector<uint8_t> * signature)106   Error Sign(uint16_t algorithm,
107              base::span<const uint8_t> input,
108              std::vector<uint8_t>* signature) override {
109     const EVP_MD* md = SSL_get_signature_algorithm_digest(algorithm);
110     uint8_t digest[EVP_MAX_MD_SIZE];
111     unsigned digest_len;
112     if (!md || !EVP_Digest(input.data(), input.size(), digest, &digest_len, md,
113                            nullptr)) {
114       return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED;
115     }
116 
117     ALG_ID hash_alg;
118     switch (EVP_MD_type(md)) {
119       case NID_md5_sha1:
120         hash_alg = CALG_SSL3_SHAMD5;
121         break;
122       case NID_sha1:
123         hash_alg = CALG_SHA1;
124         break;
125       case NID_sha256:
126         hash_alg = CALG_SHA_256;
127         break;
128       case NID_sha384:
129         hash_alg = CALG_SHA_384;
130         break;
131       case NID_sha512:
132         hash_alg = CALG_SHA_512;
133         break;
134       default:
135         NOTREACHED();
136     }
137 
138     crypto::ScopedHCRYPTHASH hash_handle;
139     if (!CryptCreateHash(
140             provider_.get(), hash_alg, 0, 0,
141             crypto::ScopedHCRYPTHASH::Receiver(hash_handle).get())) {
142       PLOG(ERROR) << "CreateCreateHash failed";
143       return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED;
144     }
145     DWORD hash_len;
146     DWORD arg_len = sizeof(hash_len);
147     if (!CryptGetHashParam(hash_handle.get(), HP_HASHSIZE,
148                            reinterpret_cast<BYTE*>(&hash_len), &arg_len, 0)) {
149       PLOG(ERROR) << "CryptGetHashParam HP_HASHSIZE failed";
150       return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED;
151     }
152     if (hash_len != digest_len)
153       return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED;
154     if (!CryptSetHashParam(hash_handle.get(), HP_HASHVAL,
155                            const_cast<BYTE*>(digest), 0)) {
156       PLOG(ERROR) << "CryptSetHashParam HP_HASHVAL failed";
157       return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED;
158     }
159     DWORD signature_len = 0;
160     if (!CryptSignHash(hash_handle.get(), key_spec_, nullptr, 0, nullptr,
161                        &signature_len)) {
162       PLOG(ERROR) << "CryptSignHash failed";
163       return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED;
164     }
165     signature->resize(signature_len);
166     if (!CryptSignHash(hash_handle.get(), key_spec_, nullptr, 0,
167                        signature->data(), &signature_len)) {
168       PLOG(ERROR) << "CryptSignHash failed";
169       return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED;
170     }
171     signature->resize(signature_len);
172 
173     // CryptoAPI signs in little-endian, so reverse it.
174     std::reverse(signature->begin(), signature->end());
175     return OK;
176   }
177 
178  private:
179   std::string provider_name_;
180   crypto::ScopedHCRYPTPROV provider_;
181   DWORD key_spec_;
182   bool prefer_sha1_ = false;
183 };
184 
GetCNGProviderName(NCRYPT_KEY_HANDLE key)185 std::wstring GetCNGProviderName(NCRYPT_KEY_HANDLE key) {
186   crypto::ScopedNCryptProvider prov;
187   DWORD prov_len = 0;
188   SECURITY_STATUS status = NCryptGetProperty(
189       key, NCRYPT_PROVIDER_HANDLE_PROPERTY,
190       reinterpret_cast<BYTE*>(
191           crypto::ScopedNCryptProvider::Receiver(prov).get()),
192       sizeof(NCRYPT_PROV_HANDLE), &prov_len, NCRYPT_SILENT_FLAG);
193   if (FAILED(status)) {
194     return L"(error getting provider)";
195   }
196   DCHECK_EQ(sizeof(NCRYPT_PROV_HANDLE), prov_len);
197 
198   // NCRYPT_NAME_PROPERTY is a NUL-terminated Unicode string, which means an
199   // array of wchar_t, however NCryptGetProperty works in bytes, so lengths must
200   // be converted.
201   DWORD name_len = 0;
202   status = NCryptGetProperty(prov.get(), NCRYPT_NAME_PROPERTY, nullptr, 0,
203                              &name_len, NCRYPT_SILENT_FLAG);
204   if (FAILED(status) || name_len % sizeof(wchar_t) != 0) {
205     return L"(error getting provider name)";
206   }
207   std::vector<wchar_t> name;
208   name.reserve(name_len / sizeof(wchar_t));
209   status = NCryptGetProperty(
210       prov.get(), NCRYPT_NAME_PROPERTY, reinterpret_cast<BYTE*>(name.data()),
211       name.size() * sizeof(wchar_t), &name_len, NCRYPT_SILENT_FLAG);
212   if (FAILED(status)) {
213     return L"(error getting provider name)";
214   }
215   name.resize(name_len / sizeof(wchar_t));
216 
217   // Per Microsoft's documentation, the name is NUL-terminated. However,
218   // smartcard drivers are notoriously buggy, so check this.
219   auto nul = base::ranges::find(name, 0);
220   if (nul != name.end()) {
221     name.erase(nul, name.end());
222   }
223   return std::wstring(name.begin(), name.end());
224 }
225 
226 class SSLPlatformKeyCNG : public ThreadedSSLPrivateKey::Delegate {
227  public:
228   // Takes ownership of |key|.
SSLPlatformKeyCNG(crypto::ScopedNCryptKey key,int type,size_t max_length)229   SSLPlatformKeyCNG(crypto::ScopedNCryptKey key, int type, size_t max_length)
230       : provider_name_(GetCNGProviderName(key.get())),
231         key_(std::move(key)),
232         type_(type),
233         max_length_(max_length) {
234     // If this is a 1024-bit RSA key or below, check for SHA-256 support. Older
235     // Estonian ID cards can only sign SHA-1 hashes. If SHA-256 does not work,
236     // prioritize SHA-1 as a workaround. See https://crbug.com/278370.
237     prefer_sha1_ =
238         type_ == EVP_PKEY_RSA && max_length_ <= 1024 / 8 && !ProbeSHA256(this);
239   }
240 
241   SSLPlatformKeyCNG(const SSLPlatformKeyCNG&) = delete;
242   SSLPlatformKeyCNG& operator=(const SSLPlatformKeyCNG&) = delete;
243 
GetProviderName()244   std::string GetProviderName() override {
245     return "CNG: " + base::WideToUTF8(provider_name_);
246   }
247 
GetAlgorithmPreferences()248   std::vector<uint16_t> GetAlgorithmPreferences() override {
249     // Per TLS 1.3 (RFC 8446), the RSA-PSS code points in TLS correspond to
250     // RSA-PSS with salt length equal to the digest length. TPM 2.0's
251     // TPM_ALG_RSAPSS algorithm, however, uses the maximum possible salt length.
252     // The TPM provider will fail signing requests for other salt lengths and
253     // thus cannot generate TLS-compatible PSS signatures.
254     //
255     // However, as of TPM revision 1.16, TPMs which follow FIPS 186-4 will
256     // instead interpret TPM_ALG_RSAPSS using salt length equal to the digest
257     // length. Those TPMs can generate TLS-compatible PSS signatures. As a
258     // result, if this is a TPM-based key, we only report PSS as supported if
259     // the salt length will match the digest length.
260     bool supports_pss = true;
261     if (provider_name_ == MS_PLATFORM_KEY_STORAGE_PROVIDER) {
262       DWORD salt_size = 0;
263       DWORD size_of_salt_size = sizeof(salt_size);
264       HRESULT status =
265           NCryptGetProperty(key_.get(), NCRYPT_PCP_PSS_SALT_SIZE_PROPERTY,
266                             reinterpret_cast<PBYTE>(&salt_size),
267                             size_of_salt_size, &size_of_salt_size, 0);
268       if (FAILED(status) || salt_size != NCRYPT_TPM_PSS_SALT_SIZE_HASHSIZE) {
269         supports_pss = false;
270       }
271     }
272     if (prefer_sha1_) {
273       std::vector<uint16_t> ret = {
274           SSL_SIGN_RSA_PKCS1_SHA1,
275           SSL_SIGN_RSA_PKCS1_SHA256,
276           SSL_SIGN_RSA_PKCS1_SHA384,
277           SSL_SIGN_RSA_PKCS1_SHA512,
278       };
279       if (supports_pss) {
280         ret.push_back(SSL_SIGN_RSA_PSS_SHA256);
281         ret.push_back(SSL_SIGN_RSA_PSS_SHA384);
282         ret.push_back(SSL_SIGN_RSA_PSS_SHA512);
283       }
284       return ret;
285     }
286     return SSLPrivateKey::DefaultAlgorithmPreferences(type_, supports_pss);
287   }
288 
Sign(uint16_t algorithm,base::span<const uint8_t> input,std::vector<uint8_t> * signature)289   Error Sign(uint16_t algorithm,
290              base::span<const uint8_t> input,
291              std::vector<uint8_t>* signature) override {
292     crypto::OpenSSLErrStackTracer tracer(FROM_HERE);
293 
294     const EVP_MD* md = SSL_get_signature_algorithm_digest(algorithm);
295     uint8_t digest[EVP_MAX_MD_SIZE];
296     unsigned digest_len;
297     if (!md || !EVP_Digest(input.data(), input.size(), digest, &digest_len, md,
298                            nullptr)) {
299       return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED;
300     }
301 
302     BCRYPT_PKCS1_PADDING_INFO pkcs1_padding_info = {nullptr};
303     BCRYPT_PSS_PADDING_INFO pss_padding_info = {nullptr};
304     void* padding_info = nullptr;
305     DWORD flags = 0;
306     if (SSL_get_signature_algorithm_key_type(algorithm) == EVP_PKEY_RSA) {
307       const WCHAR* hash_alg;
308       switch (EVP_MD_type(md)) {
309         case NID_md5_sha1:
310           hash_alg = nullptr;
311           break;
312         case NID_sha1:
313           hash_alg = BCRYPT_SHA1_ALGORITHM;
314           break;
315         case NID_sha256:
316           hash_alg = BCRYPT_SHA256_ALGORITHM;
317           break;
318         case NID_sha384:
319           hash_alg = BCRYPT_SHA384_ALGORITHM;
320           break;
321         case NID_sha512:
322           hash_alg = BCRYPT_SHA512_ALGORITHM;
323           break;
324         default:
325           NOTREACHED();
326       }
327       if (SSL_is_signature_algorithm_rsa_pss(algorithm)) {
328         pss_padding_info.pszAlgId = hash_alg;
329         pss_padding_info.cbSalt = EVP_MD_size(md);
330         padding_info = &pss_padding_info;
331         flags |= BCRYPT_PAD_PSS;
332       } else {
333         pkcs1_padding_info.pszAlgId = hash_alg;
334         padding_info = &pkcs1_padding_info;
335         flags |= BCRYPT_PAD_PKCS1;
336       }
337     }
338 
339     DWORD signature_len;
340     SECURITY_STATUS status =
341         NCryptSignHash(key_.get(), padding_info, const_cast<BYTE*>(digest),
342                        digest_len, nullptr, 0, &signature_len, flags);
343     if (FAILED(status)) {
344       LOG(ERROR) << "NCryptSignHash failed: " << status;
345       return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED;
346     }
347     signature->resize(signature_len);
348     status = NCryptSignHash(key_.get(), padding_info, const_cast<BYTE*>(digest),
349                             digest_len, signature->data(), signature_len,
350                             &signature_len, flags);
351     if (FAILED(status)) {
352       LOG(ERROR) << "NCryptSignHash failed: " << status;
353       return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED;
354     }
355     signature->resize(signature_len);
356 
357     // CNG emits raw ECDSA signatures, but BoringSSL expects a DER-encoded
358     // ECDSA-Sig-Value.
359     if (type_ == EVP_PKEY_EC) {
360       if (signature->size() % 2 != 0) {
361         LOG(ERROR) << "Bad signature length";
362         return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED;
363       }
364       size_t order_len = signature->size() / 2;
365 
366       // Convert the RAW ECDSA signature to a DER-encoded ECDSA-Sig-Value.
367       bssl::UniquePtr<ECDSA_SIG> sig(ECDSA_SIG_new());
368       if (!sig || !BN_bin2bn(signature->data(), order_len, sig->r) ||
369           !BN_bin2bn(signature->data() + order_len, order_len, sig->s)) {
370         return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED;
371       }
372 
373       int len = i2d_ECDSA_SIG(sig.get(), nullptr);
374       if (len <= 0)
375         return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED;
376       signature->resize(len);
377       uint8_t* ptr = signature->data();
378       len = i2d_ECDSA_SIG(sig.get(), &ptr);
379       if (len <= 0)
380         return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED;
381       signature->resize(len);
382     }
383 
384     return OK;
385   }
386 
387  private:
388   std::wstring provider_name_;
389   crypto::ScopedNCryptKey key_;
390   int type_;
391   size_t max_length_;
392   bool prefer_sha1_ = false;
393 };
394 
395 }  // namespace
396 
WrapCAPIPrivateKey(const X509Certificate * certificate,crypto::ScopedHCRYPTPROV prov,DWORD key_spec)397 scoped_refptr<SSLPrivateKey> WrapCAPIPrivateKey(
398     const X509Certificate* certificate,
399     crypto::ScopedHCRYPTPROV prov,
400     DWORD key_spec) {
401   return base::MakeRefCounted<ThreadedSSLPrivateKey>(
402       std::make_unique<SSLPlatformKeyCAPI>(std::move(prov), key_spec),
403       GetSSLPlatformKeyTaskRunner());
404 }
405 
WrapCNGPrivateKey(const X509Certificate * certificate,crypto::ScopedNCryptKey key)406 scoped_refptr<SSLPrivateKey> WrapCNGPrivateKey(
407     const X509Certificate* certificate,
408     crypto::ScopedNCryptKey key) {
409   // Rather than query the private key for metadata, extract the public key from
410   // the certificate without using Windows APIs. CNG does not consistently work
411   // depending on the system. See https://crbug.com/468345.
412   int key_type;
413   size_t max_length;
414   if (!GetClientCertInfo(certificate, &key_type, &max_length)) {
415     return nullptr;
416   }
417 
418   return base::MakeRefCounted<ThreadedSSLPrivateKey>(
419       std::make_unique<SSLPlatformKeyCNG>(std::move(key), key_type, max_length),
420       GetSSLPlatformKeyTaskRunner());
421 }
422 
FetchClientCertPrivateKey(const X509Certificate * certificate,PCCERT_CONTEXT cert_context)423 scoped_refptr<SSLPrivateKey> FetchClientCertPrivateKey(
424     const X509Certificate* certificate,
425     PCCERT_CONTEXT cert_context) {
426   HCRYPTPROV_OR_NCRYPT_KEY_HANDLE prov_or_key = 0;
427   DWORD key_spec = 0;
428   BOOL must_free = FALSE;
429   DWORD flags = CRYPT_ACQUIRE_PREFER_NCRYPT_KEY_FLAG;
430 
431   if (!CryptAcquireCertificatePrivateKey(cert_context, flags, nullptr,
432                                          &prov_or_key, &key_spec, &must_free)) {
433     PLOG(WARNING) << "Could not acquire private key";
434     return nullptr;
435   }
436 
437   // Should never get a cached handle back - ownership must always be
438   // transferred.
439   CHECK_EQ(must_free, TRUE);
440 
441   if (key_spec == CERT_NCRYPT_KEY_SPEC) {
442     return WrapCNGPrivateKey(certificate, crypto::ScopedNCryptKey(prov_or_key));
443   } else {
444     return WrapCAPIPrivateKey(certificate,
445                               crypto::ScopedHCRYPTPROV(prov_or_key), key_spec);
446   }
447 }
448 
WrapUnexportableKeySlowly(const crypto::UnexportableSigningKey & key)449 scoped_refptr<SSLPrivateKey> WrapUnexportableKeySlowly(
450     const crypto::UnexportableSigningKey& key) {
451   // Load NCRYPT_KEY_HANDLE from wrapped.
452   auto wrapped = key.GetWrappedKey();
453   crypto::ScopedNCryptProvider provider;
454   crypto::ScopedNCryptKey key_handle;
455   if (!crypto::LoadWrappedTPMKey(wrapped, provider, key_handle)) {
456     return nullptr;
457   }
458 
459   int key_type;
460   size_t max_length;
461   if (!GetPublicKeyInfo(key.GetSubjectPublicKeyInfo(), &key_type,
462                         &max_length)) {
463     return nullptr;
464   }
465 
466   return base::MakeRefCounted<ThreadedSSLPrivateKey>(
467       std::make_unique<SSLPlatformKeyCNG>(std::move(key_handle), key_type,
468                                           max_length),
469       GetSSLPlatformKeyTaskRunner());
470 }
471 
472 }  // namespace net
473