| 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> |
| (...skipping 15 matching lines...) Expand all Loading... |
| 26 #include "third_party/boringssl/src/include/openssl/ecdsa.h" | 26 #include "third_party/boringssl/src/include/openssl/ecdsa.h" |
| 27 #include "third_party/boringssl/src/include/openssl/evp.h" | 27 #include "third_party/boringssl/src/include/openssl/evp.h" |
| 28 | 28 |
| 29 namespace net { | 29 namespace net { |
| 30 | 30 |
| 31 namespace { | 31 namespace { |
| 32 | 32 |
| 33 class SSLPlatformKeyCAPI : public ThreadedSSLPrivateKey::Delegate { | 33 class SSLPlatformKeyCAPI : public ThreadedSSLPrivateKey::Delegate { |
| 34 public: | 34 public: |
| 35 // Takes ownership of |provider|. | 35 // Takes ownership of |provider|. |
| 36 SSLPlatformKeyCAPI(HCRYPTPROV provider, DWORD key_spec, size_t max_length) | 36 SSLPlatformKeyCAPI(HCRYPTPROV provider, DWORD key_spec) |
| 37 : provider_(provider), key_spec_(key_spec), max_length_(max_length) {} | 37 : provider_(provider), key_spec_(key_spec) {} |
| 38 | 38 |
| 39 ~SSLPlatformKeyCAPI() override {} | 39 ~SSLPlatformKeyCAPI() override {} |
| 40 | 40 |
| 41 SSLPrivateKey::Type GetType() override { return SSLPrivateKey::Type::RSA; } | |
| 42 | |
| 43 std::vector<SSLPrivateKey::Hash> GetDigestPreferences() override { | 41 std::vector<SSLPrivateKey::Hash> GetDigestPreferences() override { |
| 44 // If the key is in CAPI, assume conservatively that the CAPI service | 42 // If the key is in CAPI, assume conservatively that the CAPI service |
| 45 // provider may only be able to sign pre-TLS-1.2 and SHA-1 hashes. | 43 // provider may only be able to sign pre-TLS-1.2 and SHA-1 hashes. |
| 46 static const SSLPrivateKey::Hash kHashes[] = { | 44 static const SSLPrivateKey::Hash kHashes[] = { |
| 47 SSLPrivateKey::Hash::SHA1, SSLPrivateKey::Hash::SHA512, | 45 SSLPrivateKey::Hash::SHA1, SSLPrivateKey::Hash::SHA512, |
| 48 SSLPrivateKey::Hash::SHA384, SSLPrivateKey::Hash::SHA256}; | 46 SSLPrivateKey::Hash::SHA384, SSLPrivateKey::Hash::SHA256}; |
| 49 return std::vector<SSLPrivateKey::Hash>(kHashes, | 47 return std::vector<SSLPrivateKey::Hash>(kHashes, |
| 50 kHashes + arraysize(kHashes)); | 48 kHashes + arraysize(kHashes)); |
| 51 } | 49 } |
| 52 | 50 |
| 53 size_t GetMaxSignatureLengthInBytes() override { return max_length_; } | |
| 54 | |
| 55 Error SignDigest(SSLPrivateKey::Hash hash, | 51 Error SignDigest(SSLPrivateKey::Hash hash, |
| 56 const base::StringPiece& input, | 52 const base::StringPiece& input, |
| 57 std::vector<uint8_t>* signature) override { | 53 std::vector<uint8_t>* signature) override { |
| 58 ALG_ID hash_alg = 0; | 54 ALG_ID hash_alg = 0; |
| 59 switch (hash) { | 55 switch (hash) { |
| 60 case SSLPrivateKey::Hash::MD5_SHA1: | 56 case SSLPrivateKey::Hash::MD5_SHA1: |
| 61 hash_alg = CALG_SSL3_SHAMD5; | 57 hash_alg = CALG_SSL3_SHAMD5; |
| 62 break; | 58 break; |
| 63 case SSLPrivateKey::Hash::SHA1: | 59 case SSLPrivateKey::Hash::SHA1: |
| 64 hash_alg = CALG_SHA1; | 60 hash_alg = CALG_SHA1; |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 111 signature->resize(signature_len); | 107 signature->resize(signature_len); |
| 112 | 108 |
| 113 // CryptoAPI signs in little-endian, so reverse it. | 109 // CryptoAPI signs in little-endian, so reverse it. |
| 114 std::reverse(signature->begin(), signature->end()); | 110 std::reverse(signature->begin(), signature->end()); |
| 115 return OK; | 111 return OK; |
| 116 } | 112 } |
| 117 | 113 |
| 118 private: | 114 private: |
| 119 crypto::ScopedHCRYPTPROV provider_; | 115 crypto::ScopedHCRYPTPROV provider_; |
| 120 DWORD key_spec_; | 116 DWORD key_spec_; |
| 121 size_t max_length_; | |
| 122 | 117 |
| 123 DISALLOW_COPY_AND_ASSIGN(SSLPlatformKeyCAPI); | 118 DISALLOW_COPY_AND_ASSIGN(SSLPlatformKeyCAPI); |
| 124 }; | 119 }; |
| 125 | 120 |
| 126 class SSLPlatformKeyCNG : public ThreadedSSLPrivateKey::Delegate { | 121 class SSLPlatformKeyCNG : public ThreadedSSLPrivateKey::Delegate { |
| 127 public: | 122 public: |
| 128 // Takes ownership of |key|. | 123 // Takes ownership of |key|. |
| 129 SSLPlatformKeyCNG(NCRYPT_KEY_HANDLE key, | 124 SSLPlatformKeyCNG(NCRYPT_KEY_HANDLE key, int type, size_t max_length) |
| 130 SSLPrivateKey::Type type, | |
| 131 size_t max_length) | |
| 132 : key_(key), type_(type), max_length_(max_length) {} | 125 : key_(key), type_(type), max_length_(max_length) {} |
| 133 | 126 |
| 134 ~SSLPlatformKeyCNG() override { NCryptFreeObject(key_); } | 127 ~SSLPlatformKeyCNG() override { NCryptFreeObject(key_); } |
| 135 | 128 |
| 136 SSLPrivateKey::Type GetType() override { return type_; } | |
| 137 | |
| 138 std::vector<SSLPrivateKey::Hash> GetDigestPreferences() override { | 129 std::vector<SSLPrivateKey::Hash> GetDigestPreferences() override { |
| 139 // If this is an under 1024-bit RSA key, conservatively prefer to sign | 130 // If this is an under 1024-bit RSA key, conservatively prefer to sign |
| 140 // SHA-1 hashes. Older Estonian ID cards can only sign SHA-1 hashes. | 131 // SHA-1 hashes. Older Estonian ID cards can only sign SHA-1 hashes. |
| 141 // However, if the server doesn't advertise SHA-1, the remaining hashes | 132 // However, if the server doesn't advertise SHA-1, the remaining hashes |
| 142 // might still be supported. | 133 // might still be supported. |
| 143 if (type_ == SSLPrivateKey::Type::RSA && max_length_ <= 1024 / 8) { | 134 if (type_ == EVP_PKEY_RSA && max_length_ <= 1024 / 8) { |
| 144 static const SSLPrivateKey::Hash kHashesSpecial[] = { | 135 static const SSLPrivateKey::Hash kHashesSpecial[] = { |
| 145 SSLPrivateKey::Hash::SHA1, SSLPrivateKey::Hash::SHA512, | 136 SSLPrivateKey::Hash::SHA1, SSLPrivateKey::Hash::SHA512, |
| 146 SSLPrivateKey::Hash::SHA384, SSLPrivateKey::Hash::SHA256}; | 137 SSLPrivateKey::Hash::SHA384, SSLPrivateKey::Hash::SHA256}; |
| 147 return std::vector<SSLPrivateKey::Hash>( | 138 return std::vector<SSLPrivateKey::Hash>( |
| 148 kHashesSpecial, kHashesSpecial + arraysize(kHashesSpecial)); | 139 kHashesSpecial, kHashesSpecial + arraysize(kHashesSpecial)); |
| 149 } | 140 } |
| 150 static const SSLPrivateKey::Hash kHashes[] = { | 141 static const SSLPrivateKey::Hash kHashes[] = { |
| 151 SSLPrivateKey::Hash::SHA512, SSLPrivateKey::Hash::SHA384, | 142 SSLPrivateKey::Hash::SHA512, SSLPrivateKey::Hash::SHA384, |
| 152 SSLPrivateKey::Hash::SHA256, SSLPrivateKey::Hash::SHA1}; | 143 SSLPrivateKey::Hash::SHA256, SSLPrivateKey::Hash::SHA1}; |
| 153 return std::vector<SSLPrivateKey::Hash>(kHashes, | 144 return std::vector<SSLPrivateKey::Hash>(kHashes, |
| 154 kHashes + arraysize(kHashes)); | 145 kHashes + arraysize(kHashes)); |
| 155 } | 146 } |
| 156 | 147 |
| 157 size_t GetMaxSignatureLengthInBytes() override { return max_length_; } | |
| 158 | |
| 159 Error SignDigest(SSLPrivateKey::Hash hash, | 148 Error SignDigest(SSLPrivateKey::Hash hash, |
| 160 const base::StringPiece& input, | 149 const base::StringPiece& input, |
| 161 std::vector<uint8_t>* signature) override { | 150 std::vector<uint8_t>* signature) override { |
| 162 crypto::OpenSSLErrStackTracer tracer(FROM_HERE); | 151 crypto::OpenSSLErrStackTracer tracer(FROM_HERE); |
| 163 | 152 |
| 164 BCRYPT_PKCS1_PADDING_INFO rsa_padding_info = {0}; | 153 BCRYPT_PKCS1_PADDING_INFO rsa_padding_info = {0}; |
| 165 void* padding_info = nullptr; | 154 void* padding_info = nullptr; |
| 166 DWORD flags = 0; | 155 DWORD flags = 0; |
| 167 if (type_ == SSLPrivateKey::Type::RSA) { | 156 if (type_ == EVP_PKEY_RSA) { |
| 168 switch (hash) { | 157 switch (hash) { |
| 169 case SSLPrivateKey::Hash::MD5_SHA1: | 158 case SSLPrivateKey::Hash::MD5_SHA1: |
| 170 rsa_padding_info.pszAlgId = nullptr; | 159 rsa_padding_info.pszAlgId = nullptr; |
| 171 break; | 160 break; |
| 172 case SSLPrivateKey::Hash::SHA1: | 161 case SSLPrivateKey::Hash::SHA1: |
| 173 rsa_padding_info.pszAlgId = BCRYPT_SHA1_ALGORITHM; | 162 rsa_padding_info.pszAlgId = BCRYPT_SHA1_ALGORITHM; |
| 174 break; | 163 break; |
| 175 case SSLPrivateKey::Hash::SHA256: | 164 case SSLPrivateKey::Hash::SHA256: |
| 176 rsa_padding_info.pszAlgId = BCRYPT_SHA256_ALGORITHM; | 165 rsa_padding_info.pszAlgId = BCRYPT_SHA256_ALGORITHM; |
| 177 break; | 166 break; |
| (...skipping 23 matching lines...) Expand all Loading... |
| 201 const_cast<BYTE*>(reinterpret_cast<const BYTE*>(input.data())), | 190 const_cast<BYTE*>(reinterpret_cast<const BYTE*>(input.data())), |
| 202 input.size(), signature->data(), signature_len, &signature_len, flags); | 191 input.size(), signature->data(), signature_len, &signature_len, flags); |
| 203 if (FAILED(status)) { | 192 if (FAILED(status)) { |
| 204 LOG(ERROR) << "NCryptSignHash failed: " << status; | 193 LOG(ERROR) << "NCryptSignHash failed: " << status; |
| 205 return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED; | 194 return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED; |
| 206 } | 195 } |
| 207 signature->resize(signature_len); | 196 signature->resize(signature_len); |
| 208 | 197 |
| 209 // CNG emits raw ECDSA signatures, but BoringSSL expects a DER-encoded | 198 // CNG emits raw ECDSA signatures, but BoringSSL expects a DER-encoded |
| 210 // ECDSA-Sig-Value. | 199 // ECDSA-Sig-Value. |
| 211 if (SSLPrivateKey::IsECDSAType(type_)) { | 200 if (type_ == EVP_PKEY_EC) { |
| 212 if (signature->size() % 2 != 0) { | 201 if (signature->size() % 2 != 0) { |
| 213 LOG(ERROR) << "Bad signature length"; | 202 LOG(ERROR) << "Bad signature length"; |
| 214 return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED; | 203 return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED; |
| 215 } | 204 } |
| 216 size_t order_len = signature->size() / 2; | 205 size_t order_len = signature->size() / 2; |
| 217 | 206 |
| 218 // Convert the RAW ECDSA signature to a DER-encoded ECDSA-Sig-Value. | 207 // Convert the RAW ECDSA signature to a DER-encoded ECDSA-Sig-Value. |
| 219 bssl::UniquePtr<ECDSA_SIG> sig(ECDSA_SIG_new()); | 208 bssl::UniquePtr<ECDSA_SIG> sig(ECDSA_SIG_new()); |
| 220 if (!sig || !BN_bin2bn(signature->data(), order_len, sig->r) || | 209 if (!sig || !BN_bin2bn(signature->data(), order_len, sig->r) || |
| 221 !BN_bin2bn(signature->data() + order_len, order_len, sig->s)) { | 210 !BN_bin2bn(signature->data() + order_len, order_len, sig->s)) { |
| 222 return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED; | 211 return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED; |
| 223 } | 212 } |
| 224 | 213 |
| 225 int len = i2d_ECDSA_SIG(sig.get(), nullptr); | 214 int len = i2d_ECDSA_SIG(sig.get(), nullptr); |
| 226 if (len <= 0) | 215 if (len <= 0) |
| 227 return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED; | 216 return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED; |
| 228 signature->resize(len); | 217 signature->resize(len); |
| 229 uint8_t* ptr = signature->data(); | 218 uint8_t* ptr = signature->data(); |
| 230 len = i2d_ECDSA_SIG(sig.get(), &ptr); | 219 len = i2d_ECDSA_SIG(sig.get(), &ptr); |
| 231 if (len <= 0) | 220 if (len <= 0) |
| 232 return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED; | 221 return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED; |
| 233 signature->resize(len); | 222 signature->resize(len); |
| 234 } | 223 } |
| 235 | 224 |
| 236 return OK; | 225 return OK; |
| 237 } | 226 } |
| 238 | 227 |
| 239 private: | 228 private: |
| 240 NCRYPT_KEY_HANDLE key_; | 229 NCRYPT_KEY_HANDLE key_; |
| 241 SSLPrivateKey::Type type_; | 230 int type_; |
| 242 size_t max_length_; | 231 size_t max_length_; |
| 243 | 232 |
| 244 DISALLOW_COPY_AND_ASSIGN(SSLPlatformKeyCNG); | 233 DISALLOW_COPY_AND_ASSIGN(SSLPlatformKeyCNG); |
| 245 }; | 234 }; |
| 246 | 235 |
| 247 } // namespace | 236 } // namespace |
| 248 | 237 |
| 249 scoped_refptr<SSLPrivateKey> FetchClientCertPrivateKey( | 238 scoped_refptr<SSLPrivateKey> FetchClientCertPrivateKey( |
| 250 const X509Certificate* certificate) { | 239 const X509Certificate* certificate) { |
| 251 // Rather than query the private key for metadata, extract the public key from | 240 // Rather than query the private key for metadata, extract the public key from |
| 252 // the certificate without using Windows APIs. CAPI and CNG do not | 241 // the certificate without using Windows APIs. CAPI and CNG do not |
| 253 // consistently work depending on the system. See https://crbug.com/468345. | 242 // consistently work depending on the system. See https://crbug.com/468345. |
| 254 SSLPrivateKey::Type key_type; | 243 int key_type; |
| 255 size_t max_length; | 244 size_t max_length; |
| 256 if (!GetClientCertInfo(certificate, &key_type, &max_length)) | 245 if (!GetClientCertInfo(certificate, &key_type, &max_length)) |
| 257 return nullptr; | 246 return nullptr; |
| 258 | 247 |
| 259 PCCERT_CONTEXT cert_context = certificate->os_cert_handle(); | 248 PCCERT_CONTEXT cert_context = certificate->os_cert_handle(); |
| 260 | 249 |
| 261 HCRYPTPROV_OR_NCRYPT_KEY_HANDLE prov_or_key = 0; | 250 HCRYPTPROV_OR_NCRYPT_KEY_HANDLE prov_or_key = 0; |
| 262 DWORD key_spec = 0; | 251 DWORD key_spec = 0; |
| 263 BOOL must_free = FALSE; | 252 BOOL must_free = FALSE; |
| 264 DWORD flags = CRYPT_ACQUIRE_PREFER_NCRYPT_KEY_FLAG; | 253 DWORD flags = CRYPT_ACQUIRE_PREFER_NCRYPT_KEY_FLAG; |
| 265 | 254 |
| 266 if (!CryptAcquireCertificatePrivateKey(cert_context, flags, nullptr, | 255 if (!CryptAcquireCertificatePrivateKey(cert_context, flags, nullptr, |
| 267 &prov_or_key, &key_spec, &must_free)) { | 256 &prov_or_key, &key_spec, &must_free)) { |
| 268 PLOG(WARNING) << "Could not acquire private key"; | 257 PLOG(WARNING) << "Could not acquire private key"; |
| 269 return nullptr; | 258 return nullptr; |
| 270 } | 259 } |
| 271 | 260 |
| 272 // Should never get a cached handle back - ownership must always be | 261 // Should never get a cached handle back - ownership must always be |
| 273 // transferred. | 262 // transferred. |
| 274 CHECK_EQ(must_free, TRUE); | 263 CHECK_EQ(must_free, TRUE); |
| 275 | 264 |
| 276 std::unique_ptr<ThreadedSSLPrivateKey::Delegate> delegate; | 265 std::unique_ptr<ThreadedSSLPrivateKey::Delegate> delegate; |
| 277 if (key_spec == CERT_NCRYPT_KEY_SPEC) { | 266 if (key_spec == CERT_NCRYPT_KEY_SPEC) { |
| 278 delegate.reset(new SSLPlatformKeyCNG(prov_or_key, key_type, max_length)); | 267 delegate.reset(new SSLPlatformKeyCNG(prov_or_key, key_type, max_length)); |
| 279 } else { | 268 } else { |
| 280 DCHECK(SSLPrivateKey::Type::RSA == key_type); | 269 DCHECK_EQ(EVP_PKEY_RSA, key_type); |
| 281 delegate.reset(new SSLPlatformKeyCAPI(prov_or_key, key_spec, max_length)); | 270 delegate.reset(new SSLPlatformKeyCAPI(prov_or_key, key_spec)); |
| 282 } | 271 } |
| 283 return make_scoped_refptr(new ThreadedSSLPrivateKey( | 272 return make_scoped_refptr(new ThreadedSSLPrivateKey( |
| 284 std::move(delegate), GetSSLPlatformKeyTaskRunner())); | 273 std::move(delegate), GetSSLPlatformKeyTaskRunner())); |
| 285 } | 274 } |
| 286 | 275 |
| 287 } // namespace net | 276 } // namespace net |
| OLD | NEW |