OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "net/ssl/ssl_platform_key.h" | 5 #include "net/ssl/ssl_platform_key.h" |
6 | 6 |
7 #include <windows.h> | 7 #include <windows.h> |
8 #include <NCrypt.h> | 8 #include <NCrypt.h> |
9 | 9 |
10 #include <algorithm> | 10 #include <algorithm> |
11 #include <string> | 11 #include <string> |
12 #include <utility> | 12 #include <utility> |
13 #include <vector> | 13 #include <vector> |
14 | 14 |
15 #include <openssl/bn.h> | 15 #include <openssl/bn.h> |
16 #include <openssl/ecdsa.h> | 16 #include <openssl/ecdsa.h> |
17 #include <openssl/evp.h> | 17 #include <openssl/evp.h> |
18 #include <openssl/x509.h> | 18 #include <openssl/x509.h> |
19 | 19 |
20 #include "base/logging.h" | 20 #include "base/logging.h" |
21 #include "base/macros.h" | 21 #include "base/macros.h" |
22 #include "base/sequenced_task_runner.h" | 22 #include "base/sequenced_task_runner.h" |
23 #include "crypto/openssl_util.h" | 23 #include "crypto/openssl_util.h" |
24 #include "crypto/scoped_capi_types.h" | 24 #include "crypto/scoped_capi_types.h" |
25 #include "crypto/wincrypt_shim.h" | 25 #include "crypto/wincrypt_shim.h" |
26 #include "net/base/net_errors.h" | 26 #include "net/base/net_errors.h" |
27 #include "net/cert/x509_certificate.h" | 27 #include "net/cert/x509_certificate.h" |
28 #include "net/ssl/ssl_platform_key_task_runner.h" | 28 #include "net/ssl/ssl_platform_key_util.h" |
29 #include "net/ssl/ssl_private_key.h" | 29 #include "net/ssl/ssl_private_key.h" |
30 #include "net/ssl/threaded_ssl_private_key.h" | 30 #include "net/ssl/threaded_ssl_private_key.h" |
31 | 31 |
32 namespace net { | 32 namespace net { |
33 | 33 |
34 namespace { | 34 namespace { |
35 | 35 |
36 class SSLPlatformKeyCAPI : public ThreadedSSLPrivateKey::Delegate { | 36 class SSLPlatformKeyCAPI : public ThreadedSSLPrivateKey::Delegate { |
37 public: | 37 public: |
38 // Takes ownership of |provider|. | 38 // Takes ownership of |provider|. |
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
204 const_cast<BYTE*>(reinterpret_cast<const BYTE*>(input.data())), | 204 const_cast<BYTE*>(reinterpret_cast<const BYTE*>(input.data())), |
205 input.size(), signature->data(), signature_len, &signature_len, flags); | 205 input.size(), signature->data(), signature_len, &signature_len, flags); |
206 if (FAILED(status)) { | 206 if (FAILED(status)) { |
207 LOG(ERROR) << "NCryptSignHash failed: " << status; | 207 LOG(ERROR) << "NCryptSignHash failed: " << status; |
208 return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED; | 208 return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED; |
209 } | 209 } |
210 signature->resize(signature_len); | 210 signature->resize(signature_len); |
211 | 211 |
212 // CNG emits raw ECDSA signatures, but BoringSSL expects a DER-encoded | 212 // CNG emits raw ECDSA signatures, but BoringSSL expects a DER-encoded |
213 // ECDSA-Sig-Value. | 213 // ECDSA-Sig-Value. |
214 if (type_ == SSLPrivateKey::Type::ECDSA) { | 214 if (SSLPrivateKey::IsECDSAType(type_)) { |
215 if (signature->size() % 2 != 0) { | 215 if (signature->size() % 2 != 0) { |
216 LOG(ERROR) << "Bad signature length"; | 216 LOG(ERROR) << "Bad signature length"; |
217 return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED; | 217 return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED; |
218 } | 218 } |
219 size_t order_len = signature->size() / 2; | 219 size_t order_len = signature->size() / 2; |
220 | 220 |
221 // Convert the RAW ECDSA signature to a DER-encoded ECDSA-Sig-Value. | 221 // Convert the RAW ECDSA signature to a DER-encoded ECDSA-Sig-Value. |
222 bssl::UniquePtr<ECDSA_SIG> sig(ECDSA_SIG_new()); | 222 bssl::UniquePtr<ECDSA_SIG> sig(ECDSA_SIG_new()); |
223 if (!sig || !BN_bin2bn(signature->data(), order_len, sig->r) || | 223 if (!sig || !BN_bin2bn(signature->data(), order_len, sig->r) || |
224 !BN_bin2bn(signature->data() + order_len, order_len, sig->s)) { | 224 !BN_bin2bn(signature->data() + order_len, order_len, sig->s)) { |
(...skipping 15 matching lines...) Expand all Loading... |
240 } | 240 } |
241 | 241 |
242 private: | 242 private: |
243 NCRYPT_KEY_HANDLE key_; | 243 NCRYPT_KEY_HANDLE key_; |
244 SSLPrivateKey::Type type_; | 244 SSLPrivateKey::Type type_; |
245 size_t max_length_; | 245 size_t max_length_; |
246 | 246 |
247 DISALLOW_COPY_AND_ASSIGN(SSLPlatformKeyCNG); | 247 DISALLOW_COPY_AND_ASSIGN(SSLPlatformKeyCNG); |
248 }; | 248 }; |
249 | 249 |
250 // Determines the key type and maximum signature length of |certificate|'s | |
251 // public key. | |
252 bool GetKeyInfo(const X509Certificate* certificate, | |
253 SSLPrivateKey::Type* out_type, | |
254 size_t* out_max_length) { | |
255 crypto::OpenSSLErrStackTracer tracker(FROM_HERE); | |
256 | |
257 std::string der_encoded; | |
258 if (!X509Certificate::GetDEREncoded(certificate->os_cert_handle(), | |
259 &der_encoded)) | |
260 return false; | |
261 const uint8_t* bytes = reinterpret_cast<const uint8_t*>(der_encoded.data()); | |
262 bssl::UniquePtr<X509> x509(d2i_X509(nullptr, &bytes, der_encoded.size())); | |
263 if (!x509) | |
264 return false; | |
265 bssl::UniquePtr<EVP_PKEY> key(X509_get_pubkey(x509.get())); | |
266 if (!key) | |
267 return false; | |
268 switch (EVP_PKEY_id(key.get())) { | |
269 case EVP_PKEY_RSA: | |
270 *out_type = SSLPrivateKey::Type::RSA; | |
271 break; | |
272 case EVP_PKEY_EC: | |
273 *out_type = SSLPrivateKey::Type::ECDSA; | |
274 break; | |
275 default: | |
276 return false; | |
277 } | |
278 *out_max_length = EVP_PKEY_size(key.get()); | |
279 return true; | |
280 } | |
281 | |
282 } // namespace | 250 } // namespace |
283 | 251 |
284 scoped_refptr<SSLPrivateKey> FetchClientCertPrivateKey( | 252 scoped_refptr<SSLPrivateKey> FetchClientCertPrivateKey( |
285 X509Certificate* certificate) { | 253 X509Certificate* certificate) { |
286 // Rather than query the private key for metadata, extract the public key from | 254 // Rather than query the private key for metadata, extract the public key from |
287 // the certificate without using Windows APIs. CAPI and CNG do not | 255 // the certificate without using Windows APIs. CAPI and CNG do not |
288 // consistently work depending on the system. See https://crbug.com/468345. | 256 // consistently work depending on the system. See https://crbug.com/468345. |
289 SSLPrivateKey::Type key_type; | 257 SSLPrivateKey::Type key_type; |
290 size_t max_length; | 258 size_t max_length; |
291 if (!GetKeyInfo(certificate, &key_type, &max_length)) | 259 if (!GetClientCertInfo(certificate, &key_type, &max_length)) |
292 return nullptr; | 260 return nullptr; |
293 | 261 |
294 PCCERT_CONTEXT cert_context = certificate->os_cert_handle(); | 262 PCCERT_CONTEXT cert_context = certificate->os_cert_handle(); |
295 | 263 |
296 HCRYPTPROV_OR_NCRYPT_KEY_HANDLE prov_or_key = 0; | 264 HCRYPTPROV_OR_NCRYPT_KEY_HANDLE prov_or_key = 0; |
297 DWORD key_spec = 0; | 265 DWORD key_spec = 0; |
298 BOOL must_free = FALSE; | 266 BOOL must_free = FALSE; |
299 DWORD flags = CRYPT_ACQUIRE_PREFER_NCRYPT_KEY_FLAG; | 267 DWORD flags = CRYPT_ACQUIRE_PREFER_NCRYPT_KEY_FLAG; |
300 | 268 |
301 if (!CryptAcquireCertificatePrivateKey(cert_context, flags, nullptr, | 269 if (!CryptAcquireCertificatePrivateKey(cert_context, flags, nullptr, |
(...skipping 11 matching lines...) Expand all Loading... |
313 delegate.reset(new SSLPlatformKeyCNG(prov_or_key, key_type, max_length)); | 281 delegate.reset(new SSLPlatformKeyCNG(prov_or_key, key_type, max_length)); |
314 } else { | 282 } else { |
315 DCHECK(SSLPrivateKey::Type::RSA == key_type); | 283 DCHECK(SSLPrivateKey::Type::RSA == key_type); |
316 delegate.reset(new SSLPlatformKeyCAPI(prov_or_key, key_spec, max_length)); | 284 delegate.reset(new SSLPlatformKeyCAPI(prov_or_key, key_spec, max_length)); |
317 } | 285 } |
318 return make_scoped_refptr(new ThreadedSSLPrivateKey( | 286 return make_scoped_refptr(new ThreadedSSLPrivateKey( |
319 std::move(delegate), GetSSLPlatformKeyTaskRunner())); | 287 std::move(delegate), GetSSLPlatformKeyTaskRunner())); |
320 } | 288 } |
321 | 289 |
322 } // namespace net | 290 } // namespace net |
OLD | NEW |