diff --git a/src/internal.c b/src/internal.c index eb990b128..128de8947 100644 --- a/src/internal.c +++ b/src/internal.c @@ -27390,7 +27390,40 @@ static byte MinHashAlgo(WOLFSSL* ssl) return sha_mac; } -int PickHashSigAlgo(WOLFSSL* ssl, const byte* hashSigAlgo, word32 hashSigAlgoSz) +/* Check if a given peer hashSigAlgo is supported in our ssl->suites or + * ssl->ctx->suites. + * + * Returns 1 on match. + * Returns 0 otherwise. + * */ +static int SupportedHashSigAlgo(WOLFSSL* ssl, const byte * hashSigAlgo) +{ + const Suites * suites = NULL; + word32 i = 0; + + if (ssl == NULL || hashSigAlgo == NULL) { + return 0; + } + + suites = WOLFSSL_SUITES(ssl); + + if (suites == NULL || suites->hashSigAlgoSz == 0) { + return 0; + } + + for (i = 0; (i+1) < suites->hashSigAlgoSz; i += HELLO_EXT_SIGALGO_SZ) { + if (XMEMCMP(&suites->hashSigAlgo[i], hashSigAlgo, + HELLO_EXT_SIGALGO_SZ) == 0) { + /* Match found. */ + return 1; + } + } + + return 0; +} + +int PickHashSigAlgo(WOLFSSL* ssl, const byte* hashSigAlgo, word32 hashSigAlgoSz, + int matchSuites) { word32 i; int ret = WC_NO_ERR_TRACE(MATCH_SUITE_ERROR); @@ -27431,6 +27464,14 @@ int PickHashSigAlgo(WOLFSSL* ssl, const byte* hashSigAlgo, word32 hashSigAlgoSz) if (!MatchSigAlgo(ssl, sigAlgo)) continue; + if (matchSuites) { + /* Keep looking if peer algorithm isn't supported in our ssl->suites + * or ssl->ctx->suites. */ + if (!SupportedHashSigAlgo(ssl, &hashSigAlgo[i])) { + continue; + } + } + #ifdef HAVE_ED25519 if (ssl->pkCurveOID == ECC_ED25519_OID) { /* Matched Ed25519 - set chosen and finished. */ @@ -30051,7 +30092,7 @@ static int HashSkeData(WOLFSSL* ssl, enum wc_HashType hashType, if ((len > size) || ((*inOutIdx - begin) + len > size)) return BUFFER_ERROR; - if (PickHashSigAlgo(ssl, input + *inOutIdx, len) != 0 && + if (PickHashSigAlgo(ssl, input + *inOutIdx, len, 0) != 0 && ssl->buffers.certificate && ssl->buffers.certificate->buffer) { #ifdef HAVE_PK_CALLBACKS @@ -31086,6 +31127,15 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, ERROR_OUT(BUFFER_ERROR, exit_dske); } + /* Check if hashSigAlgo in Server Key Exchange is supported + * in our ssl->suites or ssl->ctx->suites. */ + if (!SupportedHashSigAlgo(ssl, &input[args->idx])) { + #ifdef WOLFSSL_EXTRA_ALERTS + SendAlert(ssl, alert_fatal, handshake_failure); + #endif + ERROR_OUT(MATCH_SUITE_ERROR, exit_dske); + } + DecodeSigAlg(&input[args->idx], &ssl->options.peerHashAlgo, &sigAlgo); #ifndef NO_RSA @@ -35937,7 +35987,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, if (ret != 0) return ret; ret = PickHashSigAlgo(ssl, peerSuites->hashSigAlgo, - peerSuites->hashSigAlgoSz); + peerSuites->hashSigAlgoSz, 1); if (ret != 0) return ret; @@ -36300,7 +36350,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, ret = SetCipherSpecs(ssl); if (ret == 0) { ret = PickHashSigAlgo(ssl, clSuites->hashSigAlgo, - clSuites->hashSigAlgoSz); + clSuites->hashSigAlgoSz, 0); } } else if (ret == 0) { diff --git a/src/tls13.c b/src/tls13.c index 297e250c3..ef37c29ab 100644 --- a/src/tls13.c +++ b/src/tls13.c @@ -5740,7 +5740,7 @@ static int DoTls13CertificateRequest(WOLFSSL* ssl, const byte* input, #endif ) { if (PickHashSigAlgo(ssl, peerSuites.hashSigAlgo, - peerSuites.hashSigAlgoSz) != 0) { + peerSuites.hashSigAlgoSz, 0) != 0) { WOLFSSL_ERROR_VERBOSE(INVALID_PARAMETER); return INVALID_PARAMETER; } diff --git a/wolfssl/internal.h b/wolfssl/internal.h index 7bac1f6cf..f017abaae 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -2180,7 +2180,7 @@ WOLFSSL_LOCAL int DoServerHello(WOLFSSL* ssl, const byte* input, word32* inOutI WOLFSSL_LOCAL int CompleteServerHello(WOLFSSL *ssl); WOLFSSL_LOCAL int CheckVersion(WOLFSSL *ssl, ProtocolVersion pv); WOLFSSL_LOCAL int PickHashSigAlgo(WOLFSSL* ssl, const byte* hashSigAlgo, - word32 hashSigAlgoSz); + word32 hashSigAlgoSz, int matchSuites); #if defined(WOLF_PRIVATE_KEY_ID) && !defined(NO_CHECK_PRIVATE_KEY) WOLFSSL_LOCAL int CreateDevPrivateKey(void** pkey, byte* data, word32 length, int hsType, int label, int id,