diff --git a/.github/workflows/openvpn.yml b/.github/workflows/openvpn.yml index 56b37465d..b8a76ac48 100644 --- a/.github/workflows/openvpn.yml +++ b/.github/workflows/openvpn.yml @@ -30,7 +30,7 @@ jobs: fail-fast: false matrix: # List of refs to test - ref: [ release/2.6, v2.6.0 ] # 'master' is currently broken + ref: [ release/2.6, v2.6.0, master ] name: ${{ matrix.ref }} runs-on: ubuntu-latest # This should be a safe limit for the tests to run. diff --git a/src/internal.c b/src/internal.c index 480f567b2..157e44749 100644 --- a/src/internal.c +++ b/src/internal.c @@ -29682,8 +29682,6 @@ typedef struct DskeArgs { word16 verifySigSz; #endif word16 sigSz; - byte sigAlgo; - byte hashAlgo; #if !defined(NO_RSA) && defined(WC_RSA_PSS) int bits; #endif @@ -30002,8 +30000,8 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, XMEMSET(args, 0, sizeof(DskeArgs)); args->idx = *inOutIdx; args->begin = *inOutIdx; - args->sigAlgo = ssl->specs.sig_algo; - args->hashAlgo = sha_mac; + ssl->options.peerSigAlgo = ssl->specs.sig_algo; + ssl->options.peerHashAlgo = sha_mac; #ifdef WOLFSSL_ASYNC_CRYPT ssl->async->freeArgs = FreeDskeArgs; #endif @@ -30454,43 +30452,43 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, ERROR_OUT(BUFFER_ERROR, exit_dske); } - DecodeSigAlg(&input[args->idx], &args->hashAlgo, + DecodeSigAlg(&input[args->idx], &ssl->options.peerHashAlgo, &sigAlgo); #ifndef NO_RSA if (sigAlgo == rsa_pss_sa_algo && - args->sigAlgo == rsa_sa_algo) { - args->sigAlgo = sigAlgo; + ssl->options.peerSigAlgo == rsa_sa_algo) { + ssl->options.peerSigAlgo = sigAlgo; } else #endif #if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3) if (sigAlgo == sm2_sa_algo && - args->sigAlgo == ecc_dsa_sa_algo) { - args->sigAlgo = sigAlgo; + ssl->options.peerSigAlgo == ecc_dsa_sa_algo) { + ssl->options.peerSigAlgo = sigAlgo; } else #endif #ifdef HAVE_ED25519 if (sigAlgo == ed25519_sa_algo && - args->sigAlgo == ecc_dsa_sa_algo) { - args->sigAlgo = sigAlgo; + ssl->options.peerSigAlgo == ecc_dsa_sa_algo) { + ssl->options.peerSigAlgo = sigAlgo; } else #endif #ifdef HAVE_ED448 if (sigAlgo == ed448_sa_algo && - args->sigAlgo == ecc_dsa_sa_algo) { - args->sigAlgo = sigAlgo; + ssl->options.peerSigAlgo == ecc_dsa_sa_algo) { + ssl->options.peerSigAlgo = sigAlgo; } else #endif /* Signature algorithm from message must match signature * algorithm in cipher suite. */ - if (sigAlgo != args->sigAlgo) { + if (sigAlgo != ssl->options.peerSigAlgo) { ERROR_OUT(ALGO_ID_E, exit_dske); } args->idx += 2; - hashType = HashAlgoToType(args->hashAlgo); + hashType = HashAlgoToType(ssl->options.peerHashAlgo); if (hashType == WC_HASH_TYPE_NONE) { ERROR_OUT(ALGO_ID_E, exit_dske); } @@ -30498,7 +30496,7 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, /* only using sha and md5 for rsa */ #ifndef NO_OLD_TLS hashType = WC_HASH_TYPE_SHA; - if (args->sigAlgo == rsa_sa_algo) { + if (ssl->options.peerSigAlgo == rsa_sa_algo) { hashType = WC_HASH_TYPE_MD5_SHA; } #else @@ -30519,12 +30517,12 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, } ret = HashSkeData(ssl, hashType, input + args->begin, - verifySz, args->sigAlgo); + verifySz, ssl->options.peerSigAlgo); if (ret != 0) { goto exit_dske; } - switch (args->sigAlgo) + switch (ssl->options.peerSigAlgo) { #ifndef NO_RSA #ifdef WC_RSA_PSS @@ -30572,7 +30570,7 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, default: ret = ALGO_ID_E; - } /* switch (args->sigAlgo) */ + } /* switch (ssl->options.peerSigAlgo) */ #endif /* NO_DH && !HAVE_ECC && !HAVE_ED25519 && !HAVE_ED448 */ break; @@ -30624,7 +30622,7 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, args->verifySigSz); } - switch (args->sigAlgo) + switch (ssl->options.peerSigAlgo) { #ifndef NO_RSA #ifdef WC_RSA_PSS @@ -30635,7 +30633,7 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, ret = RsaVerify(ssl, args->verifySig, args->verifySigSz, &args->output, - args->sigAlgo, args->hashAlgo, + ssl->options.peerSigAlgo, ssl->options.peerHashAlgo, ssl->peerRsaKey, #ifdef HAVE_PK_CALLBACKS &ssl->buffers.peerRsaKey @@ -30673,7 +30671,7 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, #ifdef HAVE_PK_CALLBACKS if (ssl->ctx && ssl->ctx->ProcessServerSigKexCb) { ret = ssl->ctx->ProcessServerSigKexCb(ssl, - args->sigAlgo, + ssl->options.peerSigAlgo, args->verifySig, args->verifySigSz, ssl->buffers.sig.buffer, SEED_LEN, &ssl->buffers.sig.buffer[SEED_LEN], @@ -30682,7 +30680,7 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, #endif /* HAVE_PK_CALLBACKS */ if (ret == NOT_COMPILED_IN) { #if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3) - if (args->sigAlgo == sm2_sa_algo) { + if (ssl->options.peerSigAlgo == sm2_sa_algo) { ret = Sm2wSm3Verify(ssl, TLS12_SM2_SIG_ID, TLS12_SM2_SIG_ID_SZ, args->verifySig, args->verifySigSz, @@ -30835,7 +30833,7 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, /* increment index after verify is done */ args->idx += args->verifySigSz; - switch(args->sigAlgo) + switch(ssl->options.peerSigAlgo) { #ifndef NO_RSA #ifdef WC_RSA_PSS @@ -30845,13 +30843,13 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, ssl->buffers.digest.buffer, ssl->buffers.digest.length, args->output, args->sigSz, - HashAlgoToType(args->hashAlgo)); + HashAlgoToType(ssl->options.peerHashAlgo)); #else ret = wc_RsaPSS_CheckPadding_ex( ssl->buffers.digest.buffer, ssl->buffers.digest.length, args->output, args->sigSz, - HashAlgoToType(args->hashAlgo), + HashAlgoToType(ssl->options.peerHashAlgo), -1, args->bits); #endif if (ret != 0) @@ -30891,7 +30889,7 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, encSigSz = wc_EncodeSignature(encodedSig, ssl->buffers.digest.buffer, ssl->buffers.digest.length, - TypeHash(args->hashAlgo)); + TypeHash(ssl->options.peerHashAlgo)); if (encSigSz != args->sigSz || !args->output || XMEMCMP(args->output, encodedSig, min(encSigSz, MAX_ENCODED_SIG_SZ)) != 0) { @@ -36284,8 +36282,6 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, word32 sigSz; word32 idx; word32 begin; - byte hashAlgo; - byte sigAlgo; } DcvArgs; static void FreeDcvArgs(WOLFSSL* ssl, void* pArgs) @@ -36334,8 +36330,8 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, ret = 0; ssl->options.asyncState = TLS_ASYNC_BEGIN; XMEMSET(args, 0, sizeof(DcvArgs)); - args->hashAlgo = sha_mac; - args->sigAlgo = anonymous_sa_algo; + ssl->options.peerHashAlgo = sha_mac; + ssl->options.peerSigAlgo = anonymous_sa_algo; args->idx = *inOutIdx; args->begin = *inOutIdx; #ifdef WOLFSSL_ASYNC_CRYPT @@ -36366,34 +36362,34 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, ERROR_OUT(BUFFER_ERROR, exit_dcv); } - DecodeSigAlg(&input[args->idx], &args->hashAlgo, - &args->sigAlgo); + DecodeSigAlg(&input[args->idx], &ssl->options.peerHashAlgo, + &ssl->options.peerSigAlgo); args->idx += 2; } #ifndef NO_RSA else if (ssl->peerRsaKey != NULL && ssl->peerRsaKeyPresent != 0) - args->sigAlgo = rsa_sa_algo; + ssl->options.peerSigAlgo = rsa_sa_algo; #endif #ifdef HAVE_ECC else if (ssl->peerEccDsaKeyPresent) { #if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3) if (ssl->peerEccDsaKey->dp->id == ECC_SM2P256V1) { - args->sigAlgo = sm2_sa_algo; + ssl->options.peerSigAlgo = sm2_sa_algo; } else #endif { - args->sigAlgo = ecc_dsa_sa_algo; + ssl->options.peerSigAlgo = ecc_dsa_sa_algo; } } #endif #if defined(HAVE_ED25519) && !defined(NO_ED25519_CLIENT_AUTH) else if (ssl->peerEd25519KeyPresent) - args->sigAlgo = ed25519_sa_algo; + ssl->options.peerSigAlgo = ed25519_sa_algo; #endif /* HAVE_ED25519 && !NO_ED25519_CLIENT_AUTH */ #if defined(HAVE_ED448) && !defined(NO_ED448_CLIENT_AUTH) else if (ssl->peerEd448KeyPresent) - args->sigAlgo = ed448_sa_algo; + ssl->options.peerSigAlgo = ed448_sa_algo; #endif /* HAVE_ED448 && !NO_ED448_CLIENT_AUTH */ if ((args->idx - args->begin) + OPAQUE16_LEN > size) { @@ -36429,15 +36425,15 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #endif if (IsAtLeastTLSv1_2(ssl)) { - if (args->sigAlgo != ecc_dsa_sa_algo + if (ssl->options.peerSigAlgo != ecc_dsa_sa_algo #if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3) - && args->sigAlgo != sm2_sa_algo + && ssl->options.peerSigAlgo != sm2_sa_algo #endif ) { WOLFSSL_MSG("Oops, peer sent ECC key but not in verify"); } - SetDigest(ssl, args->hashAlgo); + SetDigest(ssl, ssl->options.peerHashAlgo); } } #endif /* HAVE_ECC */ @@ -36445,7 +36441,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, if (ssl->peerEd25519KeyPresent) { WOLFSSL_MSG("Doing ED25519 peer cert verify"); if (IsAtLeastTLSv1_2(ssl) && - args->sigAlgo != ed25519_sa_algo) { + ssl->options.peerSigAlgo != ed25519_sa_algo) { WOLFSSL_MSG( "Oops, peer sent ED25519 key but not in verify"); } @@ -36455,7 +36451,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, if (ssl->peerEd448KeyPresent) { WOLFSSL_MSG("Doing ED448 peer cert verify"); if (IsAtLeastTLSv1_2(ssl) && - args->sigAlgo != ed448_sa_algo) { + ssl->options.peerSigAlgo != ed448_sa_algo) { WOLFSSL_MSG( "Oops, peer sent ED448 key but not in verify"); } @@ -36477,7 +36473,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, input + args->idx, args->sz, &args->output, - args->sigAlgo, args->hashAlgo, + ssl->options.peerSigAlgo, ssl->options.peerHashAlgo, ssl->peerRsaKey, #ifdef HAVE_PK_CALLBACKS &ssl->buffers.peerRsaKey @@ -36486,7 +36482,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #endif ); if (ret >= 0) { - if (args->sigAlgo == rsa_sa_algo) + if (ssl->options.peerSigAlgo == rsa_sa_algo) args->sendSz = ret; else { args->sigSz = ret; @@ -36501,7 +36497,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, WOLFSSL_MSG("Doing ECC peer cert verify"); #if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3) - if (args->sigAlgo == sm2_sa_algo) { + if (ssl->options.peerSigAlgo == sm2_sa_algo) { ret = Sm2wSm3Verify(ssl, TLS12_SM2_SIG_ID, TLS12_SM2_SIG_ID_SZ, input + args->idx, args->sz, @@ -36596,21 +36592,21 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, if (ssl->peerRsaKey != NULL && ssl->peerRsaKeyPresent != 0) { if (IsAtLeastTLSv1_2(ssl)) { #ifdef WC_RSA_PSS - if (args->sigAlgo == rsa_pss_sa_algo) { - SetDigest(ssl, args->hashAlgo); + if (ssl->options.peerSigAlgo == rsa_pss_sa_algo) { + SetDigest(ssl, ssl->options.peerHashAlgo); #ifdef HAVE_SELFTEST ret = wc_RsaPSS_CheckPadding( ssl->buffers.digest.buffer, ssl->buffers.digest.length, args->output, args->sigSz, - HashAlgoToType(args->hashAlgo)); + HashAlgoToType(ssl->options.peerHashAlgo)); #else ret = wc_RsaPSS_CheckPadding_ex( ssl->buffers.digest.buffer, ssl->buffers.digest.length, args->output, args->sigSz, - HashAlgoToType(args->hashAlgo), -1, + HashAlgoToType(ssl->options.peerHashAlgo), -1, mp_count_bits(&ssl->peerRsaKey->n)); #endif if (ret != 0) { @@ -36631,17 +36627,17 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } #endif - if (args->sigAlgo != rsa_sa_algo) { + if (ssl->options.peerSigAlgo != rsa_sa_algo) { WOLFSSL_MSG("Oops, peer sent RSA key but not " "in verify"); } - SetDigest(ssl, args->hashAlgo); + SetDigest(ssl, ssl->options.peerHashAlgo); args->sigSz = wc_EncodeSignature(encodedSig, ssl->buffers.digest.buffer, ssl->buffers.digest.length, - TypeHash(args->hashAlgo)); + TypeHash(ssl->options.peerHashAlgo)); if (args->sendSz != args->sigSz || !args->output || XMEMCMP(args->output, encodedSig, diff --git a/src/ssl.c b/src/ssl.c index 16c61dec7..f39d62330 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -24612,111 +24612,159 @@ int wolfSSL_set1_sigalgs_list(WOLFSSL* ssl, const char* list) return SetSuitesHashSigAlgo(ssl->suites, list); } -struct WOLFSSL_HashSigInfo { - int hashAlgo; - int sigAlgo; - int nid; -} wolfssl_hash_sig_info[] = +static int HashToNid(byte hashAlgo, int* nid) { -#ifndef NO_RSA - #ifndef NO_SHA256 - { sha256_mac, rsa_sa_algo, CTC_SHA256wRSA }, - #endif - #ifdef WOLFSSL_SHA384 - { sha384_mac, rsa_sa_algo, CTC_SHA384wRSA }, - #endif - #ifdef WOLFSSL_SHA512 - { sha512_mac, rsa_sa_algo, CTC_SHA512wRSA }, - #endif - #ifdef WOLFSSL_SHA224 - { sha224_mac, rsa_sa_algo, CTC_SHA224wRSA }, - #endif - #ifndef NO_SHA - { sha_mac, rsa_sa_algo, CTC_SHAwRSA }, - #endif - #ifdef WC_RSA_PSS - #ifndef NO_SHA256 - { sha256_mac, rsa_pss_sa_algo, CTC_SHA256wRSA }, - #endif - #ifdef WOLFSSL_SHA384 - { sha384_mac, rsa_pss_sa_algo, CTC_SHA384wRSA }, - #endif - #ifdef WOLFSSL_SHA512 - { sha512_mac, rsa_pss_sa_algo, CTC_SHA512wRSA }, - #endif - #ifdef WOLFSSL_SHA224 - { sha224_mac, rsa_pss_sa_algo, CTC_SHA224wRSA }, - #endif - #endif -#endif -#ifdef HAVE_ECC - #ifndef NO_SHA256 - { sha256_mac, ecc_dsa_sa_algo, CTC_SHA256wECDSA }, - #endif - #ifdef WOLFSSL_SHA384 - { sha384_mac, ecc_dsa_sa_algo, CTC_SHA384wECDSA }, - #endif - #ifdef WOLFSSL_SHA512 - { sha512_mac, ecc_dsa_sa_algo, CTC_SHA512wECDSA }, - #endif - #ifdef WOLFSSL_SHA224 - { sha224_mac, ecc_dsa_sa_algo, CTC_SHA224wECDSA }, - #endif - #ifndef NO_SHA - { sha_mac, ecc_dsa_sa_algo, CTC_SHAwECDSA }, - #endif -#endif -#if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3) - { sm3_mac, sm2_sa_algo, CTC_SM3wSM2 }, -#endif -#ifdef HAVE_ED25519 - { no_mac, ed25519_sa_algo, CTC_ED25519 }, -#endif -#ifdef HAVE_ED448 - { no_mac, ed448_sa_algo, CTC_ED448 }, -#endif -#ifdef HAVE_PQC -#ifdef HAVE_FALCON - { no_mac, falcon_level1_sa_algo, CTC_FALCON_LEVEL1 }, - { no_mac, falcon_level5_sa_algo, CTC_FALCON_LEVEL5 }, -#endif /* HAVE_FALCON */ -#ifdef HAVE_DILITHIUM - { no_mac, dilithium_level2_sa_algo, CTC_DILITHIUM_LEVEL2 }, - { no_mac, dilithium_level3_sa_algo, CTC_DILITHIUM_LEVEL3 }, - { no_mac, dilithium_level5_sa_algo, CTC_DILITHIUM_LEVEL5 }, -#endif /* HAVE_DILITHIUM */ -#endif /* HAVE_PQC */ -#ifndef NO_DSA - #ifndef NO_SHA - { sha_mac, dsa_sa_algo, CTC_SHAwDSA }, - #endif -#endif -}; -#define WOLFSSL_HASH_SIG_INFO_SZ \ - (int)(sizeof(wolfssl_hash_sig_info)/sizeof(*wolfssl_hash_sig_info)) + int ret = WOLFSSL_SUCCESS; + /* Cast for compiler to check everything is implemented */ + switch ((enum wc_MACAlgorithm)hashAlgo) { + case no_mac: + case rmd_mac: + *nid = NID_undef; + break; + case md5_mac: + *nid = NID_md5; + break; + case sha_mac: + *nid = NID_sha1; + break; + case sha224_mac: + *nid = NID_sha224; + break; + case sha256_mac: + *nid = NID_sha256; + break; + case sha384_mac: + *nid = NID_sha384; + break; + case sha512_mac: + *nid = NID_sha512; + break; + case blake2b_mac: + *nid = NID_blake2b512; + break; + case sm3_mac: + *nid = NID_sm3; + break; + default: + ret = WOLFSSL_FAILURE; + break; + } + + return ret; +} + +static int SaToNid(byte sa, int* nid) +{ + int ret = WOLFSSL_SUCCESS; + /* Cast for compiler to check everything is implemented */ + switch ((enum SignatureAlgorithm)sa) { + case anonymous_sa_algo: + *nid = NID_undef; + break; + case rsa_sa_algo: + *nid = NID_rsaEncryption; + break; + case dsa_sa_algo: + *nid = NID_dsa; + break; + case ecc_dsa_sa_algo: + *nid = NID_X9_62_id_ecPublicKey; + break; + case rsa_pss_sa_algo: + *nid = NID_rsassaPss; + break; + case ed25519_sa_algo: +#ifdef HAVE_ED25519 + *nid = NID_ED25519; +#else + ret = WOLFSSL_FAILURE; +#endif + break; + case rsa_pss_pss_algo: + *nid = NID_rsassaPss; + break; + case ed448_sa_algo: +#ifdef HAVE_ED448 + *nid = NID_ED448; +#else + ret = WOLFSSL_FAILURE; +#endif + break; + case falcon_level1_sa_algo: + *nid = CTC_FALCON_LEVEL1; + break; + case falcon_level5_sa_algo: + *nid = CTC_FALCON_LEVEL5; + break; + case dilithium_level2_sa_algo: + *nid = CTC_DILITHIUM_LEVEL2; + break; + case dilithium_level3_sa_algo: + *nid = CTC_DILITHIUM_LEVEL3; + break; + case dilithium_level5_sa_algo: + *nid = CTC_DILITHIUM_LEVEL5; + break; + case sm2_sa_algo: + *nid = NID_sm2; + break; + case invalid_sa_algo: + default: + ret = WOLFSSL_FAILURE; + break; + } + return ret; +} + +/* This API returns the hash selected. */ int wolfSSL_get_signature_nid(WOLFSSL *ssl, int* nid) { - int i; - int ret = WOLFSSL_FAILURE; - WOLFSSL_MSG("wolfSSL_get_signature_nid"); - if (ssl == NULL) { + if (ssl == NULL || nid == NULL) { WOLFSSL_MSG("Bad function arguments"); return WOLFSSL_FAILURE; } - for (i = 0; i < WOLFSSL_HASH_SIG_INFO_SZ; i++) { - if (ssl->options.hashAlgo == wolfssl_hash_sig_info[i].hashAlgo && - ssl->options.sigAlgo == wolfssl_hash_sig_info[i].sigAlgo) { - *nid = wolfssl_hash_sig_info[i].nid; - ret = WOLFSSL_SUCCESS; - break; - } + return HashToNid(ssl->options.hashAlgo, nid); +} + +/* This API returns the signature selected. */ +int wolfSSL_get_signature_type_nid(const WOLFSSL* ssl, int* nid) +{ + WOLFSSL_MSG("wolfSSL_get_signature_type_nid"); + + if (ssl == NULL || nid == NULL) { + WOLFSSL_MSG("Bad function arguments"); + return WOLFSSL_FAILURE; } - return ret; + return SaToNid(ssl->options.sigAlgo, nid); +} + +int wolfSSL_get_peer_signature_nid(WOLFSSL* ssl, int* nid) +{ + WOLFSSL_MSG("wolfSSL_get_peer_signature_nid"); + + if (ssl == NULL || nid == NULL) { + WOLFSSL_MSG("Bad function arguments"); + return WOLFSSL_FAILURE; + } + + return HashToNid(ssl->options.peerHashAlgo, nid); +} + +int wolfSSL_get_peer_signature_type_nid(const WOLFSSL* ssl, int* nid) +{ + WOLFSSL_MSG("wolfSSL_get_peer_signature_type_nid"); + + if (ssl == NULL || nid == NULL) { + WOLFSSL_MSG("Bad function arguments"); + return WOLFSSL_FAILURE; + } + + return SaToNid(ssl->options.peerSigAlgo, nid); } #ifdef HAVE_ECC diff --git a/src/tls13.c b/src/tls13.c index 124f9a1b5..cb27926d0 100644 --- a/src/tls13.c +++ b/src/tls13.c @@ -9420,8 +9420,6 @@ typedef struct Dcv13Args { word32 sigSz; word32 idx; word32 begin; - byte hashAlgo; - byte sigAlgo; byte* sigData; word16 sigDataSz; @@ -9575,8 +9573,8 @@ static int DoTls13CertificateVerify(WOLFSSL* ssl, byte* input, ret = 0; ssl->options.asyncState = TLS_ASYNC_BEGIN; XMEMSET(args, 0, sizeof(Dcv13Args)); - args->hashAlgo = sha_mac; - args->sigAlgo = anonymous_sa_algo; + ssl->options.peerHashAlgo = sha_mac; + ssl->options.peerSigAlgo = anonymous_sa_algo; args->idx = *inOutIdx; args->begin = *inOutIdx; #ifdef WOLFSSL_ASYNC_CRYPT @@ -9625,14 +9623,14 @@ static int DoTls13CertificateVerify(WOLFSSL* ssl, byte* input, *ssl->sigSpec == WOLFSSL_CKS_SIGSPEC_NATIVE || *ssl->sigSpec == WOLFSSL_CKS_SIGSPEC_ALTERNATIVE) { #endif /* WOLFSSL_DUAL_ALG_CERTS */ - ret = DecodeTls13SigAlg(input + args->idx, &args->hashAlgo, - &args->sigAlgo); + ret = DecodeTls13SigAlg(input + args->idx, + &ssl->options.peerHashAlgo, &ssl->options.peerSigAlgo); #ifdef WOLFSSL_DUAL_ALG_CERTS } else { ret = DecodeTls13HybridSigAlg(input + args->idx, - &args->hashAlgo, - &args->sigAlgo, + &ssl->options.peerHashAlgo, + &ssl->options.peerSigAlgo, &args->altSigAlgo); } #endif /* WOLFSSL_DUAL_ALG_CERTS */ @@ -9661,7 +9659,7 @@ static int DoTls13CertificateVerify(WOLFSSL* ssl, byte* input, word16 sa; if (args->altSigAlgo == 0) - sa = args->sigAlgo; + sa = ssl->options.peerSigAlgo; else sa = args->altSigAlgo; @@ -9747,66 +9745,66 @@ static int DoTls13CertificateVerify(WOLFSSL* ssl, byte* input, /* Assume invalid unless signature algo matches the key provided */ validSigAlgo = 0; #ifdef HAVE_ED25519 - if (args->sigAlgo == ed25519_sa_algo) { + if (ssl->options.peerSigAlgo == ed25519_sa_algo) { WOLFSSL_MSG("Peer sent ED25519 sig"); validSigAlgo = (ssl->peerEd25519Key != NULL) && ssl->peerEd25519KeyPresent; } #endif #ifdef HAVE_ED448 - if (args->sigAlgo == ed448_sa_algo) { + if (ssl->options.peerSigAlgo == ed448_sa_algo) { WOLFSSL_MSG("Peer sent ED448 sig"); validSigAlgo = (ssl->peerEd448Key != NULL) && ssl->peerEd448KeyPresent; } #endif #ifdef HAVE_ECC - if (args->sigAlgo == ecc_dsa_sa_algo) { + if (ssl->options.peerSigAlgo == ecc_dsa_sa_algo) { WOLFSSL_MSG("Peer sent ECC sig"); validSigAlgo = (ssl->peerEccDsaKey != NULL) && ssl->peerEccDsaKeyPresent; } #endif #if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3) - if (args->sigAlgo == sm2_sa_algo) { + if (ssl->options.peerSigAlgo == sm2_sa_algo) { WOLFSSL_MSG("Peer sent SM2 sig"); validSigAlgo = (ssl->peerEccDsaKey != NULL) && ssl->peerEccDsaKeyPresent; } #endif #ifdef HAVE_PQC - if (args->sigAlgo == falcon_level1_sa_algo) { + if (ssl->options.peerSigAlgo == falcon_level1_sa_algo) { WOLFSSL_MSG("Peer sent Falcon Level 1 sig"); validSigAlgo = (ssl->peerFalconKey != NULL) && ssl->peerFalconKeyPresent; } - if (args->sigAlgo == falcon_level5_sa_algo) { + if (ssl->options.peerSigAlgo == falcon_level5_sa_algo) { WOLFSSL_MSG("Peer sent Falcon Level 5 sig"); validSigAlgo = (ssl->peerFalconKey != NULL) && ssl->peerFalconKeyPresent; } - if (args->sigAlgo == dilithium_level2_sa_algo) { + if (ssl->options.peerSigAlgo == dilithium_level2_sa_algo) { WOLFSSL_MSG("Peer sent Dilithium Level 2 sig"); validSigAlgo = (ssl->peerDilithiumKey != NULL) && ssl->peerDilithiumKeyPresent; } - if (args->sigAlgo == dilithium_level3_sa_algo) { + if (ssl->options.peerSigAlgo == dilithium_level3_sa_algo) { WOLFSSL_MSG("Peer sent Dilithium Level 3 sig"); validSigAlgo = (ssl->peerDilithiumKey != NULL) && ssl->peerDilithiumKeyPresent; } - if (args->sigAlgo == dilithium_level5_sa_algo) { + if (ssl->options.peerSigAlgo == dilithium_level5_sa_algo) { WOLFSSL_MSG("Peer sent Dilithium Level 5 sig"); validSigAlgo = (ssl->peerDilithiumKey != NULL) && ssl->peerDilithiumKeyPresent; } #endif #ifndef NO_RSA - if (args->sigAlgo == rsa_sa_algo) { + if (ssl->options.peerSigAlgo == rsa_sa_algo) { WOLFSSL_MSG("Peer sent PKCS#1.5 algo - not valid TLS 1.3"); ERROR_OUT(INVALID_PARAMETER, exit_dcv); } - if (args->sigAlgo == rsa_pss_sa_algo) { + if (ssl->options.peerSigAlgo == rsa_pss_sa_algo) { WOLFSSL_MSG("Peer sent RSA sig"); validSigAlgo = (ssl->peerRsaKey != NULL) && ssl->peerRsaKeyPresent; @@ -9830,10 +9828,10 @@ static int DoTls13CertificateVerify(WOLFSSL* ssl, byte* input, * don't do: * sig->length -= args->altSignatureSz; */ #define RSA3072_SIG_LEN 384 - if (args->sigAlgo == rsa_pss_sa_algo) { + if (ssl->options.peerSigAlgo == rsa_pss_sa_algo) { sig->length = RSA3072_SIG_LEN; } - else if (args->sigAlgo == ecc_dsa_sa_algo) { + else if (ssl->options.peerSigAlgo == ecc_dsa_sa_algo) { word32 tmpIdx = args->idx; sig->length = wc_SignatureGetSize(WC_SIGNATURE_TYPE_ECC, ssl->peerEccDsaKey, @@ -9873,11 +9871,11 @@ static int DoTls13CertificateVerify(WOLFSSL* ssl, byte* input, if (ret != 0) goto exit_dcv; #if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3) - if (args->sigAlgo != sm2_sa_algo) + if (ssl->options.peerSigAlgo != sm2_sa_algo) #endif { ret = CreateECCEncodedSig(args->sigData, - args->sigDataSz, args->hashAlgo); + args->sigDataSz, ssl->options.peerHashAlgo); if (ret < 0) goto exit_dcv; args->sigDataSz = (word16)ret; @@ -9957,7 +9955,7 @@ static int DoTls13CertificateVerify(WOLFSSL* ssl, byte* input, #ifndef NO_RSA if (ssl->peerRsaKey != NULL && ssl->peerRsaKeyPresent != 0) { ret = RsaVerify(ssl, sig->buffer, (word32)sig->length, &args->output, - args->sigAlgo, args->hashAlgo, ssl->peerRsaKey, + ssl->options.peerSigAlgo, ssl->options.peerHashAlgo, ssl->peerRsaKey, #ifdef HAVE_PK_CALLBACKS &ssl->buffers.peerRsaKey #else @@ -9973,7 +9971,7 @@ static int DoTls13CertificateVerify(WOLFSSL* ssl, byte* input, #ifdef HAVE_ECC if (ssl->peerEccDsaKeyPresent) { #if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3) - if (args->sigAlgo == sm2_sa_algo) { + if (ssl->options.peerSigAlgo == sm2_sa_algo) { ret = Sm2wSm3Verify(ssl, TLS13_SM2_SIG_ID, TLS13_SM2_SIG_ID_SZ, input + args->idx, args->sz, args->sigData, args->sigDataSz, @@ -10153,8 +10151,8 @@ static int DoTls13CertificateVerify(WOLFSSL* ssl, byte* input, { #if !defined(NO_RSA) && defined(WC_RSA_PSS) if (ssl->peerRsaKey != NULL && ssl->peerRsaKeyPresent != 0) { - ret = CheckRSASignature(ssl, args->sigAlgo, args->hashAlgo, - args->output, args->sendSz); + ret = CheckRSASignature(ssl, ssl->options.peerSigAlgo, + ssl->options.peerHashAlgo, args->output, args->sendSz); if (ret != 0) goto exit_dcv; diff --git a/tests/api.c b/tests/api.c index 98492b6a2..9ec4d63d5 100644 --- a/tests/api.c +++ b/tests/api.c @@ -6360,6 +6360,9 @@ static int test_ssl_memio_do_handshake(test_ssl_memio_ctx* ctx, int max_rounds, err = wolfSSL_get_error(ctx->c_ssl, ret); if (err != WOLFSSL_ERROR_WANT_READ && err != WOLFSSL_ERROR_WANT_WRITE) { + char buff[WOLFSSL_MAX_ERROR_SZ]; + fprintf(stderr, "error = %d, %s\n", err, + wolfSSL_ERR_error_string(err, buff)); failing_c = 1; hs_c = 1; if (failing_c && failing_s) { @@ -6379,6 +6382,9 @@ static int test_ssl_memio_do_handshake(test_ssl_memio_ctx* ctx, int max_rounds, err = wolfSSL_get_error(ctx->s_ssl, ret); if (err != WOLFSSL_ERROR_WANT_READ && err != WOLFSSL_ERROR_WANT_WRITE) { + char buff[WOLFSSL_MAX_ERROR_SZ]; + fprintf(stderr, "error = %d, %s\n", err, + wolfSSL_ERR_error_string(err, buff)); failing_s = 1; hs_s = 1; if (failing_c && failing_s) { @@ -69803,6 +69809,168 @@ static int test_read_write_hs(void) return EXPECT_RESULT(); } +#if defined(HAVE_SSL_MEMIO_TESTS_DEPENDENCIES) && defined(OPENSSL_EXTRA) +static const char* test_get_signature_nid_siglag; +static int test_get_signature_nid_sig; +static int test_get_signature_nid_hash; + +static int test_get_signature_nid_ssl_ready(WOLFSSL* ssl) +{ + EXPECT_DECLS; + ExpectIntEQ(wolfSSL_set_cipher_list(ssl, "ALL"), WOLFSSL_SUCCESS); + if (!wolfSSL_is_server(ssl)) { + ExpectIntEQ(wolfSSL_set1_sigalgs_list(ssl, + test_get_signature_nid_siglag), WOLFSSL_SUCCESS); + } + return EXPECT_RESULT(); +} + +static int test_get_signature_nid_on_hs_client(WOLFSSL_CTX **ctx, WOLFSSL **ssl) +{ + EXPECT_DECLS; + int nid = 0; + (void)ctx; + if (XSTRSTR(wolfSSL_get_cipher(*ssl), "TLS_RSA_") == NULL) { + ExpectIntEQ(SSL_get_peer_signature_type_nid(*ssl, &nid), WOLFSSL_SUCCESS); + ExpectIntEQ(nid, test_get_signature_nid_sig); + ExpectIntEQ(SSL_get_peer_signature_nid(*ssl, &nid), WOLFSSL_SUCCESS); + ExpectIntEQ(nid, test_get_signature_nid_hash); + } + else /* No sigalg info on static ciphersuite */ + return TEST_SUCCESS; + return EXPECT_RESULT(); +} + +static int test_get_signature_nid_on_hs_server(WOLFSSL_CTX **ctx, WOLFSSL **ssl) +{ + EXPECT_DECLS; + int nid = 0; + (void)ctx; + ExpectIntEQ(SSL_get_signature_type_nid(*ssl, &nid), WOLFSSL_SUCCESS); + ExpectIntEQ(nid, test_get_signature_nid_sig); + ExpectIntEQ(SSL_get_signature_nid(*ssl, &nid), WOLFSSL_SUCCESS); + ExpectIntEQ(nid, test_get_signature_nid_hash); + return EXPECT_RESULT(); +} +#endif + +static int test_get_signature_nid(void) +{ + EXPECT_DECLS; +#if defined(HAVE_SSL_MEMIO_TESTS_DEPENDENCIES) && defined(OPENSSL_EXTRA) + test_ssl_cbf client_cbf; + test_ssl_cbf server_cbf; + size_t i; +#define TGSN_TLS12_RSA(sigalg, sig_nid, hash_nid) \ + { sigalg, sig_nid, hash_nid, WOLFSSL_TLSV1_2, svrCertFile, svrKeyFile, \ + caCertFile } +#define TGSN_TLS12_ECDSA(sigalg, sig_nid, hash_nid) \ + { sigalg, sig_nid, hash_nid, WOLFSSL_TLSV1_2, eccCertFile, eccKeyFile, \ + caEccCertFile } +#define TGSN_TLS13_RSA(sigalg, sig_nid, hash_nid) \ + { sigalg, sig_nid, hash_nid, WOLFSSL_TLSV1_3, svrCertFile, svrKeyFile, \ + caCertFile } +#define TGSN_TLS13_ECDSA(sigalg, sig_nid, hash_nid) \ + { sigalg, sig_nid, hash_nid, WOLFSSL_TLSV1_3, eccCertFile, eccKeyFile, \ + caEccCertFile } +#define TGSN_TLS13_ED25519(sigalg, sig_nid, hash_nid) \ + { sigalg, sig_nid, hash_nid, WOLFSSL_TLSV1_3, edCertFile, edKeyFile, \ + caEdCertFile } +#define TGSN_TLS13_ED448(sigalg, sig_nid, hash_nid) \ + { sigalg, sig_nid, hash_nid, WOLFSSL_TLSV1_3, ed448CertFile, ed448KeyFile, \ + caEd448CertFile } + struct { + const char* siglag; + int sig_nid; + int hash_nid; + int tls_ver; + const char* server_cert; + const char* server_key; + const char* client_ca; + } params[] = { +#ifndef NO_RSA + #ifndef NO_SHA256 + TGSN_TLS12_RSA("RSA+SHA256", NID_rsaEncryption, NID_sha256), + #ifdef WC_RSA_PSS + TGSN_TLS12_RSA("RSA-PSS+SHA256", NID_rsassaPss, NID_sha256), + TGSN_TLS13_RSA("RSA-PSS+SHA256", NID_rsassaPss, NID_sha256), + #endif + #endif + #ifdef WOLFSSL_SHA512 + TGSN_TLS12_RSA("RSA+SHA512", NID_rsaEncryption, NID_sha512), + #ifdef WC_RSA_PSS + TGSN_TLS12_RSA("RSA-PSS+SHA512", NID_rsassaPss, NID_sha512), + TGSN_TLS13_RSA("RSA-PSS+SHA512", NID_rsassaPss, NID_sha512), + #endif + #endif +#endif +#ifdef HAVE_ECC + #ifndef NO_SHA256 + TGSN_TLS12_ECDSA("ECDSA+SHA256", NID_X9_62_id_ecPublicKey, NID_sha256), + TGSN_TLS13_ECDSA("ECDSA+SHA256", NID_X9_62_id_ecPublicKey, NID_sha256), + #endif +#endif +#ifdef HAVE_ED25519 + TGSN_TLS13_ED25519("ED25519", NID_ED25519, NID_sha512), +#endif +#ifdef HAVE_ED448 + TGSN_TLS13_ED448("ED448", NID_ED448, NID_sha512), +#endif + }; + + printf("\n"); + + for (i = 0; i < XELEM_CNT(params) && !EXPECT_FAIL(); i++) { + + XMEMSET(&client_cbf, 0, sizeof(client_cbf)); + XMEMSET(&server_cbf, 0, sizeof(server_cbf)); + + printf("Testing %s with %s...", tls_desc[params[i].tls_ver], + params[i].siglag); + + switch (params[i].tls_ver) { +#ifndef WOLFSSL_NO_TLS12 + case WOLFSSL_TLSV1_2: + client_cbf.method = wolfTLSv1_2_client_method; + server_cbf.method = wolfTLSv1_2_server_method; + break; +#endif +#ifdef WOLFSSL_TLS13 + case WOLFSSL_TLSV1_3: + client_cbf.method = wolfTLSv1_3_client_method; + server_cbf.method = wolfTLSv1_3_server_method; + break; +#endif + default: + printf("skipping\n"); + continue; + } + + test_get_signature_nid_siglag = params[i].siglag; + test_get_signature_nid_sig = params[i].sig_nid; + test_get_signature_nid_hash = params[i].hash_nid; + + client_cbf.ssl_ready = test_get_signature_nid_ssl_ready; + server_cbf.ssl_ready = test_get_signature_nid_ssl_ready; + + client_cbf.on_handshake = test_get_signature_nid_on_hs_client; + server_cbf.on_handshake = test_get_signature_nid_on_hs_server; + + server_cbf.certPemFile = params[i].server_cert; + server_cbf.keyPemFile = params[i].server_key; + + client_cbf.caPemFile = params[i].client_ca; + + ExpectIntEQ(test_wolfSSL_client_server_nofail_memio(&client_cbf, + &server_cbf, NULL), TEST_SUCCESS); + if (EXPECT_SUCCESS()) + printf("passed\n"); + } + +#endif + return EXPECT_RESULT(); +} + /*----------------------------------------------------------------------------* | Main *----------------------------------------------------------------------------*/ @@ -71111,6 +71279,7 @@ TEST_CASE testCases[] = { TEST_DECL(test_tls_multi_handshakes_one_record), TEST_DECL(test_write_dup), TEST_DECL(test_read_write_hs), + TEST_DECL(test_get_signature_nid), /* This test needs to stay at the end to clean up any caches allocated. */ TEST_DECL(test_wolfSSL_Cleanup) }; diff --git a/tests/utils.h b/tests/utils.h index 601c56ca5..cf57e336f 100644 --- a/tests/utils.h +++ b/tests/utils.h @@ -431,3 +431,9 @@ void join_thread(THREAD_TYPE thread) THREAD_CHECK_RET(wolfSSL_JoinThread(thread)); } #endif /* SINGLE_THREADED */ + +/* These correspond to WOLFSSL_SSLV3...WOLFSSL_DTLSV1_3 */ +const char* tls_desc[] = { + "SSLv3", "TLSv1.0", "TLSv1.1", "TLSv1.2", "TLSv1.3", + "DTLSv1.0", "DTLSv1.2", "DTLSv1.3" +}; diff --git a/wolfssl/internal.h b/wolfssl/internal.h index c3c7577c1..8b65d0a29 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -4814,6 +4814,8 @@ struct Options { byte cipherSuite; /* second byte, actual suite */ byte hashAlgo; /* selected hash algorithm */ byte sigAlgo; /* selected sig algorithm */ + byte peerHashAlgo; /* peer's chosen hash algo */ + byte peerSigAlgo; /* peer's chosen sig algo */ byte serverState; byte clientState; byte handShakeState; diff --git a/wolfssl/openssl/ssl.h b/wolfssl/openssl/ssl.h index 77874c770..5cd96e26f 100644 --- a/wolfssl/openssl/ssl.h +++ b/wolfssl/openssl/ssl.h @@ -340,6 +340,9 @@ typedef STACK_OF(ACCESS_DESCRIPTION) AUTHORITY_INFO_ACCESS; #define SSL_CTX_set1_sigalgs_list wolfSSL_CTX_set1_sigalgs_list #define SSL_set1_sigalgs_list wolfSSL_set1_sigalgs_list #define SSL_get_signature_nid wolfSSL_get_signature_nid +#define SSL_get_signature_type_nid wolfSSL_get_signature_type_nid +#define SSL_get_peer_signature_nid wolfSSL_get_peer_signature_nid +#define SSL_get_peer_signature_type_nid wolfSSL_get_peer_signature_type_nid #define SSL_CTX_set1_groups wolfSSL_CTX_set1_groups #define SSL_set1_groups wolfSSL_set1_groups diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h index 16fb93028..7099fa1f2 100644 --- a/wolfssl/ssl.h +++ b/wolfssl/ssl.h @@ -1132,6 +1132,10 @@ WOLFSSL_API int wolfSSL_CTX_up_ref(WOLFSSL_CTX* ctx); #ifdef OPENSSL_EXTRA WOLFSSL_API int wolfSSL_CTX_set_ecdh_auto(WOLFSSL_CTX* ctx, int onoff); WOLFSSL_API int wolfSSL_get_signature_nid(WOLFSSL* ssl, int* nid); +WOLFSSL_API int wolfSSL_get_signature_type_nid(const WOLFSSL* ssl, int* nid); +WOLFSSL_API int wolfSSL_get_peer_signature_nid(WOLFSSL* ssl, int* nid); +WOLFSSL_API int wolfSSL_get_peer_signature_type_nid(const WOLFSSL* ssl, + int* nid); WOLFSSL_API int wolfSSL_CTX_set1_sigalgs_list(WOLFSSL_CTX* ctx, const char* list); WOLFSSL_API int wolfSSL_set1_sigalgs_list(WOLFSSL* ssl, const char* list);