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

Unified 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: 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: net/ssl/openssl_platform_key_win.cc
diff --git a/net/ssl/openssl_platform_key_win.cc b/net/ssl/openssl_platform_key_win.cc
index ead5957000800baab85ab59e331c254c4cc21071..fa5b6f5b1455ef626ad39cc4991cca4dd5f21fbf 100644
--- a/net/ssl/openssl_platform_key_win.cc
+++ b/net/ssl/openssl_platform_key_win.cc
@@ -167,6 +167,50 @@ class BoringSSLEngine {
base::LazyInstance<BoringSSLEngine>::Leaky global_boringssl_engine =
LAZY_INSTANCE_INITIALIZER;
+// Signs |in| with |key|, writing the output to |out| and the size to |out_len|.
+// Although the buffer is preallocated, this calls NCryptSignHash twice. Some
+// smartcards are buggy and assume the two-call pattern. See
+// https://crbug.com/470204. Returns true on success and false on error.
+bool DoNCryptSignHash(NCRYPT_KEY_HANDLE key,
+ void* padding,
+ const uint8_t* in,
+ size_t in_len,
+ uint8_t* out,
+ size_t max_out,
+ 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
+ DWORD flags) {
+ // Determine the output length.
+ DWORD signature_len;
+ SECURITY_STATUS ncrypt_status = g_cng_functions.Get().ncrypt_sign_hash()(
+ key, padding, const_cast<PBYTE>(in), in_len, nullptr, 0, &signature_len,
+ flags);
+ if (FAILED(ncrypt_status)) {
+ LOG(ERROR) << "NCryptSignHash failed: " << ncrypt_status;
+ return false;
+ }
+ // Check |max_out| externally rather than trust the smartcard.
+ if (signature_len == 0 || signature_len > max_out) {
+ LOG(ERROR) << "Bad signature length.";
+ return false;
+ }
+ // It is important that |signature_len| already be initialized with the
+ // correct size. Some smartcards are buggy and do not write to it on the
+ // second call.
+ ncrypt_status = g_cng_functions.Get().ncrypt_sign_hash()(
+ key, padding, const_cast<PBYTE>(in), in_len, out, signature_len,
+ &signature_len, flags);
+ if (FAILED(ncrypt_status)) {
+ LOG(ERROR) << "NCryptSignHash failed: " << ncrypt_status;
+ return false;
+ }
+ if (signature_len == 0) {
+ LOG(ERROR) << "Bad signature length.";
+ return false;
+ }
+ *out_len = signature_len;
+ return true;
+}
+
// Custom RSA_METHOD that uses the platform APIs for signing.
const KeyExData* RsaGetExData(const RSA* rsa) {
@@ -221,15 +265,14 @@ int RsaMethodSign(int hash_nid,
return 0;
}
- DWORD signature_len;
- SECURITY_STATUS ncrypt_status = g_cng_functions.Get().ncrypt_sign_hash()(
- ex_data->key->hNCryptKey, &rsa_padding_info, const_cast<PBYTE>(in),
- in_len, out, RSA_size(rsa), &signature_len, BCRYPT_PAD_PKCS1);
- if (FAILED(ncrypt_status) || signature_len == 0) {
+ 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.
+ if (!DoNCryptSignHash(ex_data->key->hNCryptKey, &rsa_padding_info, in,
+ in_len, out, RSA_size(rsa), &out_len_size_t,
+ BCRYPT_PAD_PKCS1)) {
OpenSSLPutNetError(FROM_HERE, ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED);
return 0;
}
- *out_len = signature_len;
+ *out_len = static_cast<unsigned>(out_len_size_t);
return 1;
}
@@ -438,11 +481,14 @@ int EcdsaMethodSign(const uint8_t* digest,
}
std::vector<uint8_t> raw_sig(order_len * 2);
- DWORD signature_len;
- SECURITY_STATUS ncrypt_status = g_cng_functions.Get().ncrypt_sign_hash()(
- ex_data->key->hNCryptKey, nullptr, const_cast<PBYTE>(digest), digest_len,
- &raw_sig[0], raw_sig.size(), &signature_len, 0);
- if (FAILED(ncrypt_status) || signature_len != raw_sig.size()) {
+ size_t raw_sig_len;
+ if (!DoNCryptSignHash(ex_data->key->hNCryptKey, nullptr, digest, digest_len,
+ &raw_sig[0], raw_sig.size(), &raw_sig_len, 0)) {
+ OpenSSLPutNetError(FROM_HERE, ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED);
+ return 0;
+ }
+ if (raw_sig_len != raw_sig.size()) {
+ LOG(ERROR) << "Bad signature length";
OpenSSLPutNetError(FROM_HERE, ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED);
return 0;
}
« 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