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 a2d7f3faaa51da8c1a703b18d0f48485c2933860..8c9589afe0d0247edd887dfa7a897d6f4f6a38c6 100644 |
--- a/net/ssl/openssl_platform_key_win.cc |
+++ b/net/ssl/openssl_platform_key_win.cc |
@@ -13,11 +13,13 @@ |
#include <vector> |
#include <openssl/bn.h> |
+#include <openssl/digest.h> |
#include <openssl/ec_key.h> |
#include <openssl/err.h> |
#include <openssl/engine.h> |
#include <openssl/evp.h> |
#include <openssl/md5.h> |
+#include <openssl/obj_mac.h> |
#include <openssl/rsa.h> |
#include <openssl/sha.h> |
@@ -33,9 +35,6 @@ |
#include "net/cert/x509_certificate.h" |
#include "net/ssl/openssl_ssl_util.h" |
-// TODO(davidben): The key needs to inform the choice of hash function in |
-// TLS 1.2. See https://crbug.com/278370. |
- |
namespace net { |
namespace { |
@@ -383,6 +382,39 @@ int RsaMethodVerifyRaw(RSA* rsa, |
return 0; |
} |
+int RsaMethodSupportsDigest(const RSA* rsa, const EVP_MD* md) { |
+ const KeyExData* ex_data = RsaGetExData(rsa); |
+ if (!ex_data) { |
+ NOTREACHED(); |
+ return 0; |
+ } |
+ |
+ int hash_nid = EVP_MD_type(md); |
+ if (ex_data->key->dwKeySpec == CERT_NCRYPT_KEY_SPEC) { |
+ // Only hashes which appear in RsaSignPKCS1 are supported. |
+ if (hash_nid != NID_sha1 && hash_nid != NID_sha256 && |
+ hash_nid != NID_sha384 && hash_nid != NID_sha512) { |
+ return 0; |
+ } |
+ |
+ // If the key is a 1024-bit RSA, assume conservatively that it may only be |
+ // able to sign SHA-1 hashes. This is the case for older Estonian ID cards |
+ // that have 1024-bit RSA keys. |
+ // |
+ // CNG does provide NCryptIsAlgSupported and NCryptEnumAlgorithms functions, |
+ // however they seem to both return NTE_NOT_SUPPORTED when querying the |
+ // NCRYPT_PROV_HANDLE at the key's NCRYPT_PROVIDER_HANDLE_PROPERTY. |
+ if (ex_data->key_length <= 1024 && hash_nid != NID_sha1) |
+ return 0; |
+ |
+ return 1; |
+ } else { |
+ // If the key is in CAPI, assume conservatively that the CAPI service |
+ // provider may only be able to sign SHA-1 hashes. |
+ return hash_nid == NID_sha1; |
+ } |
+} |
+ |
const RSA_METHOD win_rsa_method = { |
{ |
0, // references |
@@ -404,6 +436,7 @@ const RSA_METHOD win_rsa_method = { |
nullptr, // bn_mod_exp |
RSA_FLAG_OPAQUE, |
nullptr, // keygen |
+ RsaMethodSupportsDigest, |
}; |
// Custom ECDSA_METHOD that uses the platform APIs. |