OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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/openssl_platform_key.h" | 5 #include "net/ssl/openssl_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 <string.h> | 10 #include <string.h> |
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
160 | 160 |
161 private: | 161 private: |
162 const int rsa_index_; | 162 const int rsa_index_; |
163 const int ec_key_index_; | 163 const int ec_key_index_; |
164 ENGINE* const engine_; | 164 ENGINE* const engine_; |
165 }; | 165 }; |
166 | 166 |
167 base::LazyInstance<BoringSSLEngine>::Leaky global_boringssl_engine = | 167 base::LazyInstance<BoringSSLEngine>::Leaky global_boringssl_engine = |
168 LAZY_INSTANCE_INITIALIZER; | 168 LAZY_INSTANCE_INITIALIZER; |
169 | 169 |
| 170 // Signs |in| with |key|, writing the output to |out| and the size to |out_len|. |
| 171 // Although the buffer is preallocated, this calls NCryptSignHash twice. Some |
| 172 // smartcards are buggy and assume the two-call pattern. See |
| 173 // https://crbug.com/470204. Returns true on success and false on error. |
| 174 bool DoNCryptSignHash(NCRYPT_KEY_HANDLE key, |
| 175 void* padding, |
| 176 const BYTE* in, |
| 177 DWORD in_len, |
| 178 BYTE* out, |
| 179 DWORD max_out, |
| 180 DWORD* out_len, |
| 181 DWORD flags) { |
| 182 // Determine the output length. |
| 183 DWORD signature_len; |
| 184 SECURITY_STATUS ncrypt_status = g_cng_functions.Get().ncrypt_sign_hash()( |
| 185 key, padding, const_cast<BYTE*>(in), in_len, nullptr, 0, &signature_len, |
| 186 flags); |
| 187 if (FAILED(ncrypt_status)) { |
| 188 LOG(ERROR) << "NCryptSignHash failed: " << ncrypt_status; |
| 189 return false; |
| 190 } |
| 191 // Check |max_out| externally rather than trust the smartcard. |
| 192 if (signature_len == 0 || signature_len > max_out) { |
| 193 LOG(ERROR) << "Bad signature length."; |
| 194 return false; |
| 195 } |
| 196 // It is important that |signature_len| already be initialized with the |
| 197 // correct size. Some smartcards are buggy and do not write to it on the |
| 198 // second call. |
| 199 ncrypt_status = g_cng_functions.Get().ncrypt_sign_hash()( |
| 200 key, padding, const_cast<PBYTE>(in), in_len, out, signature_len, |
| 201 &signature_len, flags); |
| 202 if (FAILED(ncrypt_status)) { |
| 203 LOG(ERROR) << "NCryptSignHash failed: " << ncrypt_status; |
| 204 return false; |
| 205 } |
| 206 if (signature_len == 0) { |
| 207 LOG(ERROR) << "Bad signature length."; |
| 208 return false; |
| 209 } |
| 210 *out_len = signature_len; |
| 211 return true; |
| 212 } |
| 213 |
170 // Custom RSA_METHOD that uses the platform APIs for signing. | 214 // Custom RSA_METHOD that uses the platform APIs for signing. |
171 | 215 |
172 const KeyExData* RsaGetExData(const RSA* rsa) { | 216 const KeyExData* RsaGetExData(const RSA* rsa) { |
173 return reinterpret_cast<const KeyExData*>( | 217 return reinterpret_cast<const KeyExData*>( |
174 RSA_get_ex_data(rsa, global_boringssl_engine.Get().rsa_ex_index())); | 218 RSA_get_ex_data(rsa, global_boringssl_engine.Get().rsa_ex_index())); |
175 } | 219 } |
176 | 220 |
177 size_t RsaMethodSize(const RSA* rsa) { | 221 size_t RsaMethodSize(const RSA* rsa) { |
178 const KeyExData* ex_data = RsaGetExData(rsa); | 222 const KeyExData* ex_data = RsaGetExData(rsa); |
179 return (ex_data->key_length + 7) / 8; | 223 return (ex_data->key_length + 7) / 8; |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
215 break; | 259 break; |
216 case NID_sha512: | 260 case NID_sha512: |
217 rsa_padding_info.pszAlgId = BCRYPT_SHA512_ALGORITHM; | 261 rsa_padding_info.pszAlgId = BCRYPT_SHA512_ALGORITHM; |
218 break; | 262 break; |
219 default: | 263 default: |
220 OPENSSL_PUT_ERROR(RSA, RSA_sign, RSA_R_UNKNOWN_ALGORITHM_TYPE); | 264 OPENSSL_PUT_ERROR(RSA, RSA_sign, RSA_R_UNKNOWN_ALGORITHM_TYPE); |
221 return 0; | 265 return 0; |
222 } | 266 } |
223 | 267 |
224 DWORD signature_len; | 268 DWORD signature_len; |
225 SECURITY_STATUS ncrypt_status = g_cng_functions.Get().ncrypt_sign_hash()( | 269 if (!DoNCryptSignHash(ex_data->key->hNCryptKey, &rsa_padding_info, in, |
226 ex_data->key->hNCryptKey, &rsa_padding_info, const_cast<PBYTE>(in), | 270 in_len, out, RSA_size(rsa), &signature_len, |
227 in_len, out, RSA_size(rsa), &signature_len, BCRYPT_PAD_PKCS1); | 271 BCRYPT_PAD_PKCS1)) { |
228 if (FAILED(ncrypt_status) || signature_len == 0) { | |
229 OpenSSLPutNetError(FROM_HERE, ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED); | 272 OpenSSLPutNetError(FROM_HERE, ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED); |
230 return 0; | 273 return 0; |
231 } | 274 } |
232 *out_len = signature_len; | 275 *out_len = signature_len; |
233 return 1; | 276 return 1; |
234 } | 277 } |
235 | 278 |
236 ALG_ID hash_alg; | 279 ALG_ID hash_alg; |
237 switch (hash_nid) { | 280 switch (hash_nid) { |
238 case NID_md5_sha1: | 281 case NID_md5_sha1: |
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
432 // An ECDSA signature is two integers, modulo the order of the group. | 475 // An ECDSA signature is two integers, modulo the order of the group. |
433 size_t order_len = (ex_data->key_length + 7) / 8; | 476 size_t order_len = (ex_data->key_length + 7) / 8; |
434 if (order_len == 0) { | 477 if (order_len == 0) { |
435 NOTREACHED(); | 478 NOTREACHED(); |
436 OpenSSLPutNetError(FROM_HERE, ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED); | 479 OpenSSLPutNetError(FROM_HERE, ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED); |
437 return 0; | 480 return 0; |
438 } | 481 } |
439 std::vector<uint8_t> raw_sig(order_len * 2); | 482 std::vector<uint8_t> raw_sig(order_len * 2); |
440 | 483 |
441 DWORD signature_len; | 484 DWORD signature_len; |
442 SECURITY_STATUS ncrypt_status = g_cng_functions.Get().ncrypt_sign_hash()( | 485 if (!DoNCryptSignHash(ex_data->key->hNCryptKey, nullptr, digest, digest_len, |
443 ex_data->key->hNCryptKey, nullptr, const_cast<PBYTE>(digest), digest_len, | 486 &raw_sig[0], raw_sig.size(), &signature_len, 0)) { |
444 &raw_sig[0], raw_sig.size(), &signature_len, 0); | |
445 if (FAILED(ncrypt_status) || signature_len != raw_sig.size()) { | |
446 OpenSSLPutNetError(FROM_HERE, ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED); | 487 OpenSSLPutNetError(FROM_HERE, ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED); |
447 return 0; | 488 return 0; |
448 } | 489 } |
| 490 if (signature_len != raw_sig.size()) { |
| 491 LOG(ERROR) << "Bad signature length"; |
| 492 OpenSSLPutNetError(FROM_HERE, ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED); |
| 493 return 0; |
| 494 } |
449 | 495 |
450 // Convert the RAW ECDSA signature to a DER-encoded ECDSA-Sig-Value. | 496 // Convert the RAW ECDSA signature to a DER-encoded ECDSA-Sig-Value. |
451 crypto::ScopedECDSA_SIG sig(ECDSA_SIG_new()); | 497 crypto::ScopedECDSA_SIG sig(ECDSA_SIG_new()); |
452 if (!sig) { | 498 if (!sig) { |
453 OpenSSLPutNetError(FROM_HERE, ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED); | 499 OpenSSLPutNetError(FROM_HERE, ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED); |
454 return 0; | 500 return 0; |
455 } | 501 } |
456 sig->r = BN_bin2bn(&raw_sig[0], order_len, nullptr); | 502 sig->r = BN_bin2bn(&raw_sig[0], order_len, nullptr); |
457 sig->s = BN_bin2bn(&raw_sig[order_len], order_len, nullptr); | 503 sig->s = BN_bin2bn(&raw_sig[order_len], order_len, nullptr); |
458 if (!sig->r || !sig->s) { | 504 if (!sig->r || !sig->s) { |
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
597 case EVP_PKEY_RSA: | 643 case EVP_PKEY_RSA: |
598 return CreateRSAWrapper(key.Pass(), key_length); | 644 return CreateRSAWrapper(key.Pass(), key_length); |
599 case EVP_PKEY_EC: | 645 case EVP_PKEY_EC: |
600 return CreateECDSAWrapper(key.Pass(), key_length); | 646 return CreateECDSAWrapper(key.Pass(), key_length); |
601 default: | 647 default: |
602 return nullptr; | 648 return nullptr; |
603 } | 649 } |
604 } | 650 } |
605 | 651 |
606 } // namespace net | 652 } // namespace net |
OLD | NEW |