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 |