Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(530)

Side by Side Diff: net/ssl/openssl_platform_key_win.cc

Issue 1037123002: Work around a bug in the NCryptSignHash implementation of some smartcards. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: unnecessary churn Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698