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 |