diff --git a/configure.ac b/configure.ac index 5f392d326..22d95c05e 100644 --- a/configure.ac +++ b/configure.ac @@ -256,7 +256,6 @@ AC_ARG_ENABLE([tls13], if test "$ENABLED_TLS13" = "yes" then AM_CFLAGS="-DWOLFSSL_TLS13 -DHAVE_TLS_EXTENSIONS -DHAVE_FFDHE_2048 $AM_CFLAGS" - AM_CFLAGS="-DWC_RSA_PSS $AM_CFLAGS" fi # check if TLS v1.3 was enabled for conditionally running tls13.test script @@ -1332,6 +1331,28 @@ fi AM_CONDITIONAL([BUILD_RSA], [test "x$ENABLED_RSA" = "xyes"]) +# RSA-PSS +AC_ARG_ENABLE([rsapss], + [ --enable-rsapss Enable RSA-PSS (default: disabled)], + [ ENABLED_RSAPSS=$enableval ], + [ ENABLED_RSAPSS=no ] + ) + +if test "$ENABLED_RSA" = "no" +then + ENABLED_RSAPSS="no" +else + if test "$ENABLED_TLS13" = "yes" + then + ENABLED_RSAPSS="yes" + fi +fi +if test "$ENABLED_RSAPSS" = "yes" +then + AM_CFLAGS="$AM_CFLAGS -DWC_RSA_PSS" +fi + + # DH AC_ARG_ENABLE([dh], [AS_HELP_STRING([--enable-dh],[Enable DH (default: enabled)])], @@ -3658,6 +3679,7 @@ echo " * Poly1305: $ENABLED_POLY1305" echo " * LEANPSK: $ENABLED_LEANPSK" echo " * LEANTLS: $ENABLED_LEANTLS" echo " * RSA: $ENABLED_RSA" +echo " * RSA-PSS: $ENABLED_RSAPSS" echo " * DSA: $ENABLED_DSA" echo " * DH: $ENABLED_DH" echo " * ECC: $ENABLED_ECC" diff --git a/src/internal.c b/src/internal.c index efa05d6b4..a634f9210 100755 --- a/src/internal.c +++ b/src/internal.c @@ -1693,10 +1693,12 @@ void InitCipherSpecs(CipherSpecs* cs) } static void InitSuitesHashSigAlgo(Suites* suites, int haveECDSAsig, - int haveRSAsig, int haveAnon) + int haveRSAsig, int haveAnon, int tls1_2) { int idx = 0; + (void)tls1_2; + if (haveECDSAsig) { #ifdef WOLFSSL_SHA512 suites->hashSigAlgo[idx++] = sha512_mac; @@ -1718,6 +1720,22 @@ static void InitSuitesHashSigAlgo(Suites* suites, int haveECDSAsig, } if (haveRSAsig) { + #ifdef WC_RSA_PSS + if (tls1_2) { + #ifdef WOLFSSL_SHA512 + suites->hashSigAlgo[idx++] = rsa_pss_sa_algo; + suites->hashSigAlgo[idx++] = sha512_mac; + #endif + #ifdef WOLFSSL_SHA384 + suites->hashSigAlgo[idx++] = rsa_pss_sa_algo; + suites->hashSigAlgo[idx++] = sha384_mac; + #endif + #ifndef NO_SHA256 + suites->hashSigAlgo[idx++] = rsa_pss_sa_algo; + suites->hashSigAlgo[idx++] = sha256_mac; + #endif + } + #endif #ifdef WOLFSSL_SHA512 suites->hashSigAlgo[idx++] = sha512_mac; suites->hashSigAlgo[idx++] = rsa_sa_algo; @@ -2615,9 +2633,67 @@ void InitSuites(Suites* suites, ProtocolVersion pv, word16 haveRSA, suites->suiteSz = idx; - InitSuitesHashSigAlgo(suites, haveECDSAsig, haveRSAsig, 0); + InitSuitesHashSigAlgo(suites, haveECDSAsig, haveRSAsig, 0, tls1_2); } +#if !defined(NO_WOLFSSL_SERVER) || !defined(NO_CERTS) +/* Decode the signature algorithm. + * + * input The encoded signature algorithm. + * hashalgo The hash algorithm. + * hsType The signature type. + */ +static INLINE void DecodeSigAlg(const byte* input, byte* hashAlgo, byte* hsType) +{ + switch (input[0]) { + #ifdef WC_RSA_PSS + case rsa_pss_sa_algo: + /* PSS signatures: 0x080[4-6] */ + if (input[1] <= sha512_mac) { + *hsType = input[0]; + *hashAlgo = input[1]; + } + break; + #endif + /* ED25519: 0x0807 */ + /* ED448: 0x0808 */ + default: + *hashAlgo = input[0]; + *hsType = input[1]; + break; + } +} +#endif /* !NO_WOLFSSL_SERVER || !NO_CERTS */ + +#if !defined(NO_DH) || defined(HAVE_ECC) + +static enum wc_HashType HashType(int hashAlgo) +{ + switch (hashAlgo) { + #ifdef WOLFSSL_SHA512 + case sha512_mac: + return WC_HASH_TYPE_SHA512; + #endif + #ifdef WOLFSSL_SHA384 + case sha384_mac: + return WC_HASH_TYPE_SHA384; + #endif + #ifndef NO_SHA256 + case sha256_mac: + return WC_HASH_TYPE_SHA256; + #endif + #if !defined(NO_SHA) && (!defined(NO_OLD_TLS) || \ + defined(WOLFSSL_ALLOW_TLS_SHA1)) + case sha_mac: + return WC_HASH_TYPE_SHA; + #endif + default: + WOLFSSL_MSG("Bad hash sig algo"); + break; + } + + return WC_HASH_TYPE_NONE; +} #ifndef NO_CERTS @@ -2729,11 +2805,132 @@ void FreeX509(WOLFSSL_X509* x509) FreeAltNames(x509->altNames, NULL); } +#endif /* !NO_DH || HAVE_ECC */ + +#if !defined(NO_RSA) || defined(HAVE_ECC) +/* Encode the signature algorithm into buffer. + * + * hashalgo The hash algorithm. + * hsType The signature type. + * output The buffer to encode into. + */ +static INLINE void EncodeSigAlg(byte hashAlgo, byte hsType, byte* output) +{ + switch (hsType) { +#ifdef HAVE_ECC + case ecc_dsa_sa_algo: + output[0] = hashAlgo; + output[1] = ecc_dsa_sa_algo; + break; +#endif +#ifndef NO_RSA + case rsa_sa_algo: + output[0] = hashAlgo; + output[1] = rsa_sa_algo; + break; + #ifdef WC_RSA_PSS + /* PSS signatures: 0x080[4-6] */ + case rsa_pss_sa_algo: + output[0] = rsa_pss_sa_algo; + output[1] = hashAlgo; + break; + #endif +#endif + /* ED25519: 0x0807 */ + /* ED448: 0x0808 */ + } +} +static void SetDigest(WOLFSSL* ssl, int hashAlgo) +{ + switch (hashAlgo) { + #ifndef NO_SHA + case sha_mac: + ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha; + ssl->buffers.digest.length = SHA_DIGEST_SIZE; + break; + #endif /* !NO_SHA */ + #ifndef NO_SHA256 + case sha256_mac: + ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha256; + ssl->buffers.digest.length = SHA256_DIGEST_SIZE; + break; + #endif /* !NO_SHA256 */ + #ifdef WOLFSSL_SHA384 + case sha384_mac: + ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha384; + ssl->buffers.digest.length = SHA384_DIGEST_SIZE; + break; + #endif /* WOLFSSL_SHA384 */ + #ifdef WOLFSSL_SHA512 + case sha512_mac: + ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha512; + ssl->buffers.digest.length = SHA512_DIGEST_SIZE; + break; + #endif /* WOLFSSL_SHA512 */ + } /* switch */ +} +#endif #ifndef NO_RSA +static int TypeHash(int hashAlgo) +{ + switch (hashAlgo) { + #ifdef WOLFSSL_SHA512 + case sha512_mac: + return SHA512h; + #endif + #ifdef WOLFSSL_SHA384 + case sha384_mac: + return SHA384h; + #endif + #ifndef NO_SHA256 + case sha256_mac: + return SHA256h; + #endif + #ifndef NO_SHA + case sha_mac: + return SHAh; + #endif + } + + return 0; +} + +#if defined(WC_RSA_PSS) +static int ConvertHashPss(int hashAlgo, enum wc_HashType* hashType, int* mgf) { + switch (hashAlgo) { + #ifdef WOLFSSL_SHA512 + case sha512_mac: + *hashType = WC_HASH_TYPE_SHA512; + if (mgf != NULL) + *mgf = WC_MGF1SHA512; + break; + #endif + #ifdef WOLFSSL_SHA384 + case sha384_mac: + *hashType = WC_HASH_TYPE_SHA384; + if (mgf != NULL) + *mgf = WC_MGF1SHA384; + break; + #endif + #ifndef NO_SHA256 + case sha256_mac: + *hashType = WC_HASH_TYPE_SHA256; + if (mgf != NULL) + *mgf = WC_MGF1SHA256; + break; + #endif + default: + return BAD_FUNC_ARG; + } + + return 0; +} +#endif int RsaSign(WOLFSSL* ssl, const byte* in, word32 inSz, byte* out, - word32* outSz, RsaKey* key, const byte* keyBuf, word32 keySz, void* ctx) + word32* outSz, int sigAlgo, int hashAlgo, RsaKey* key, + const byte* keyBuf, word32 keySz, void* ctx) { int ret; @@ -2741,9 +2938,35 @@ int RsaSign(WOLFSSL* ssl, const byte* in, word32 inSz, byte* out, (void)keyBuf; (void)keySz; (void)ctx; + (void)sigAlgo; + (void)hashAlgo; WOLFSSL_ENTER("RsaSign"); +#if defined(WC_RSA_PSS) + if (sigAlgo == rsa_pss_sa_algo) { + enum wc_HashType hashType = WC_HASH_TYPE_NONE; + int mgf = 0; + + ret = ConvertHashPss(hashAlgo, &hashType, &mgf); + if (ret != 0) + return ret; + + #if defined(HAVE_PK_CALLBACKS) + if (ssl->ctx->RsaPssSignCb) { + ret = ssl->ctx->RsaPssSignCb(ssl, in, inSz, out, outSz, + TypeHash(hashAlgo), mgf, + keyBuf, keySz, ctx); + } + else + #endif + { + ret = wc_RsaPSS_Sign(in, inSz, out, *outSz, hashType, mgf, key, + ssl->rng); + } + } + else +#endif #if defined(HAVE_PK_CALLBACKS) if (ssl->ctx->RsaSignCb) { ret = ssl->ctx->RsaSignCb(ssl, in, inSz, out, outSz, keyBuf, keySz, @@ -2751,9 +2974,7 @@ int RsaSign(WOLFSSL* ssl, const byte* in, word32 inSz, byte* out, } else #endif /*HAVE_PK_CALLBACKS */ - { ret = wc_RsaSSL_Sign(in, inSz, out, *outSz, key, ssl->rng); - } /* Handle async pending response */ #if defined(WOLFSSL_ASYNC_CRYPT) @@ -2788,6 +3009,26 @@ int RsaVerify(WOLFSSL* ssl, byte* in, word32 inSz, byte** out, int sigAlgo, WOLFSSL_ENTER("RsaVerify"); +#if defined(WC_RSA_PSS) + if (sigAlgo == rsa_pss_sa_algo) { + enum wc_HashType hashType = WC_HASH_TYPE_NONE; + int mgf = 0; + + ret = ConvertHashPss(hashAlgo, &hashType, &mgf); + if (ret != 0) + return ret; +#ifdef HAVE_PK_CALLBACKS + if (ssl->ctx->RsaPssVerifyCb) { + ret = ssl->ctx->RsaPssVerifyCb(ssl, in, inSz, out, + TypeHash(hashAlgo), mgf, + keyBuf, keySz, ctx); + } + else +#endif /*HAVE_PK_CALLBACKS */ + ret = wc_RsaPSS_VerifyInline(in, inSz, out, hashType, mgf, key); + } + else +#endif #ifdef HAVE_PK_CALLBACKS if (ssl->ctx->RsaVerifyCb) { ret = ssl->ctx->RsaVerifyCb(ssl, in, inSz, out, keyBuf, keySz, ctx); @@ -2795,37 +3036,7 @@ int RsaVerify(WOLFSSL* ssl, byte* in, word32 inSz, byte** out, int sigAlgo, else #endif /*HAVE_PK_CALLBACKS */ { -#ifdef WOLFSSL_TLS13 - #ifdef WC_RSA_PSS - if (sigAlgo == rsa_pss_sa_algo) { - enum wc_HashType hashType = WC_HASH_TYPE_NONE; - int mgf = 0; - switch (hashAlgo) { - case sha512_mac: - #ifdef WOLFSSL_SHA512 - hashType = WC_HASH_TYPE_SHA512; - mgf = WC_MGF1SHA512; - #endif - break; - case sha384_mac: - #ifdef WOLFSSL_SHA384 - hashType = WC_HASH_TYPE_SHA384; - mgf = WC_MGF1SHA384; - #endif - break; - case sha256_mac: - #ifndef NO_SHA256 - hashType = WC_HASH_TYPE_SHA256; - mgf = WC_MGF1SHA256; - #endif - break; - } - ret = wc_RsaPSS_VerifyInline(in, inSz, out, hashType, mgf, key); - } - else - #endif -#endif - ret = wc_RsaSSL_VerifyInline(in, inSz, out, key); + ret = wc_RsaSSL_VerifyInline(in, inSz, out, key); } /* Handle async pending response */ @@ -2842,12 +3053,14 @@ int RsaVerify(WOLFSSL* ssl, byte* in, word32 inSz, byte** out, int sigAlgo, /* Verify RSA signature, 0 on success */ int VerifyRsaSign(WOLFSSL* ssl, byte* verifySig, word32 sigSz, - const byte* plain, word32 plainSz, RsaKey* key) + const byte* plain, word32 plainSz, int sigAlgo, int hashAlgo, RsaKey* key) { byte* out = NULL; /* inline result */ int ret; (void)ssl; + (void)sigAlgo; + (void)hashAlgo; WOLFSSL_ENTER("VerifyRsaSign"); @@ -2860,15 +3073,33 @@ int VerifyRsaSign(WOLFSSL* ssl, byte* verifySig, word32 sigSz, return BUFFER_E; } - ret = wc_RsaSSL_VerifyInline(verifySig, sigSz, &out, key); +#if defined(WC_RSA_PSS) + if (sigAlgo == rsa_pss_sa_algo) { + enum wc_HashType hashType = WC_HASH_TYPE_NONE; + int mgf = 0; - if (ret > 0) { - if (ret != (int)plainSz || !out || - XMEMCMP(plain, out, plainSz) != 0) { - WOLFSSL_MSG("RSA Signature verification failed"); - ret = RSA_SIGN_FAULT; - } else { - ret = 0; /* RSA reset */ + ret = ConvertHashPss(hashAlgo, &hashType, &mgf); + if (ret != 0) + return ret; + ret = wc_RsaPSS_VerifyInline(verifySig, sigSz, &out, hashType, mgf, + key); + if (ret > 0) + ret = wc_RsaPSS_CheckPadding(plain, plainSz, out, ret, hashType); + if (ret != 0) + ret = VERIFY_CERT_ERROR; + } + else +#endif + { + ret = wc_RsaSSL_VerifyInline(verifySig, sigSz, &out, key); + if (ret > 0) { + if (ret != (int)plainSz || !out || + XMEMCMP(plain, out, plainSz) != 0) { + WOLFSSL_MSG("RSA Signature verification failed"); + ret = RSA_SIGN_FAULT; + } else { + ret = 0; /* RSA reset */ + } } } @@ -14884,7 +15115,7 @@ int SetCipherList(WOLFSSL_CTX* ctx, Suites* suites, const char* list) if (ret) { suites->setSuites = 1; suites->suiteSz = (word16)idx; - InitSuitesHashSigAlgo(suites, haveECDSAsig, haveRSAsig, haveAnon); + InitSuitesHashSigAlgo(suites, haveECDSAsig, haveRSAsig, haveAnon, 1); } (void)ctx; @@ -14893,7 +15124,8 @@ int SetCipherList(WOLFSSL_CTX* ctx, Suites* suites, const char* list) } #if !defined(NO_WOLFSSL_SERVER) || !defined(NO_CERTS) -void PickHashSigAlgo(WOLFSSL* ssl, const byte* hashSigAlgo, word32 hashSigAlgoSz) +void PickHashSigAlgo(WOLFSSL* ssl, const byte* hashSigAlgo, + word32 hashSigAlgoSz) { word32 i; @@ -14913,25 +15145,33 @@ void PickHashSigAlgo(WOLFSSL* ssl, const byte* hashSigAlgo, word32 hashSigAlgoSz /* i+1 since peek a byte ahead for type */ for (i = 0; (i+1) < hashSigAlgoSz; i += HELLO_EXT_SIGALGO_SZ) { - if (hashSigAlgo[i+1] == ssl->specs.sig_algo) { - if (hashSigAlgo[i] == sha_mac) { + byte hashAlgo = 0, sigAlgo = 0; + + DecodeSigAlg(&hashSigAlgo[i], &hashAlgo, &sigAlgo); + if (sigAlgo == ssl->specs.sig_algo || (sigAlgo == rsa_pss_sa_algo && + ssl->specs.sig_algo == rsa_sa_algo)) { + if (hashAlgo == sha_mac) { + ssl->suites->sigAlgo = sigAlgo; break; } #ifndef NO_SHA256 - else if (hashSigAlgo[i] == sha256_mac) { + else if (hashAlgo == sha256_mac) { ssl->suites->hashAlgo = sha256_mac; + ssl->suites->sigAlgo = sigAlgo; break; } #endif #ifdef WOLFSSL_SHA384 - else if (hashSigAlgo[i] == sha384_mac) { + else if (hashAlgo == sha384_mac) { ssl->suites->hashAlgo = sha384_mac; + ssl->suites->sigAlgo = sigAlgo; break; } #endif #ifdef WOLFSSL_SHA512 - else if (hashSigAlgo[i] == sha512_mac) { + else if (hashAlgo == sha512_mac) { ssl->suites->hashAlgo = sha512_mac; + ssl->suites->sigAlgo = sigAlgo; break; } #endif @@ -14940,6 +15180,7 @@ void PickHashSigAlgo(WOLFSSL* ssl, const byte* hashSigAlgo, word32 hashSigAlgoSz ssl->suites->hashAlgo = ssl->specs.mac_algorithm; } } + } #endif /* !defined(NO_WOLFSSL_SERVER) || !defined(NO_CERTS) */ @@ -15887,14 +16128,12 @@ typedef struct DskeArgs { #endif word32 idx; word32 begin; -#ifndef NO_RSA - int typeH; -#endif #if !defined(NO_DH) || defined(HAVE_ECC) word16 verifySigSz; #endif word16 sigSz; byte sigAlgo; + byte hashAlgo; } DskeArgs; static void FreeDskeArgs(WOLFSSL* ssl, void* pArgs) @@ -15943,6 +16182,7 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, args->idx = *inOutIdx; args->begin = *inOutIdx; args->sigAlgo = ssl->specs.sig_algo; + args->hashAlgo = sha_mac; #ifdef WOLFSSL_ASYNC_CRYPT ssl->async.freeArgs = FreeDskeArgs; #endif @@ -16403,8 +16643,7 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, #if defined(NO_DH) && !defined(HAVE_ECC) ERROR_OUT(NOT_COMPILED_IN, exit_dske); #else - byte hashAlgo = sha_mac; - enum wc_HashType hashType = WC_HASH_TYPE_NONE; + enum wc_HashType hashType; word16 verifySz; if (ssl->options.usingAnon_cipher) { @@ -16422,37 +16661,10 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, ERROR_OUT(BUFFER_ERROR, exit_dske); } - hashAlgo = input[args->idx++]; - args->sigAlgo = input[args->idx++]; - - switch (hashAlgo) { - case sha512_mac: - #ifdef WOLFSSL_SHA512 - hashType = WC_HASH_TYPE_SHA512; - #endif - break; - case sha384_mac: - #ifdef WOLFSSL_SHA384 - hashType = WC_HASH_TYPE_SHA384; - #endif - break; - case sha256_mac: - #ifndef NO_SHA256 - hashType = WC_HASH_TYPE_SHA256; - #endif - break; - case sha_mac: - #if !defined(NO_SHA) && \ - (!defined(NO_OLD_TLS) || \ - defined(WOLFSSL_ALLOW_TLS_SHA1)) - hashType = WC_HASH_TYPE_SHA; - #endif - break; - default: - WOLFSSL_MSG("Bad hash sig algo"); - break; - } - + DecodeSigAlg(&input[args->idx], &args->hashAlgo, + &args->sigAlgo); + args->idx += 2; + hashType = HashType(args->hashAlgo); if (hashType == WC_HASH_TYPE_NONE) { ERROR_OUT(ALGO_ID_E, exit_dske); } @@ -16467,9 +16679,6 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, ERROR_OUT(ALGO_ID_E, exit_dske); #endif } - #ifndef NO_RSA - args->typeH = wc_HashGetOID(hashType); - #endif /* signature */ if ((args->idx - args->begin) + OPAQUE16_LEN > size) { @@ -16519,6 +16728,9 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, switch (args->sigAlgo) { #ifndef NO_RSA + #ifdef WC_RSA_PSS + case rsa_pss_sa_algo: + #endif case rsa_sa_algo: { if (ssl->peerRsaKey == NULL || @@ -16594,12 +16806,15 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, switch (args->sigAlgo) { #ifndef NO_RSA + #ifdef WC_RSA_PSS + case rsa_pss_sa_algo: + #endif case rsa_sa_algo: { ret = RsaVerify(ssl, args->verifySig, args->verifySigSz, &args->output, - rsa_sa_algo, no_mac, + args->sigAlgo, args->hashAlgo, ssl->peerRsaKey, #ifdef HAVE_PK_CALLBACKS ssl->buffers.peerRsaKey.buffer, @@ -16686,6 +16901,17 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, switch(args->sigAlgo) { #ifndef NO_RSA + #ifdef WC_RSA_PSS + case rsa_pss_sa_algo: + ret = wc_RsaPSS_CheckPadding( + ssl->buffers.digest.buffer, + ssl->buffers.digest.length, + args->output, args->sigSz, + HashType(args->hashAlgo)); + if (ret != 0) + return ret; + break; + #endif case rsa_sa_algo: { if (IsAtLeastTLSv1_2(ssl)) { @@ -16706,7 +16932,8 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, encSigSz = wc_EncodeSignature(encodedSig, ssl->buffers.digest.buffer, - ssl->buffers.digest.length, args->typeH); + ssl->buffers.digest.length, + TypeHash(args->hashAlgo)); if (encSigSz != args->sigSz || !args->output || XMEMCMP(args->output, encodedSig, min(encSigSz, MAX_ENCODED_SIG_SZ)) != 0) { @@ -18335,6 +18562,7 @@ typedef struct ScvArgs { int sendSz; int length; int inputSz; + byte sigAlgo; } ScvArgs; static void FreeScvArgs(WOLFSSL* ssl, void* pArgs) @@ -18416,8 +18644,6 @@ int SendCertificateVerify(WOLFSSL* ssl) case TLS_ASYNC_BUILD: { - int typeH; - ret = BuildCertHashes(ssl, &ssl->hsHashes->certHashes); if (ret != 0) { goto exit_scv; @@ -18452,59 +18678,33 @@ int SendCertificateVerify(WOLFSSL* ssl) #ifndef NO_OLD_TLS #ifndef NO_SHA /* old tls default */ - ssl->buffers.digest.length = SHA_DIGEST_SIZE; - ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha; - typeH = SHAh; + SetDigest(ssl, sha_mac); #endif #else #ifndef NO_SHA256 /* new tls default */ - ssl->buffers.digest.length = SHA256_DIGEST_SIZE; - ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha256; - typeH = SHA256h; + SetDigest(ssl, sha256_mac); #endif #endif /* !NO_OLD_TLS */ - if (IsAtLeastTLSv1_2(ssl)) { - args->verify[0] = ssl->suites->hashAlgo; - args->verify[1] = (ssl->hsType == DYNAMIC_TYPE_ECC) ? - ecc_dsa_sa_algo : rsa_sa_algo; - args->extraSz = HASH_SIG_SIZE; + if (ssl->hsType == DYNAMIC_TYPE_RSA) { + #ifdef WC_RSA_PSS + if (IsAtLeastTLSv1_2(ssl) && + (ssl->pssAlgo | (1 << ssl->suites->hashAlgo))) { + args->sigAlgo = rsa_pss_sa_algo; + } + else + #endif + args->sigAlgo = rsa_sa_algo; + } + else if (ssl->hsType == DYNAMIC_TYPE_ECC) + args->sigAlgo = ecc_dsa_sa_algo; - switch (ssl->suites->hashAlgo) { - #ifndef NO_SHA - case sha_mac: - ssl->buffers.digest.length = SHA_DIGEST_SIZE; - ssl->buffers.digest.buffer = - ssl->hsHashes->certHashes.sha; - typeH = SHAh; - break; - #endif /* NO_SHA */ - #ifndef NO_SHA256 - case sha256_mac: - ssl->buffers.digest.length = SHA256_DIGEST_SIZE; - ssl->buffers.digest.buffer = - ssl->hsHashes->certHashes.sha256; - typeH = SHA256h; - break; - #endif /* !NO_SHA256 */ - #ifdef WOLFSSL_SHA384 - case sha384_mac: - ssl->buffers.digest.length = SHA384_DIGEST_SIZE; - ssl->buffers.digest.buffer = - ssl->hsHashes->certHashes.sha384; - typeH = SHA384h; - break; - #endif /* WOLFSSL_SHA384 */ - #ifdef WOLFSSL_SHA512 - case sha512_mac: - ssl->buffers.digest.length = SHA512_DIGEST_SIZE; - ssl->buffers.digest.buffer = - ssl->hsHashes->certHashes.sha512; - typeH = SHA512h; - break; - #endif /* WOLFSSL_SHA512 */ - } /* switch */ + if (IsAtLeastTLSv1_2(ssl)) { + EncodeSigAlg(ssl->suites->hashAlgo, args->sigAlgo, + args->verify); + args->extraSz = HASH_SIG_SIZE; + SetDigest(ssl, ssl->suites->hashAlgo); } #ifndef NO_OLD_TLS else { @@ -18514,21 +18714,27 @@ int SendCertificateVerify(WOLFSSL* ssl) } #endif - if (typeH == 0) { - ERROR_OUT(ALGO_ID_E, exit_scv); - } - #ifndef NO_RSA - if (ssl->hsType == DYNAMIC_TYPE_RSA) { + if (args->sigAlgo == rsa_sa_algo) { ssl->buffers.sig.length = FINISHED_SZ; args->sigSz = ENCRYPT_LEN; if (IsAtLeastTLSv1_2(ssl)) { ssl->buffers.sig.length = wc_EncodeSignature( ssl->buffers.sig.buffer, ssl->buffers.digest.buffer, - ssl->buffers.digest.length, typeH); + ssl->buffers.digest.length, + TypeHash(ssl->suites->hashAlgo)); } + /* prepend hdr */ + c16toa((word16)args->length, args->verify + args->extraSz); + } + else if (args->sigAlgo == rsa_pss_sa_algo) { + XMEMCPY(ssl->buffers.sig.buffer, ssl->buffers.digest.buffer, + ssl->buffers.digest.length); + ssl->buffers.sig.length = ssl->buffers.digest.length; + args->sigSz = ENCRYPT_LEN; + /* prepend hdr */ c16toa((word16)args->length, args->verify + args->extraSz); } @@ -18569,9 +18775,8 @@ int SendCertificateVerify(WOLFSSL* ssl) ret = RsaSign(ssl, ssl->buffers.sig.buffer, ssl->buffers.sig.length, args->verify + args->extraSz + VERIFY_HEADER, &args->sigSz, - key, - ssl->buffers.key->buffer, - ssl->buffers.key->length, + args->sigAlgo, ssl->suites->hashAlgo, key, + ssl->buffers.key->buffer, ssl->buffers.key->length, #ifdef HAVE_PK_CALLBACKS ssl->RsaSignCtx #else @@ -18624,7 +18829,7 @@ int SendCertificateVerify(WOLFSSL* ssl) ret = VerifyRsaSign(ssl, args->verifySig, args->sigSz, ssl->buffers.sig.buffer, ssl->buffers.sig.length, - key + args->sigAlgo, ssl->suites->hashAlgo, key ); } #endif /* !NO_RSA */ @@ -19609,7 +19814,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #ifdef HAVE_ECC case ecc_diffie_hellman_kea: { - enum wc_HashType hashType = WC_HASH_TYPE_NONE; + enum wc_HashType hashType; /* curve type, named curve, length(1) */ args->idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; @@ -19644,9 +19849,12 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, preSigSz = args->length; preSigIdx = args->idx; - switch(ssl->specs.sig_algo) + switch(ssl->suites->sigAlgo) { #ifndef NO_RSA + #ifdef WC_RSA_PSS + case rsa_pss_sa_algo: + #endif case rsa_sa_algo: { word32 i = 0; @@ -19765,37 +19973,12 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, /* Determine hash type */ if (IsAtLeastTLSv1_2(ssl)) { - args->output[args->idx++] = ssl->suites->hashAlgo; - args->output[args->idx++] = ssl->suites->sigAlgo; - - switch (ssl->suites->hashAlgo) { - case sha512_mac: - #ifdef WOLFSSL_SHA512 - hashType = WC_HASH_TYPE_SHA512; - #endif - break; - case sha384_mac: - #ifdef WOLFSSL_SHA384 - hashType = WC_HASH_TYPE_SHA384; - #endif - break; - case sha256_mac: - #ifndef NO_SHA256 - hashType = WC_HASH_TYPE_SHA256; - #endif - break; - case sha_mac: - #if !defined(NO_SHA) && \ - (!defined(NO_OLD_TLS) || \ - defined(WOLFSSL_ALLOW_TLS_SHA1)) - hashType = WC_HASH_TYPE_SHA; - #endif - break; - default: - WOLFSSL_MSG("Bad hash sig algo"); - break; - } + EncodeSigAlg(ssl->suites->hashAlgo, + ssl->suites->sigAlgo, + &args->output[args->idx]); + args->idx += 2; + hashType = HashType(ssl->suites->hashAlgo); if (hashType == WC_HASH_TYPE_NONE) { ERROR_OUT(ALGO_ID_E, exit_sske); } @@ -19854,14 +20037,13 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, args->sigSz = args->tmpSigSz; /* Sign hash to create signature */ - switch (ssl->specs.sig_algo) + switch (ssl->suites->sigAlgo) { #ifndef NO_RSA case rsa_sa_algo: { /* For TLS 1.2 re-encode signature */ if (IsAtLeastTLSv1_2(ssl)) { - int typeH = 0; byte* encodedSig = (byte*)XMALLOC( MAX_ENCODED_SIG_SZ, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); @@ -19869,37 +20051,11 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, ERROR_OUT(MEMORY_E, exit_sske); } - switch (ssl->suites->hashAlgo) { - case sha512_mac: - #ifdef WOLFSSL_SHA512 - typeH = SHA512h; - #endif - break; - case sha384_mac: - #ifdef WOLFSSL_SHA384 - typeH = SHA384h; - #endif - break; - case sha256_mac: - #ifndef NO_SHA256 - typeH = SHA256h; - #endif - break; - case sha_mac: - #if !defined(NO_SHA) && \ - (!defined(NO_OLD_TLS) || \ - defined(WOLFSSL_ALLOW_TLS_SHA1)) - typeH = SHAh; - #endif - break; - default: - break; - } - ssl->buffers.sig.length = wc_EncodeSignature(encodedSig, - ssl->buffers.sig.buffer, - ssl->buffers.sig.length, typeH); + ssl->buffers.sig.buffer, + ssl->buffers.sig.length, + TypeHash(ssl->suites->hashAlgo)); /* Replace sig buffer with new one */ XFREE(ssl->buffers.sig.buffer, ssl->heap, @@ -19913,6 +20069,14 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, args->idx += LENGTH_SZ; break; } + #ifdef WC_RSA_PSS + case rsa_pss_sa_algo: + /* write sig size here */ + c16toa((word16)args->sigSz, + args->output + args->idx); + args->idx += LENGTH_SZ; + break; + #endif #endif /* !NO_RSA */ case ecc_dsa_sa_algo: { @@ -19925,7 +20089,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #if !defined(NO_DH) && !defined(NO_RSA) case diffie_hellman_kea: { - enum wc_HashType hashType = WC_HASH_TYPE_NONE; + enum wc_HashType hashType; args->idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; args->length = LENGTH_SZ * 3; /* p, g, pub */ @@ -20045,37 +20209,12 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, /* Determine hash type */ if (IsAtLeastTLSv1_2(ssl)) { - args->output[args->idx++] = ssl->suites->hashAlgo; - args->output[args->idx++] = ssl->suites->sigAlgo; - - switch (ssl->suites->hashAlgo) { - case sha512_mac: - #ifdef WOLFSSL_SHA512 - hashType = WC_HASH_TYPE_SHA512; - #endif - break; - case sha384_mac: - #ifdef WOLFSSL_SHA384 - hashType = WC_HASH_TYPE_SHA384; - #endif - break; - case sha256_mac: - #ifndef NO_SHA256 - hashType = WC_HASH_TYPE_SHA256; - #endif - break; - case sha_mac: - #if !defined(NO_SHA) && \ - (!defined(NO_OLD_TLS) || \ - defined(WOLFSSL_ALLOW_TLS_SHA1)) - hashType = WC_HASH_TYPE_SHA; - #endif - break; - default: - WOLFSSL_MSG("Bad hash sig algo"); - break; - } + EncodeSigAlg(ssl->suites->hashAlgo, + ssl->suites->sigAlgo, + &args->output[args->idx]); + args->idx += 2; + hashType = HashType(ssl->suites->hashAlgo); if (hashType == WC_HASH_TYPE_NONE) { ERROR_OUT(ALGO_ID_E, exit_sske); } @@ -20135,7 +20274,6 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, { /* For TLS 1.2 re-encode signature */ if (IsAtLeastTLSv1_2(ssl)) { - int typeH = 0; byte* encodedSig = (byte*)XMALLOC( MAX_ENCODED_SIG_SZ, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); @@ -20143,37 +20281,11 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, ERROR_OUT(MEMORY_E, exit_sske); } - switch (ssl->suites->hashAlgo) { - case sha512_mac: - #ifdef WOLFSSL_SHA512 - typeH = SHA512h; - #endif - break; - case sha384_mac: - #ifdef WOLFSSL_SHA384 - typeH = SHA384h; - #endif - break; - case sha256_mac: - #ifndef NO_SHA256 - typeH = SHA256h; - #endif - break; - case sha_mac: - #if !defined(NO_SHA) && \ - (!defined(NO_OLD_TLS) || \ - defined(WOLFSSL_ALLOW_TLS_SHA1)) - typeH = SHAh; - #endif - break; - default: - break; - } - ssl->buffers.sig.length = - wc_EncodeSignature(encodedSig, - ssl->buffers.sig.buffer, - ssl->buffers.sig.length, typeH); + wc_EncodeSignature(encodedSig, + ssl->buffers.sig.buffer, + ssl->buffers.sig.length, + TypeHash(ssl->suites->hashAlgo)); /* Replace sig buffer with new one */ XFREE(ssl->buffers.sig.buffer, ssl->heap, @@ -20225,9 +20337,12 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, case ecc_diffie_hellman_kea: { /* Sign hash to create signature */ - switch (ssl->specs.sig_algo) + switch (ssl->suites->sigAlgo) { #ifndef NO_RSA + #ifdef WC_RSA_PSS + case rsa_pss_sa_algo: + #endif case rsa_sa_algo: { RsaKey* key = (RsaKey*)ssl->hsKey; @@ -20237,6 +20352,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, ssl->buffers.sig.length, args->output + args->idx, &args->sigSz, + ssl->suites->sigAlgo, ssl->suites->hashAlgo, key, ssl->buffers.key->buffer, ssl->buffers.key->length, @@ -20280,6 +20396,9 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, switch (ssl->suites->sigAlgo) { #ifndef NO_RSA + #ifdef WC_RSA_PSS + case rsa_pss_sa_algo: + #endif case rsa_sa_algo: { RsaKey* key = (RsaKey*)ssl->hsKey; @@ -20293,6 +20412,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, ssl->buffers.sig.length, args->output + args->idx, &args->sigSz, + ssl->suites->sigAlgo, ssl->suites->hashAlgo, key, ssl->buffers.key->buffer, ssl->buffers.key->length, @@ -20350,9 +20470,12 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #ifdef HAVE_ECC case ecc_diffie_hellman_kea: { - switch(ssl->specs.sig_algo) + switch(ssl->suites->sigAlgo) { #ifndef NO_RSA + #ifdef WC_RSA_PSS + case rsa_pss_sa_algo: + #endif case rsa_sa_algo: { RsaKey* key = (RsaKey*)ssl->hsKey; @@ -20376,6 +20499,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, args->verifySig, args->sigSz, ssl->buffers.sig.buffer, ssl->buffers.sig.length, + ssl->suites->sigAlgo, ssl->suites->hashAlgo, key ); break; @@ -20404,6 +20528,9 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, switch (ssl->suites->sigAlgo) { #ifndef NO_RSA + #ifndef WC_RSA_PSS + case rsa_pss_sa_algo: + #endif case rsa_sa_algo: { RsaKey* key = (RsaKey*)ssl->hsKey; @@ -20431,6 +20558,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, args->verifySig, args->sigSz, ssl->buffers.sig.buffer, ssl->buffers.sig.length, + ssl->suites->sigAlgo, ssl->suites->hashAlgo, key ); break; @@ -20710,7 +20838,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, result = SetCipherSpecs(ssl); if (result == 0) PickHashSigAlgo(ssl, peerSuites->hashSigAlgo, - peerSuites->hashSigAlgoSz); + peerSuites->hashSigAlgoSz); return result; } else { @@ -21501,9 +21629,18 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, ERROR_OUT(BUFFER_ERROR, exit_dcv); } - args->hashAlgo = input[args->idx++]; - args->sigAlgo = input[args->idx++]; + DecodeSigAlg(&input[args->idx], &args->hashAlgo, + &args->sigAlgo); + args->idx += 2; } + #ifndef NO_RSA + else if (ssl->peerRsaKey != NULL && ssl->peerRsaKeyPresent != 0) + args->sigAlgo = rsa_sa_algo; + #endif + #ifdef HAVE_ECC + else if (ssl->peerEccDsaKeyPresent) + args->sigAlgo = ecc_dsa_sa_algo; + #endif if ((args->idx - args->begin) + OPAQUE16_LEN > size) { ERROR_OUT(BUFFER_ERROR, exit_dcv); @@ -21524,17 +21661,13 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, /* make sure a default is defined */ #if !defined(NO_SHA) - ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha; - ssl->buffers.digest.length = SHA_DIGEST_SIZE; + SetDigest(ssl, sha_mac); #elif !defined(NO_SHA256) - ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha256; - ssl->buffers.digest.length = SHA256_DIGEST_SIZE; + SetDigest(ssl, sha256_mac); #elif defined(WOLFSSL_SHA384) - ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha384; - ssl->buffers.digest.length = SHA384_DIGEST_SIZE; + SetDigest(ssl, sha384_mac); #elif defined(WOLFSSL_SHA512) - ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha512; - ssl->buffers.digest.length = SHA512_DIGEST_SIZE; + SetDigest(ssl, sha512_mac); #else #error No digest enabled for ECC sig verify #endif @@ -21544,26 +21677,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, WOLFSSL_MSG("Oops, peer sent ECC key but not in verify"); } - switch (args->hashAlgo) { - case sha256_mac: - #ifndef NO_SHA256 - ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha256; - ssl->buffers.digest.length = SHA256_DIGEST_SIZE; - #endif - break; - case sha384_mac: - #ifdef WOLFSSL_SHA384 - ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha384; - ssl->buffers.digest.length = SHA384_DIGEST_SIZE; - #endif - break; - case sha512_mac: - #ifdef WOLFSSL_SHA512 - ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha512; - ssl->buffers.digest.length = SHA512_DIGEST_SIZE; - #endif - break; - } + SetDigest(ssl, args->hashAlgo); } } #endif /* HAVE_ECC */ @@ -21583,7 +21697,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, input + args->idx, args->sz, &args->output, - rsa_sa_algo, no_mac, + args->sigAlgo, args->hashAlgo, ssl->peerRsaKey, #ifdef HAVE_PK_CALLBACKS ssl->buffers.peerRsaKey.buffer, @@ -21594,7 +21708,12 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #endif ); if (ret >= 0) { - args->sendSz = ret; + if (args->sigAlgo == rsa_sa_algo) + args->sendSz = ret; + else { + args->sigSz = ret; + args->sendSz = ssl->buffers.digest.length; + } ret = 0; } } @@ -21633,79 +21752,56 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #ifndef NO_RSA if (ssl->peerRsaKey != NULL && ssl->peerRsaKeyPresent != 0) { if (IsAtLeastTLSv1_2(ssl)) { - #ifdef WOLFSSL_SMALL_STACK - byte* encodedSig = NULL; - #else - byte encodedSig[MAX_ENCODED_SIG_SZ]; - #endif - int typeH = SHAh; + #ifdef WC_RSA_PSS + if (args->sigAlgo == rsa_pss_sa_algo) { + SetDigest(ssl, args->hashAlgo); - /* make sure a default is defined */ - #if !defined(NO_SHA) - ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha; - ssl->buffers.digest.length = SHA_DIGEST_SIZE; - #elif !defined(NO_SHA256) - ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha256; - ssl->buffers.digest.length = SHA256_DIGEST_SIZE; - #elif defined(WOLFSSL_SHA384) - ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha384; - ssl->buffers.digest.length = SHA384_DIGEST_SIZE; - #elif defined(WOLFSSL_SHA512) - ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha512; - ssl->buffers.digest.length = SHA512_DIGEST_SIZE; - #else - #error No digest enabled for RSA sig verify - #endif - - #ifdef WOLFSSL_SMALL_STACK - encodedSig = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ, - ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); - if (encodedSig == NULL) { - ERROR_OUT(MEMORY_E, exit_dcv); + ret = wc_RsaPSS_CheckPadding( + ssl->buffers.digest.buffer, + ssl->buffers.digest.length, + args->output, args->sigSz, + HashType(args->hashAlgo)); + if (ret != 0) + return ret; } + else #endif + { + #ifdef WOLFSSL_SMALL_STACK + byte* encodedSig = NULL; + #else + byte encodedSig[MAX_ENCODED_SIG_SZ]; + #endif - if (args->sigAlgo != rsa_sa_algo) { - WOLFSSL_MSG("Oops, peer sent RSA key but not in verify"); + #ifdef WOLFSSL_SMALL_STACK + encodedSig = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ, + ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (encodedSig == NULL) { + ERROR_OUT(MEMORY_E, exit_dcv); + } + #endif + + if (args->sigAlgo != rsa_sa_algo) { + WOLFSSL_MSG("Oops, peer sent RSA key but not in verify"); + } + + SetDigest(ssl, args->hashAlgo); + + args->sigSz = wc_EncodeSignature(encodedSig, + ssl->buffers.digest.buffer, + ssl->buffers.digest.length, + TypeHash(args->hashAlgo)); + + if (args->sendSz != args->sigSz || !args->output || + XMEMCMP(args->output, encodedSig, + min(args->sigSz, MAX_ENCODED_SIG_SZ)) != 0) { + ret = VERIFY_CERT_ERROR; + } + + #ifdef WOLFSSL_SMALL_STACK + XFREE(encodedSig, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif } - - switch (args->hashAlgo) { - case sha256_mac: - #ifndef NO_SHA256 - typeH = SHA256h; - ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha256; - ssl->buffers.digest.length = SHA256_DIGEST_SIZE; - #endif /* !NO_SHA256 */ - break; - case sha384_mac: - #ifdef WOLFSSL_SHA384 - typeH = SHA384h; - ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha384; - ssl->buffers.digest.length = SHA384_DIGEST_SIZE; - #endif /* WOLFSSL_SHA384 */ - break; - case sha512_mac: - #ifdef WOLFSSL_SHA512 - typeH = SHA512h; - ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha512; - ssl->buffers.digest.length = SHA512_DIGEST_SIZE; - #endif /* WOLFSSL_SHA512 */ - break; - } /* switch */ - - args->sigSz = wc_EncodeSignature(encodedSig, - ssl->buffers.digest.buffer, - ssl->buffers.digest.length, typeH); - - if (args->sendSz != args->sigSz || !args->output || - XMEMCMP(args->output, encodedSig, - min(args->sigSz, MAX_ENCODED_SIG_SZ)) != 0) { - ret = VERIFY_CERT_ERROR; - } - - #ifdef WOLFSSL_SMALL_STACK - XFREE(encodedSig, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); - #endif } else { if (args->sendSz != FINISHED_SZ || !args->output || diff --git a/src/ssl.c b/src/ssl.c index 1ad509f99..eae22571a 100755 --- a/src/ssl.c +++ b/src/ssl.c @@ -22066,6 +22066,53 @@ void* wolfSSL_GetRsaVerifyCtx(WOLFSSL* ssl) return NULL; } +#ifdef WC_RSA_PSS +void wolfSSL_CTX_SetRsaPssSignCb(WOLFSSL_CTX* ctx, CallbackRsaPssSign cb) +{ + if (ctx) + ctx->RsaPssSignCb = cb; +} + + +void wolfSSL_SetRsaPssSignCtx(WOLFSSL* ssl, void *ctx) +{ + if (ssl) + ssl->RsaPssSignCtx = ctx; +} + + +void* wolfSSL_GetRsaPssSignCtx(WOLFSSL* ssl) +{ + if (ssl) + return ssl->RsaPssSignCtx; + + return NULL; +} + + +void wolfSSL_CTX_SetRsaPssVerifyCb(WOLFSSL_CTX* ctx, CallbackRsaPssVerify cb) +{ + if (ctx) + ctx->RsaPssVerifyCb = cb; +} + + +void wolfSSL_SetRsaPssVerifyCtx(WOLFSSL* ssl, void *ctx) +{ + if (ssl) + ssl->RsaPssVerifyCtx = ctx; +} + + +void* wolfSSL_GetRsaPssVerifyCtx(WOLFSSL* ssl) +{ + if (ssl) + return ssl->RsaPssVerifyCtx; + + return NULL; +} +#endif + void wolfSSL_CTX_SetRsaEncCb(WOLFSSL_CTX* ctx, CallbackRsaEnc cb) { if (ctx) diff --git a/src/tls.c b/src/tls.c index 2f77fe233..a25afd141 100755 --- a/src/tls.c +++ b/src/tls.c @@ -4439,7 +4439,6 @@ static int TLSX_SetSupportedVersions(TLSX** extensions, const void* data, /* Sugnature Algorithms */ /******************************************************************************/ -#ifdef WOLFSSL_TLS13 /* Return the size of the SignatureAlgorithms extension's data. * * data Unused @@ -4448,57 +4447,35 @@ static int TLSX_SetSupportedVersions(TLSX** extensions, const void* data, static word16 TLSX_SignatureAlgorithms_GetSize(void* data) { WOLFSSL* ssl = (WOLFSSL*)data; - int cnt = 0; - (void)data; + return OPAQUE16_LEN + ssl->suites->hashSigAlgoSz; +} -#ifndef NO_RSA - #ifndef NO_SHA1 - cnt++; - #endif - #ifndef NO_SHA256 - cnt++; - #endif - #ifdef HAVE_SHA384 - cnt++; - #endif - #ifdef HAVE_SHA512 - cnt++; - #endif - #ifdef WC_RSA_PSS - if (IsAtLeastTLSv1_3(ssl->version)) { - #ifndef NO_SHA256 - cnt++; - #endif - #ifdef HAVE_SHA384 - cnt++; - #endif - #ifdef HAVE_SHA512 - cnt++; - #endif - } - #endif -#endif +/* Creates a bit string of supported hash algorithms with RSA PSS. + * The bit string is used when determining which signature algorithm to use + * when creating the CertificateVerify message. + * Note: Valid data has an even length as each signature algorithm is two bytes. + * + * ssl The SSL/TLS object. + * input The buffer with the list of supported signature algorithms. + * length The length of the list in bytes. + * returns 0 on success, BUFFER_ERROR when the length is not even. + */ +static int TLSX_SignatureAlgorithms_MapPss(WOLFSSL *ssl, byte* input, + word16 length) +{ + word16 i; -#ifdef HAVE_ECC - #if !defined(NO_ECC256) || defined(HAVE_ALL_CURVES) - #ifndef NO_ECC_SECP - cnt++; - #endif - #endif - #if !defined(NO_ECC384) || defined(HAVE_ALL_CURVES) - #ifndef NO_ECC_SECP - cnt++; - #endif - #endif - #if !defined(NO_ECC521) || defined(HAVE_ALL_CURVES) - #ifndef NO_ECC_SECP - cnt++; - #endif - #endif -#endif + if ((length & 1) == 1) + return BUFFER_ERROR; - return OPAQUE16_LEN + cnt * OPAQUE16_LEN; + ssl->pssAlgo = 0; + for (i = 0; i < length; i += 2) { + if (input[i] == rsa_pss_sa_algo && input[i + 1] <= sha512_mac) + ssl->pssAlgo |= 1 << input[i + 1]; + } + + return 0; } /* Writes the SignatureAlgorithms extension into the buffer. @@ -4510,69 +4487,15 @@ static word16 TLSX_SignatureAlgorithms_GetSize(void* data) static word16 TLSX_SignatureAlgorithms_Write(void* data, byte* output) { WOLFSSL* ssl = (WOLFSSL*)data; - int idx = OPAQUE16_LEN; + c16toa(ssl->suites->hashSigAlgoSz, output); + XMEMCPY(output + OPAQUE16_LEN, ssl->suites->hashSigAlgo, + ssl->suites->hashSigAlgoSz); -#ifndef NO_RSA - #ifndef NO_SHA1 - output[idx++] = 0x02; - output[idx++] = 0x01; - #endif - #ifndef NO_SHA256 - output[idx++] = 0x04; - output[idx++] = 0x01; - #endif - #ifdef HAVE_SHA384 - output[idx++] = 0x05; - output[idx++] = 0x01; - #endif - #ifdef HAVE_SHA512 - output[idx++] = 0x06; - output[idx++] = 0x01; - #endif - #ifdef WC_RSA_PSS - if (IsAtLeastTLSv1_3(ssl->version)) { - #ifndef NO_SHA256 - output[idx++] = 0x08; - output[idx++] = 0x04; - #endif - #ifdef HAVE_SHA384 - output[idx++] = 0x08; - output[idx++] = 0x05; - #endif - #ifdef HAVE_SHA512 - output[idx++] = 0x08; - output[idx++] = 0x06; - #endif - } - #endif -#endif + TLSX_SignatureAlgorithms_MapPss(ssl, output + OPAQUE16_LEN, + ssl->suites->hashSigAlgoSz); -#ifdef HAVE_ECC - #if !defined(NO_ECC256) || defined(HAVE_ALL_CURVES) - #ifndef NO_ECC_SECP - output[idx++] = 0x04; - output[idx++] = 0x03; - #endif - #endif - #if !defined(NO_ECC384) || defined(HAVE_ALL_CURVES) - #ifndef NO_ECC_SECP - output[idx++] = 0x05; - output[idx++] = 0x03; - #endif - #endif - #if !defined(NO_ECC521) || defined(HAVE_ALL_CURVES) - #ifndef NO_ECC_SECP - output[idx++] = 0x06; - output[idx++] = 0x03; - #endif - #endif -#endif - - output[0] = (idx - OPAQUE16_LEN) >> 8; - output[1] = idx - OPAQUE16_LEN; - - return idx; + return OPAQUE16_LEN + ssl->suites->hashSigAlgoSz; } /* Parse the SignatureAlgorithms extension. @@ -4583,9 +4506,8 @@ static word16 TLSX_SignatureAlgorithms_Write(void* data, byte* output) * returns 0 on success, otherwise failure. */ static int TLSX_SignatureAlgorithms_Parse(WOLFSSL *ssl, byte* input, - word16 length) + word16 length, Suites* suites) { - int ret = 0; word16 len; (void)ssl; @@ -4595,14 +4517,16 @@ static int TLSX_SignatureAlgorithms_Parse(WOLFSSL *ssl, byte* input, return BUFFER_ERROR; ato16(input, &len); + input += OPAQUE16_LEN; /* Algorithm array must fill rest of data. */ if (length != OPAQUE16_LEN + len) return BUFFER_ERROR; - /* Ignore for now. */ + XMEMCPY(suites->hashSigAlgo, input, len); + suites->hashSigAlgoSz = len; - return ret; + return TLSX_SignatureAlgorithms_MapPss(ssl, input, len); } /* Sets a new SupportedVersions extension into the extension list. @@ -4625,13 +4549,6 @@ static int TLSX_SetSignatureAlgorithms(TLSX** extensions, const void* data, #define SA_WRITE TLSX_SignatureAlgorithms_Write #define SA_PARSE TLSX_SignatureAlgorithms_Parse -#else - -#define SA_GET_SIZE(a) 0 -#define SA_WRITE(a, b) 0 -#define SA_PARSE(a, b, c) 0 - -#endif /******************************************************************************/ /* Key Share */ @@ -6545,9 +6462,7 @@ static word16 TLSX_GetSize(TLSX* list, byte* semaphore, byte msgType) break; case TLSX_SIGNATURE_ALGORITHMS: -#ifdef WOLFSSL_TLS13 length += SA_GET_SIZE(extension->data); -#endif break; #ifdef WOLFSSL_TLS13 @@ -6669,10 +6584,8 @@ static word16 TLSX_Write(TLSX* list, byte* output, byte* semaphore, break; case TLSX_SIGNATURE_ALGORITHMS: -#ifdef WOLFSSL_TLS13 WOLFSSL_MSG("Signature Algorithms extension to write"); offset += SA_WRITE(extension->data, output + offset); -#endif break; #ifdef WOLFSSL_TLS13 @@ -7091,12 +7004,12 @@ int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isServer) #endif /* HAVE_ECC && HAVE_SUPPORTED_CURVES */ } /* is not server */ - #ifdef WOLFSSL_TLS13 WOLFSSL_MSG("Adding signature algorithms extension"); if ((ret = TLSX_SetSignatureAlgorithms(&ssl->extensions, ssl, ssl->heap)) != 0) return ret; + #ifdef WOLFSSL_TLS13 if (!isServer && IsAtLeastTLSv1_3(ssl->version)) { /* Add mandatory TLS v1.3 extension: supported version */ WOLFSSL_MSG("Adding supported versions extension"); @@ -7229,6 +7142,8 @@ word16 TLSX_GetRequestSize(WOLFSSL* ssl) EC_VALIDATE_REQUEST(ssl, semaphore); QSH_VALIDATE_REQUEST(ssl, semaphore); WOLF_STK_VALIDATE_REQUEST(ssl); + if (ssl->suites->hashSigAlgoSz == 0) + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_SIGNATURE_ALGORITHMS)); #if defined(WOLFSSL_TLS13) if (!IsAtLeastTLSv1_2(ssl)) TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_SUPPORTED_VERSIONS)); @@ -7250,12 +7165,6 @@ word16 TLSX_GetRequestSize(WOLFSSL* ssl) client_hello); } -#ifndef WOLFSSL_TLS13 - if (IsAtLeastTLSv1_2(ssl) && ssl->suites->hashSigAlgoSz) - length += HELLO_EXT_SZ + OPAQUE16_LEN + - + ssl->suites->hashSigAlgoSz; -#endif - #ifdef HAVE_EXTENDED_MASTER if (ssl->options.haveEMS) length += HELLO_EXT_SZ; @@ -7281,6 +7190,8 @@ word16 TLSX_WriteRequest(WOLFSSL* ssl, byte* output) EC_VALIDATE_REQUEST(ssl, semaphore); WOLF_STK_VALIDATE_REQUEST(ssl); QSH_VALIDATE_REQUEST(ssl, semaphore); + if (ssl->suites->hashSigAlgoSz == 0) + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_SIGNATURE_ALGORITHMS)); #if defined(WOLFSSL_TLS13) if (!IsAtLeastTLSv1_2(ssl)) TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_SUPPORTED_VERSIONS)); @@ -7304,28 +7215,6 @@ word16 TLSX_WriteRequest(WOLFSSL* ssl, byte* output) offset += TLSX_Write(ssl->ctx->extensions, output + offset, semaphore, client_hello); -#ifndef WOLFSSL_TLS13 - if (IsAtLeastTLSv1_2(ssl) && ssl->suites->hashSigAlgoSz) { - int i; - /* extension type */ - c16toa(TLSX_SIGNATURE_ALGORITHMS, output + offset); - offset += HELLO_EXT_TYPE_SZ; - - /* extension data length */ - c16toa(OPAQUE16_LEN + ssl->suites->hashSigAlgoSz, - output + offset); - offset += OPAQUE16_LEN; - - /* sig algos length */ - c16toa(ssl->suites->hashSigAlgoSz, output + offset); - offset += OPAQUE16_LEN; - - /* sig algos */ - for (i = 0; i < ssl->suites->hashSigAlgoSz; i++, offset++) - output[offset] = ssl->suites->hashSigAlgo[i]; - } -#endif - #ifdef HAVE_EXTENDED_MASTER if (ssl->options.haveEMS) { c16toa(HELLO_EXT_EXTMS, output + offset); @@ -7627,29 +7516,18 @@ int TLSX_Parse(WOLFSSL* ssl, byte* input, word16 length, byte msgType, ret = ALPN_PARSE(ssl, input + offset, size, isRequest); break; -#ifndef WOLFSSL_TLS13 case TLSX_SIGNATURE_ALGORITHMS: - WOLFSSL_MSG("Extended signature algorithm extension received"); + WOLFSSL_MSG("Signature Algorithms extension received"); - if (isRequest) { - /* do not mess with offset inside the switch! */ - if (IsAtLeastTLSv1_2(ssl)) { - ato16(input + offset, &suites->hashSigAlgoSz); + if (!IsAtLeastTLSv1_2(ssl)) + break; - if (suites->hashSigAlgoSz > size - OPAQUE16_LEN) - return BUFFER_ERROR; - - XMEMCPY(suites->hashSigAlgo, - input + offset + OPAQUE16_LEN, - min(suites->hashSigAlgoSz, - HELLO_EXT_SIGALGO_MAX)); - } - } else { - WOLFSSL_MSG("Servers MUST NOT send SIG ALGO extension."); + if (IsAtLeastTLSv1_3(ssl->version) && + msgType != client_hello) { + return EXT_NOT_ALLOWED; } - + ret = SA_PARSE(ssl, input + offset, size, suites); break; -#endif #ifdef WOLFSSL_TLS13 case TLSX_SUPPORTED_VERSIONS: @@ -7665,19 +7543,6 @@ int TLSX_Parse(WOLFSSL* ssl, byte* input, word16 length, byte msgType, ret = SV_PARSE(ssl, input + offset, size); break; - case TLSX_SIGNATURE_ALGORITHMS: - WOLFSSL_MSG("Signature Algorithms extension received"); - - if (!IsAtLeastTLSv1_2(ssl)) - break; - - if (IsAtLeastTLSv1_3(ssl->version) && - msgType != client_hello) { - return EXT_NOT_ALLOWED; - } - ret = SA_PARSE(ssl, input + offset, size); - break; - case TLSX_KEY_SHARE: WOLFSSL_MSG("Key Share extension received"); diff --git a/src/tls13.c b/src/tls13.c index 4ef99997a..cb1879019 100644 --- a/src/tls13.c +++ b/src/tls13.c @@ -2885,18 +2885,24 @@ static INLINE void EncodeSigAlg(byte hashAlgo, byte hsType, byte* output) { switch (hsType) { #ifdef HAVE_ECC - case DYNAMIC_TYPE_ECC: + case ecc_dsa_sa_algo: output[0] = hashAlgo; output[1] = ecc_dsa_sa_algo; break; #endif #ifndef NO_RSA - case DYNAMIC_TYPE_RSA: + case rsa_sa_algo: output[0] = hashAlgo; output[1] = rsa_sa_algo; break; -#endif + #ifdef WC_RSA_PSS /* PSS signatures: 0x080[4-6] */ + case rsa_pss_sa_algo: + output[0] = rsa_pss_sa_algo; + output[1] = hashAlgo; + break; + #endif +#endif /* ED25519: 0x0807 */ /* ED448: 0x0808 */ } @@ -2911,6 +2917,7 @@ static INLINE void EncodeSigAlg(byte hashAlgo, byte hsType, byte* output) static INLINE void DecodeSigAlg(byte* input, byte* hashAlgo, byte* hsType) { switch (input[0]) { + #ifdef WC_RSA_PSS case 0x08: /* PSS signatures: 0x080[4-6] */ if (input[1] <= 0x06) { @@ -2918,6 +2925,7 @@ static INLINE void DecodeSigAlg(byte* input, byte* hashAlgo, byte* hsType) *hashAlgo = input[1]; } break; + #endif /* ED25519: 0x0807 */ /* ED448: 0x0808 */ default: @@ -3017,12 +3025,22 @@ static void CreateSigData(WOLFSSL* ssl, byte* sigData, word16* sigDataSz, * returns the length of the encoded signature or negative on error. */ static int CreateRSAEncodedSig(byte* sig, byte* sigData, int sigDataSz, - int hashAlgo) + int sigAlgo, int hashAlgo) { Digest digest; int hashSz = 0; int hashOid = 0; int ret = BAD_FUNC_ARG; + byte* hash; + + (void)sigAlgo; + +#ifdef WC_RSA_PSS + if (sigAlgo == rsa_pss_sa_algo) + hash = sig; + else +#endif + hash = sigData; /* Digest the signature data. */ switch (hashAlgo) { @@ -3032,7 +3050,7 @@ static int CreateRSAEncodedSig(byte* sig, byte* sigData, int sigDataSz, if (ret == 0) { ret = wc_Sha256Update(&digest.sha256, sigData, sigDataSz); if (ret == 0) - ret = wc_Sha256Final(&digest.sha256, sigData); + ret = wc_Sha256Final(&digest.sha256, hash); wc_Sha256Free(&digest.sha256); } hashSz = SHA256_DIGEST_SIZE; @@ -3045,7 +3063,7 @@ static int CreateRSAEncodedSig(byte* sig, byte* sigData, int sigDataSz, if (ret == 0) { ret = wc_Sha384Update(&digest.sha384, sigData, sigDataSz); if (ret == 0) - ret = wc_Sha384Final(&digest.sha384, sigData); + ret = wc_Sha384Final(&digest.sha384, hash); wc_Sha384Free(&digest.sha384); } hashSz = SHA384_DIGEST_SIZE; @@ -3058,7 +3076,7 @@ static int CreateRSAEncodedSig(byte* sig, byte* sigData, int sigDataSz, if (ret == 0) { ret = wc_Sha512Update(&digest.sha512, sigData, sigDataSz); if (ret == 0) - ret = wc_Sha512Final(&digest.sha512, sigData); + ret = wc_Sha512Final(&digest.sha512, hash); wc_Sha512Free(&digest.sha512); } hashSz = SHA512_DIGEST_SIZE; @@ -3070,8 +3088,15 @@ static int CreateRSAEncodedSig(byte* sig, byte* sigData, int sigDataSz, if (ret != 0) return ret; - /* Encode the signature data as per PKCS #1.5 */ - return wc_EncodeSignature(sig, sigData, hashSz, hashOid); +#ifdef WC_RSA_PSS + if (sigAlgo == rsa_pss_sa_algo) + return hashSz; + else +#endif + { + /* Encode the signature data as per PKCS #1.5 */ + return wc_EncodeSignature(sig, hash, hashSz, hashOid); + } } #ifdef HAVE_ECC @@ -3159,7 +3184,40 @@ static int CheckRSASignature(WOLFSSL* ssl, int sigAlgo, int hashAlgo, #endif word32 sigSz; - if (sigAlgo == rsa_sa_algo) { + CreateSigData(ssl, sigData, &sigDataSz, 1); +#ifdef WC_RSA_PSS + if (sigAlgo == rsa_pss_sa_algo) { + int hashType = WC_HASH_TYPE_NONE; + + switch (hashAlgo) { + case sha512_mac: + #ifdef WOLFSSL_SHA512 + hashType = WC_HASH_TYPE_SHA512; + #endif + break; + case sha384_mac: + #ifdef WOLFSSL_SHA384 + hashType = WC_HASH_TYPE_SHA384; + #endif + break; + case sha256_mac: + #ifndef NO_SHA256 + hashType = WC_HASH_TYPE_SHA256; + #endif + break; + } + + ret = sigSz = CreateRSAEncodedSig(sigData, sigData, sigDataSz, + rsa_pss_sa_algo, hashAlgo); + if (ret < 0) + return ret; + + ret = wc_RsaPSS_CheckPadding(sigData, sigSz, decSig, decSigSz, + hashType); + } + else +#endif + { #ifdef WOLFSSL_SMALL_STACK encodedSig = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); @@ -3169,29 +3227,14 @@ static int CheckRSASignature(WOLFSSL* ssl, int sigAlgo, int hashAlgo, } #endif - CreateSigData(ssl, sigData, &sigDataSz, 1); - sigSz = CreateRSAEncodedSig(encodedSig, sigData, sigDataSz, hashAlgo); + sigSz = CreateRSAEncodedSig(encodedSig, sigData, sigDataSz, + DYNAMIC_TYPE_RSA, hashAlgo); /* Check the encoded and decrypted signature data match. */ if (decSigSz != sigSz || decSig == NULL || XMEMCMP(decSig, encodedSig, sigSz) != 0) { ret = VERIFY_CERT_ERROR; } } - else { - CreateSigData(ssl, sigData, &sigDataSz, 1); - sigSz = CreateECCEncodedSig(sigData, sigDataSz, hashAlgo); - if (decSigSz != sigSz || decSig == NULL) - ret = VERIFY_CERT_ERROR; - else { - decSig -= 2 * decSigSz; - XMEMCPY(decSig, sigData, decSigSz); - decSig -= 8; - XMEMSET(decSig, 0, 8); - CreateECCEncodedSig(decSig, 8 + decSigSz * 2, hashAlgo); - if (XMEMCMP(decSig, decSig + 8 + decSigSz * 2, decSigSz) != 0) - ret = VERIFY_CERT_ERROR; - } - } #ifdef WOLFSSL_SMALL_STACK end: @@ -3468,6 +3511,7 @@ typedef struct Scv13Args { int sendSz; word16 length; + byte sigAlgo; byte* sigData; word16 sigDataSz; } Scv13Args; @@ -3573,7 +3617,17 @@ int SendTls13CertificateVerify(WOLFSSL* ssl) goto exit_scv; /* Add signature algorithm. */ - EncodeSigAlg(ssl->suites->hashAlgo, ssl->hsType, args->verify); + if (ssl->hsType == DYNAMIC_TYPE_RSA) { + #ifdef WC_RSA_PSS + if (ssl->pssAlgo | (1 << ssl->suites->hashAlgo)) + args->sigAlgo = rsa_pss_sa_algo; + else + #endif + args->sigAlgo = rsa_sa_algo; + } + else if (ssl->hsType == DYNAMIC_TYPE_ECC) + args->sigAlgo = ecc_dsa_sa_algo; + EncodeSigAlg(ssl->suites->hashAlgo, args->sigAlgo, args->verify); /* Create the data to be signed. */ args->sigData = (byte*)XMALLOC(MAX_SIG_DATA_SZ, ssl->heap, @@ -3594,9 +3648,8 @@ int SendTls13CertificateVerify(WOLFSSL* ssl) ERROR_OUT(MEMORY_E, exit_scv); } - /* Digest the signature data and encode. Used in verify too. */ ret = CreateRSAEncodedSig(sig->buffer, args->sigData, - args->sigDataSz, ssl->suites->hashAlgo); + args->sigDataSz, args->sigAlgo, ssl->suites->hashAlgo); if (ret < 0) goto exit_scv; sig->length = ret; @@ -3648,6 +3701,7 @@ int SendTls13CertificateVerify(WOLFSSL* ssl) ret = RsaSign(ssl, sig->buffer, sig->length, args->verify + HASH_SIG_SIZE + VERIFY_HEADER, &args->sigLen, + args->sigAlgo, ssl->suites->hashAlgo, (RsaKey*)ssl->hsKey, ssl->buffers.key->buffer, ssl->buffers.key->length, #ifdef HAVE_PK_CALLBACKS @@ -3693,7 +3747,8 @@ int SendTls13CertificateVerify(WOLFSSL* ssl) /* check for signature faults */ ret = VerifyRsaSign(ssl, args->verifySig, args->sigLen, - sig->buffer, sig->length, (RsaKey*)ssl->hsKey); + sig->buffer, sig->length, args->sigAlgo, + ssl->suites->hashAlgo, (RsaKey*)ssl->hsKey); } #endif /* !NO_RSA */ @@ -3886,7 +3941,6 @@ static int DoTls13CertificateVerify(WOLFSSL* ssl, byte* input, } DecodeSigAlg(input + args->idx, &args->hashAlgo, &args->sigAlgo); args->idx += OPAQUE16_LEN; - /* TODO: [TLS13] was it in SignatureAlgorithms extension? */ /* Signature length. */ if ((args->idx - args->begin) + OPAQUE16_LEN > totalSz) { diff --git a/wolfcrypt/src/rsa.c b/wolfcrypt/src/rsa.c index 7f9da78b7..fdf6a45c4 100755 --- a/wolfcrypt/src/rsa.c +++ b/wolfcrypt/src/rsa.c @@ -580,9 +580,13 @@ static int RsaPad_OAEP(const byte* input, word32 inputLen, byte* pkcsBlock, #endif /* !WC_NO_RSA_OAEP */ #ifdef WC_RSA_PSS +/* 0x00 .. 0x00 0x01 | Salt | Gen Hash | 0xbc + * XOR MGF over all bytes down to end of Salt + * Gen Hash = HASH(8 * 0x00 | Message Hash | Salt) + */ static int RsaPad_PSS(const byte* input, word32 inputLen, byte* pkcsBlock, word32 pkcsBlockLen, WC_RNG* rng, enum wc_HashType hType, int mgf, - void* heap) + int bits, void* heap) { int ret; int hLen, i; @@ -613,7 +617,7 @@ static int RsaPad_PSS(const byte* input, word32 inputLen, byte* pkcsBlock, ret = RsaMGF(mgf, h, hLen, pkcsBlock, pkcsBlockLen - hLen - 1, heap); if (ret != 0) return ret; - pkcsBlock[0] &= 0x7f; + pkcsBlock[0] &= (1 << ((bits - 1) & 0x7)) - 1; m = pkcsBlock + pkcsBlockLen - 1 - hLen - hLen - 1; *(m++) ^= 0x01; @@ -676,7 +680,7 @@ static int RsaPad(const byte* input, word32 inputLen, byte* pkcsBlock, /* helper function to direct which padding is used */ static int wc_RsaPad_ex(const byte* input, word32 inputLen, byte* pkcsBlock, word32 pkcsBlockLen, byte padValue, WC_RNG* rng, int padType, - enum wc_HashType hType, int mgf, byte* optLabel, word32 labelLen, + enum wc_HashType hType, int mgf, byte* optLabel, word32 labelLen, int bits, void* heap) { int ret; @@ -700,8 +704,8 @@ static int wc_RsaPad_ex(const byte* input, word32 inputLen, byte* pkcsBlock, #ifdef WC_RSA_PSS case WC_RSA_PSS_PAD: WOLFSSL_MSG("wolfSSL Using RSA PSS padding"); - ret = RsaPad_PSS(input, inputLen, pkcsBlock, pkcsBlockLen, - rng, hType, mgf, heap); + ret = RsaPad_PSS(input, inputLen, pkcsBlock, pkcsBlockLen, rng, + hType, mgf, bits, heap); break; #endif @@ -715,6 +719,7 @@ static int wc_RsaPad_ex(const byte* input, word32 inputLen, byte* pkcsBlock, (void)mgf; (void)optLabel; (void)labelLen; + (void)bits; (void)heap; return ret; @@ -811,7 +816,7 @@ static int RsaUnPad_OAEP(byte *pkcsBlock, unsigned int pkcsBlockLen, #ifdef WC_RSA_PSS static int RsaUnPad_PSS(byte *pkcsBlock, unsigned int pkcsBlockLen, byte **output, enum wc_HashType hType, int mgf, - void* heap) + int bits, void* heap) { int ret; byte* tmp; @@ -835,7 +840,7 @@ static int RsaUnPad_PSS(byte *pkcsBlock, unsigned int pkcsBlockLen, return ret; } - tmp[0] &= 0x7f; + tmp[0] &= (1 << ((bits - 1) & 0x7)) - 1; for (i = 0; i < (int)(pkcsBlockLen - 1 - hLen - hLen - 1); i++) { if (tmp[i] != pkcsBlock[i]) { XFREE(tmp, heap, DYNAMIC_TYPE_TMP_BUFFER); @@ -851,8 +856,11 @@ static int RsaUnPad_PSS(byte *pkcsBlock, unsigned int pkcsBlockLen, XFREE(tmp, heap, DYNAMIC_TYPE_TMP_BUFFER); + i = pkcsBlockLen - (RSA_PSS_PAD_SZ + 3 * hLen + 1); + XMEMSET(pkcsBlock + i, 0, RSA_PSS_PAD_SZ); + *output = pkcsBlock + i; - return hLen; + return RSA_PSS_PAD_SZ + 3 * hLen; } #endif @@ -906,7 +914,8 @@ static int RsaUnPad(const byte *pkcsBlock, unsigned int pkcsBlockLen, /* helper function to direct unpadding */ static int wc_RsaUnPad_ex(byte* pkcsBlock, word32 pkcsBlockLen, byte** out, byte padValue, int padType, enum wc_HashType hType, - int mgf, byte* optLabel, word32 labelLen, void* heap) + int mgf, byte* optLabel, word32 labelLen, int bits, + void* heap) { int ret; @@ -928,7 +937,7 @@ static int wc_RsaUnPad_ex(byte* pkcsBlock, word32 pkcsBlockLen, byte** out, case WC_RSA_PSS_PAD: WOLFSSL_MSG("wolfSSL Using RSA PSS un-padding"); ret = RsaUnPad_PSS((byte*)pkcsBlock, pkcsBlockLen, out, hType, mgf, - heap); + bits, heap); break; #endif @@ -942,6 +951,7 @@ static int wc_RsaUnPad_ex(byte* pkcsBlock, word32 pkcsBlockLen, byte** out, (void)mgf; (void)optLabel; (void)labelLen; + (void)bits; (void)heap; return ret; @@ -1276,7 +1286,8 @@ static int RsaPublicEncryptEx(const byte* in, word32 inLen, byte* out, #endif ret = wc_RsaPad_ex(in, inLen, out, sz, pad_value, rng, pad_type, hash, - mgf, label, labelSz, key->heap); + mgf, label, labelSz, mp_count_bits(&key->n), + key->heap); if (ret < 0) { break; } @@ -1409,7 +1420,8 @@ static int RsaPrivateDecryptEx(byte* in, word32 inLen, byte* out, { byte* pad = NULL; ret = wc_RsaUnPad_ex(key->data, key->dataLen, &pad, pad_value, pad_type, - hash, mgf, label, labelSz, key->heap); + hash, mgf, label, labelSz, mp_count_bits(&key->n), + key->heap); if (ret > 0 && ret <= (int)outLen && pad != NULL) { /* only copy output if not inline */ if (outPtr == NULL) { @@ -1577,6 +1589,32 @@ int wc_RsaPSS_VerifyInline(byte* in, word32 inLen, byte** out, RSA_PUBLIC_DECRYPT, RSA_BLOCK_TYPE_1, WC_RSA_PSS_PAD, hash, mgf, NULL, 0, rng); } + +/* Sig = 8 * 0x00 | Space for Message Hash | Salt | Exp Hash + * Exp Hash = HASH(8 * 0x00 | Message Hash | Salt) + */ +int wc_RsaPSS_CheckPadding(const byte* in, word32 inSz, byte* sig, + word32 sigSz, enum wc_HashType hashType) +{ + int ret; + + if (in == NULL || sig == NULL || + inSz != (word32)wc_HashGetDigestSize(hashType) || + sigSz != RSA_PSS_PAD_SZ + inSz * 3) + ret = BAD_FUNC_ARG; + else { + XMEMCPY(sig + RSA_PSS_PAD_SZ, in, inSz); + ret = wc_Hash(hashType, sig, RSA_PSS_PAD_SZ + inSz * 2, sig, inSz); + if (ret != 0) + return ret; + if (XMEMCMP(sig, sig + RSA_PSS_PAD_SZ + inSz * 2, inSz) != 0) + ret = BAD_PADDING_E; + else + ret = 0; + } + + return ret; +} #endif int wc_RsaSSL_Sign(const byte* in, word32 inLen, byte* out, word32 outLen, @@ -1587,6 +1625,15 @@ int wc_RsaSSL_Sign(const byte* in, word32 inLen, byte* out, word32 outLen, WC_HASH_TYPE_NONE, WC_MGF1NONE, NULL, 0, rng); } +#ifdef WC_RSA_PSS +int wc_RsaPSS_Sign(const byte* in, word32 inLen, byte* out, word32 outLen, + enum wc_HashType hash, int mgf, RsaKey* key, WC_RNG* rng) +{ + return RsaPublicEncryptEx(in, inLen, out, outLen, key, + RSA_PRIVATE_ENCRYPT, RSA_BLOCK_TYPE_1, WC_RSA_PSS_PAD, + hash, mgf, NULL, 0, rng); +} +#endif int wc_RsaEncryptSize(RsaKey* key) { diff --git a/wolfssl/internal.h b/wolfssl/internal.h index 568fb7e86..5b63d2bc9 100755 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -2267,6 +2267,10 @@ struct WOLFSSL_CTX { #ifndef NO_RSA CallbackRsaSign RsaSignCb; /* User RsaSign Callback handler */ CallbackRsaVerify RsaVerifyCb; /* User RsaVerify Callback handler */ + #ifdef WC_RSA_PSS + CallbackRsaPssSign RsaPssSignCb; /* User RsaPssSign */ + CallbackRsaPssVerify RsaPssVerifyCb; /* User RsaPssVerify */ + #endif CallbackRsaEnc RsaEncCb; /* User Rsa Public Encrypt handler */ CallbackRsaDec RsaDecCb; /* User Rsa Private Decrypt handler */ #endif /* NO_RSA */ @@ -3105,8 +3109,9 @@ struct WOLFSSL { byte user_set_QSHSchemes; #endif #ifdef WOLFSSL_TLS13 - word16 namedGroup; + word16 namedGroup; #endif + byte pssAlgo; #ifdef HAVE_NTRU word16 peerNtruKeyLen; byte peerNtruKey[MAX_NTRU_PUB_KEY_SZ]; @@ -3237,6 +3242,10 @@ struct WOLFSSL { #ifndef NO_RSA void* RsaSignCtx; /* Rsa Sign Callback Context */ void* RsaVerifyCtx; /* Rsa Verify Callback Context */ + #ifdef WC_RSA_PSS + void* RsaPssSignCtx; /* Rsa PSS Sign Callback Context */ + void* RsaPssVerifyCtx; /* Rsa PSS Verify Callback Context */ + #endif void* RsaEncCtx; /* Rsa Public Encrypt Callback Context */ void* RsaDecCtx; /* Rsa Private Decrypt Callback Context */ #endif /* NO_RSA */ @@ -3425,12 +3434,17 @@ WOLFSSL_LOCAL void ShrinkOutputBuffer(WOLFSSL* ssl); WOLFSSL_LOCAL int VerifyClientSuite(WOLFSSL* ssl); #ifndef NO_CERTS #ifndef NO_RSA + WOLFSSL_LOCAL int CheckRsaPssPadding(const byte* plain, word32 plainSz, + byte* out, word32 sigSz, + enum wc_HashType hashType); WOLFSSL_LOCAL int VerifyRsaSign(WOLFSSL* ssl, byte* verifySig, word32 sigSz, const byte* plain, word32 plainSz, + int sigAlgo, int hashAlgo, RsaKey* key); - WOLFSSL_LOCAL int RsaSign(WOLFSSL* ssl, const byte* in, word32 inSz, byte* out, - word32* outSz, RsaKey* key, const byte* keyBuf, word32 keySz, void* ctx); + WOLFSSL_LOCAL int RsaSign(WOLFSSL* ssl, const byte* in, word32 inSz, + byte* out, word32* outSz, int sigAlgo, int hashAlgo, RsaKey* key, + const byte* keyBuf, word32 keySz, void* ctx); WOLFSSL_LOCAL int RsaVerify(WOLFSSL* ssl, byte* in, word32 inSz, byte** out, int sigAlgo, int hashAlgo, RsaKey* key, const byte* keyBuf, word32 keySz, void* ctx); diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h index 7eccb75fc..964fc87f4 100644 --- a/wolfssl/ssl.h +++ b/wolfssl/ssl.h @@ -1535,6 +1535,29 @@ WOLFSSL_API void wolfSSL_CTX_SetRsaVerifyCb(WOLFSSL_CTX*, CallbackRsaVerify); WOLFSSL_API void wolfSSL_SetRsaVerifyCtx(WOLFSSL* ssl, void *ctx); WOLFSSL_API void* wolfSSL_GetRsaVerifyCtx(WOLFSSL* ssl); +#ifdef WC_RSA_PSS +typedef int (*CallbackRsaPssSign)(WOLFSSL* ssl, + const unsigned char* in, unsigned int inSz, + unsigned char* out, unsigned int* outSz, + int hash, int mgf, + const unsigned char* keyDer, unsigned int keySz, + void* ctx); +WOLFSSL_API void wolfSSL_CTX_SetRsaPssSignCb(WOLFSSL_CTX*, CallbackRsaPssSign); +WOLFSSL_API void wolfSSL_SetRsaPssSignCtx(WOLFSSL* ssl, void *ctx); +WOLFSSL_API void* wolfSSL_GetRsaPssSignCtx(WOLFSSL* ssl); + +typedef int (*CallbackRsaPssVerify)(WOLFSSL* ssl, + unsigned char* sig, unsigned int sigSz, + unsigned char** out, + int hash, int mgf, + const unsigned char* keyDer, unsigned int keySz, + void* ctx); +WOLFSSL_API void wolfSSL_CTX_SetRsaPssVerifyCb(WOLFSSL_CTX*, + CallbackRsaPssVerify); +WOLFSSL_API void wolfSSL_SetRsaPssVerifyCtx(WOLFSSL* ssl, void *ctx); +WOLFSSL_API void* wolfSSL_GetRsaPssVerifyCtx(WOLFSSL* ssl); +#endif + /* RSA Public Encrypt cb */ typedef int (*CallbackRsaEnc)(WOLFSSL* ssl, const unsigned char* in, unsigned int inSz, diff --git a/wolfssl/test.h b/wolfssl/test.h index 3f48b2ce1..aab51b4e6 100644 --- a/wolfssl/test.h +++ b/wolfssl/test.h @@ -1948,6 +1948,104 @@ static INLINE int myRsaVerify(WOLFSSL* ssl, byte* sig, word32 sigSz, return ret; } +#ifdef WC_RSA_PSS +static INLINE int myRsaPssSign(WOLFSSL* ssl, const byte* in, word32 inSz, + byte* out, word32* outSz, int hash, int mgf, const byte* key, + word32 keySz, void* ctx) +{ + enum wc_HashType hashType; + WC_RNG rng; + int ret; + word32 idx = 0; + RsaKey myKey; + + (void)ssl; + (void)ctx; + + switch (hash) { +#ifndef NO_SHA256 + case SHA256h: + hashType = WC_HASH_TYPE_SHA256; + break; +#endif +#ifdef WOLFSSL_SHA384 + case SHA384h: + hashType = WC_HASH_TYPE_SHA384; + break; +#endif +#ifdef WOLFSSL_SHA512 + case SHA512h: + hashType = WC_HASH_TYPE_SHA512; + break; +#endif + } + + ret = wc_InitRng(&rng); + if (ret != 0) + return ret; + + ret = wc_InitRsaKey(&myKey, NULL); + if (ret == 0) { + ret = wc_RsaPrivateKeyDecode(key, &idx, &myKey, keySz); + if (ret == 0) { + ret = wc_RsaPSS_Sign(in, inSz, out, *outSz, hashType, mgf, &myKey, + &rng); + } + if (ret > 0) { /* save and convert to 0 success */ + *outSz = ret; + ret = 0; + } + wc_FreeRsaKey(&myKey); + } + wc_FreeRng(&rng); + + return ret; +} + + +static INLINE int myRsaPssVerify(WOLFSSL* ssl, byte* sig, word32 sigSz, + byte** out, int hash, int mgf, const byte* key, word32 keySz, void* ctx) +{ + enum wc_HashType hashType; + int ret; + word32 idx = 0; + RsaKey myKey; + + (void)ssl; + (void)ctx; + + switch (hash) { +#ifndef NO_SHA256 + case SHA256h: + hashType = WC_HASH_TYPE_SHA256; + break; +#endif +#ifdef WOLFSSL_SHA384 + case SHA384h: + hashType = WC_HASH_TYPE_SHA384; + break; +#endif +#ifdef WOLFSSL_SHA512 + case SHA512h: + hashType = WC_HASH_TYPE_SHA512; + break; +#endif + } + + ret = wc_InitRsaKey(&myKey, NULL); + if (ret == 0) { + ret = wc_RsaPublicKeyDecode(key, &idx, &myKey, keySz); + if (ret == 0) { + ret = wc_RsaPSS_VerifyInline(sig, sigSz, out, hashType, mgf, + &myKey); + } + wc_FreeRsaKey(&myKey); + } + + return ret; +} +#endif + static INLINE int myRsaEnc(WOLFSSL* ssl, const byte* in, word32 inSz, byte* out, word32* outSz, const byte* key, @@ -2030,6 +2128,10 @@ static INLINE void SetupPkCallbacks(WOLFSSL_CTX* ctx, WOLFSSL* ssl) #ifndef NO_RSA wolfSSL_CTX_SetRsaSignCb(ctx, myRsaSign); wolfSSL_CTX_SetRsaVerifyCb(ctx, myRsaVerify); + #ifdef WC_RSA_PSS + wolfSSL_CTX_SetRsaPssSignCb(ctx, myRsaPssSign); + wolfSSL_CTX_SetRsaPssVerifyCb(ctx, myRsaPssVerify); + #endif wolfSSL_CTX_SetRsaEncCb(ctx, myRsaEnc); wolfSSL_CTX_SetRsaDecCb(ctx, myRsaDec); #endif /* NO_RSA */ diff --git a/wolfssl/wolfcrypt/rsa.h b/wolfssl/wolfcrypt/rsa.h index 6905d1dd2..30938fd16 100644 --- a/wolfssl/wolfcrypt/rsa.h +++ b/wolfssl/wolfcrypt/rsa.h @@ -76,7 +76,9 @@ enum { RSA_MIN_SIZE = 512, RSA_MAX_SIZE = 4096, - RSA_MIN_PAD_SZ = 11 /* separator + 0 + pad value + 8 pads */ + RSA_MIN_PAD_SZ = 11, /* separator + 0 + pad value + 8 pads */ + + RSA_PSS_PAD_SZ = 8 }; @@ -122,6 +124,9 @@ WOLFSSL_API int wc_RsaPrivateDecrypt(const byte* in, word32 inLen, byte* out, word32 outLen, RsaKey* key); WOLFSSL_API int wc_RsaSSL_Sign(const byte* in, word32 inLen, byte* out, word32 outLen, RsaKey* key, WC_RNG* rng); +WOLFSSL_API int wc_RsaPSS_Sign(const byte* in, word32 inLen, byte* out, + word32 outLen, enum wc_HashType hash, int mgf, + RsaKey* key, WC_RNG* rng); WOLFSSL_API int wc_RsaSSL_VerifyInline(byte* in, word32 inLen, byte** out, RsaKey* key); WOLFSSL_API int wc_RsaSSL_Verify(const byte* in, word32 inLen, byte* out, @@ -129,6 +134,10 @@ WOLFSSL_API int wc_RsaSSL_Verify(const byte* in, word32 inLen, byte* out, WOLFSSL_API int wc_RsaPSS_VerifyInline(byte* in, word32 inLen, byte** out, enum wc_HashType hash, int mgf, RsaKey* key); +WOLFSSL_API int wc_RsaPSS_CheckPadding(const byte* in, word32 inLen, byte* sig, + word32 sigSz, + enum wc_HashType hashType); + WOLFSSL_API int wc_RsaEncryptSize(RsaKey* key); #ifndef HAVE_FIPS /* to avoid asn duplicate symbols @wc_fips */