From d21603334b3e0f2431ca0a3d5e4a3d7521284866 Mon Sep 17 00:00:00 2001 From: David Garske Date: Wed, 24 Oct 2018 09:59:59 -0700 Subject: [PATCH] Added build option `USE_ECDSA_KEYSZ_HASH_ALGO` to alter the hash algorithm selection for `ecc_dsa_sa_algo`. With this build option we try and choose a hash algorithm digest size that matches the ephemeral key size, if not found then will match on next highest. We've seen cases with some Windows based TLS client's where they do not properly support hashing a smaller ephemeral key with a larger hash digest size (such as P-256 key and SHA512 hash). --- src/internal.c | 58 +++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 55 insertions(+), 3 deletions(-) diff --git a/src/internal.c b/src/internal.c index d4455b5d2..b584f0495 100644 --- a/src/internal.c +++ b/src/internal.c @@ -16512,9 +16512,60 @@ void PickHashSigAlgo(WOLFSSL* ssl, const byte* hashSigAlgo, ssl->suites->hashAlgo = sha512_mac; break; } + #endif + /* For ECDSA the `USE_ECDSA_KEYSZ_HASH_ALGO` build option will choose a hash + * algorithm that matches the ephemeral ECDHE key size or the next higest + * available. This workaround resolves issue with some peer's that do not + * properly support scenarios such as a P-256 key hashed with SHA512. + */ + #if defined(HAVE_ECC) && defined(USE_ECDSA_KEYSZ_HASH_ALGO) + if (sigAlgo == ssl->suites->sigAlgo && sigAlgo == ecc_dsa_sa_algo) { + word32 digestSz = 0; + switch (hashAlgo) { + #ifndef NO_SHA + case sha_mac: + digestSz = WC_SHA_DIGEST_SIZE; + break; + #endif + #ifndef NO_SHA256 + case sha256_mac: + digestSz = WC_SHA256_DIGEST_SIZE; + break; + #endif + #ifdef WOLFSSL_SHA384 + case sha384_mac: + digestSz = WC_SHA384_DIGEST_SIZE; + break; + #endif + #ifdef WOLFSSL_SHA512 + case sha512_mac: + digestSz = WC_SHA512_DIGEST_SIZE; + break; + #endif + default: + continue; + } + + /* For ecc_dsa_sa_algo, pick hash algo that is curve size unless + algorithm in not compiled in, then choose next highest */ + if (digestSz == ssl->eccTempKeySz) { + ssl->suites->hashAlgo = hashAlgo; + ssl->suites->sigAlgo = sigAlgo; + return; /* done selected sig/hash algorithms */ + } + /* not strong enough, so keep checking hashSigAlso list */ + if (digestSz < ssl->eccTempKeySz) + continue; + + /* mark as highest and check remainder of hashSigAlgo list */ + ssl->suites->hashAlgo = hashAlgo; + ssl->suites->sigAlgo = sigAlgo; + } + else #endif if (sigAlgo == ssl->suites->sigAlgo || (sigAlgo == rsa_pss_sa_algo && ssl->suites->sigAlgo == rsa_sa_algo)) { + /* pick highest available between both server and client */ switch (hashAlgo) { case sha_mac: #ifndef NO_SHA256 @@ -16526,8 +16577,10 @@ void PickHashSigAlgo(WOLFSSL* ssl, const byte* hashSigAlgo, #ifdef WOLFSSL_SHA512 case sha512_mac: #endif + /* not strong enough, so keep checking hashSigAlso list */ if (hashAlgo < ssl->suites->hashAlgo) continue; + /* mark as highest and check remainder of hashSigAlgo list */ ssl->suites->hashAlgo = hashAlgo; ssl->suites->sigAlgo = sigAlgo; break; @@ -16540,13 +16593,12 @@ void PickHashSigAlgo(WOLFSSL* ssl, const byte* hashSigAlgo, ssl->suites->hashAlgo = ssl->specs.mac_algorithm; } } - } #endif /* !defined(NO_WOLFSSL_SERVER) || !defined(NO_CERTS) */ #if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA) - /* Initialisze HandShakeInfo */ + /* Initialize HandShakeInfo */ void InitHandShakeInfo(HandShakeInfo* info, WOLFSSL* ssl) { int i; @@ -16599,7 +16651,7 @@ void PickHashSigAlgo(WOLFSSL* ssl, const byte* hashSigAlgo, #ifdef WOLFSSL_CALLBACKS - /* Initialisze TimeoutInfo */ + /* Initialize TimeoutInfo */ void InitTimeoutInfo(TimeoutInfo* info) { int i;