| 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 |