Chromium Code Reviews| 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 uint8_t* in, | |
| 177 size_t in_len, | |
| 178 uint8_t* out, | |
| 179 size_t max_out, | |
| 180 size_t* out_len, | |
|
Ryan Sleevi
2015/03/27 07:00:38
Why is this a size_t? Why not consistent type and
davidben
2015/03/27 18:59:23
I figured I'd push the native types -> Windows bou
| |
| 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<PBYTE>(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 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 214 rsa_padding_info.pszAlgId = BCRYPT_SHA384_ALGORITHM; | 258 rsa_padding_info.pszAlgId = BCRYPT_SHA384_ALGORITHM; |
| 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 size_t out_len_size_t; |
|
Ryan Sleevi
2015/03/27 07:00:37
Reverse Hungarian Notation? :D
why not signature_
davidben
2015/03/27 18:59:23
Done.
| |
| 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), &out_len_size_t, |
| 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 = static_cast<unsigned>(out_len_size_t); |
| 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: |
| 239 hash_alg = CALG_SSL3_SHAMD5; | 282 hash_alg = CALG_SSL3_SHAMD5; |
| 240 break; | 283 break; |
| 241 case NID_sha1: | 284 case NID_sha1: |
| 242 hash_alg = CALG_SHA1; | 285 hash_alg = CALG_SHA1; |
| (...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 431 | 474 |
| 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 size_t raw_sig_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(), &raw_sig_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 (raw_sig_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 |