diff --git a/doc/dox_comments/header_files/rsa.h b/doc/dox_comments/header_files/rsa.h index c0cbab2830..8d67d591ce 100644 --- a/doc/dox_comments/header_files/rsa.h +++ b/doc/dox_comments/header_files/rsa.h @@ -742,10 +742,13 @@ int wc_RsaPSS_VerifyCheck_ex(byte* in, word32 inLen, The key has to be associated with RNG by wc_RsaSetRNG when WC_RSA_BLINDING is enabled. \return the length of the PSS data on success and negative indicates failure. + On the crypto callback path *out is set to NULL though the return stays + positive, so callers must not dereference *out. \param in The byte array to be decrypted. \param inLen The length of in. - \param out The byte array for the decrypted data to be stored. + \param out The byte array for the decrypted data to be stored. Set to NULL + when a crypto callback device performed the verify (see \return). \param digest Hash of the data that is being verified. \param digestLen Length of hash. \param hash The hash type to be in message diff --git a/tests/api/test_cmac.c b/tests/api/test_cmac.c index 5a49fbce64..16e7fa64e2 100644 --- a/tests/api/test_cmac.c +++ b/tests/api/test_cmac.c @@ -720,3 +720,80 @@ int test_wc_AesCmacVerify_CryptoCb_LenMismatch(void) return EXPECT_RESULT(); } /* END test_wc_AesCmacVerify_CryptoCb_LenMismatch */ +/* Test that wc_CmacFree() dispatches a WC_ALGO_TYPE_FREE / WC_ALGO_TYPE_CMAC + * request to a registered crypto callback (CryptoCb) device. */ +#if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_FREE) && \ + defined(WOLFSSL_CMAC) && !defined(NO_AES) && defined(WOLFSSL_AES_DIRECT) +/* Spy device: declines every request (software handles the work) but counts + * CMAC free dispatches. */ +static int cmac_free_test_crypto_cb(int devIdArg, wc_CryptoInfo* info, void* ctx) +{ + int* freeSeen = (int*)ctx; + + (void)devIdArg; + + if (info == NULL) { + return BAD_FUNC_ARG; + } + + if (info->algo_type == WC_ALGO_TYPE_FREE && + info->free.algo == WC_ALGO_TYPE_CMAC) { + if (freeSeen != NULL) { + (*freeSeen)++; + } + } + + return WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE); +} +#endif + +int test_wc_CryptoCb_CmacFree(void) +{ + EXPECT_DECLS; +#if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_FREE) && \ + defined(WOLFSSL_CMAC) && !defined(NO_AES) && defined(WOLFSSL_AES_DIRECT) + int devId = 4460; + int freeSeen = 0; + byte key16[16] = { + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10 + }; + byte in[16] = { + 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, + 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x00 + }; + byte tag[WC_AES_BLOCK_SIZE]; + word32 tagSz = (word32)sizeof(tag); + WC_DECLARE_VAR(cmac, Cmac, 1, HEAP_HINT); + + WC_ALLOC_VAR(cmac, Cmac, 1, HEAP_HINT); +#ifdef WC_DECLARE_VAR_IS_HEAP_ALLOC + ExpectNotNull(cmac); +#endif + + ExpectIntEQ(wc_CryptoCb_RegisterDevice(devId, cmac_free_test_crypto_cb, + &freeSeen), 0); + + /* wc_CmacFinal() internally frees the Cmac -> free dispatched to device. */ + ExpectIntEQ(wc_InitCmac_ex(cmac, key16, (word32)sizeof(key16), WC_CMAC_AES, + NULL, HEAP_HINT, devId), 0); + ExpectIntEQ(wc_CmacUpdate(cmac, in, (word32)sizeof(in)), 0); + freeSeen = 0; + ExpectIntEQ(wc_CmacFinal(cmac, tag, &tagSz), 0); + ExpectIntGE(freeSeen, 1); + + /* Explicit wc_CmacFree() also dispatches to the device. */ + tagSz = (word32)sizeof(tag); + ExpectIntEQ(wc_InitCmac_ex(cmac, key16, (word32)sizeof(key16), WC_CMAC_AES, + NULL, HEAP_HINT, devId), 0); + ExpectIntEQ(wc_CmacUpdate(cmac, in, (word32)sizeof(in)), 0); + freeSeen = 0; + ExpectIntEQ(wc_CmacFree(cmac), 0); + ExpectIntGE(freeSeen, 1); + + wc_CryptoCb_UnRegisterDevice(devId); + + WC_FREE_VAR(cmac, HEAP_HINT); +#endif + return EXPECT_RESULT(); +} /* END test_wc_CryptoCb_CmacFree */ diff --git a/tests/api/test_cmac.h b/tests/api/test_cmac.h index e7e4616c0a..28272c59a6 100644 --- a/tests/api/test_cmac.h +++ b/tests/api/test_cmac.h @@ -34,6 +34,7 @@ int test_wc_InitCmac_Label(void); int test_wc_AesCmacGenerateExDecisionCoverage(void); int test_wc_AesCmacVerifyExDecisionCoverage(void); int test_wc_AesCmacVerify_CryptoCb_LenMismatch(void); +int test_wc_CryptoCb_CmacFree(void); #define TEST_CMAC_DECLS \ TEST_DECL_GROUP("cmac", test_wc_InitCmac), \ @@ -45,6 +46,7 @@ int test_wc_AesCmacVerify_CryptoCb_LenMismatch(void); TEST_DECL_GROUP("cmac", test_wc_InitCmac_Label), \ TEST_DECL_GROUP("cmac", test_wc_AesCmacGenerateExDecisionCoverage), \ TEST_DECL_GROUP("cmac", test_wc_AesCmacVerifyExDecisionCoverage), \ - TEST_DECL_GROUP("cmac", test_wc_AesCmacVerify_CryptoCb_LenMismatch) + TEST_DECL_GROUP("cmac", test_wc_AesCmacVerify_CryptoCb_LenMismatch), \ + TEST_DECL_GROUP("cmac", test_wc_CryptoCb_CmacFree) #endif /* WOLFCRYPT_TEST_CMAC_H */ diff --git a/tests/api/test_ed448.c b/tests/api/test_ed448.c index 2fe404b9c9..922b027a96 100644 --- a/tests/api/test_ed448.c +++ b/tests/api/test_ed448.c @@ -30,6 +30,9 @@ #include #include +#ifdef WOLF_CRYPTO_CB + #include +#endif #include #include @@ -1369,3 +1372,126 @@ int test_wc_ed448_check_key_decisions(void) return EXPECT_RESULT(); } /* END test_wc_ed448_check_key_decisions */ +/* Test Ed448 sign/verify routed through a crypto callback (CryptoCb) device. */ +#if defined(WOLF_CRYPTO_CB) && defined(HAVE_ED448) && \ + defined(HAVE_ED448_SIGN) && defined(HAVE_ED448_VERIFY) && \ + !defined(WC_NO_RNG) +typedef struct ed448SpyCtx { + int signSeen; + int verifySeen; +} ed448SpyCtx; + +/* Spy device: services Ed448 sign/verify in software (devId cleared) and counts + * each; declines everything else so make_key runs in software. */ +static int ed448_test_crypto_cb(int devIdArg, wc_CryptoInfo* info, void* ctx) +{ + ed448SpyCtx* spy = (ed448SpyCtx*)ctx; + int ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE); + + (void)devIdArg; + + if (info == NULL || spy == NULL) { + return BAD_FUNC_ARG; + } + + if (info->algo_type == WC_ALGO_TYPE_PK) { + #ifdef HAVE_ED448_SIGN + if (info->pk.type == WC_PK_TYPE_ED448) { + int save = info->pk.ed448sign.key->devId; + info->pk.ed448sign.key->devId = INVALID_DEVID; + ret = wc_ed448_sign_msg_ex( + info->pk.ed448sign.in, info->pk.ed448sign.inLen, + info->pk.ed448sign.out, info->pk.ed448sign.outLen, + info->pk.ed448sign.key, info->pk.ed448sign.type, + info->pk.ed448sign.context, info->pk.ed448sign.contextLen); + info->pk.ed448sign.key->devId = save; + spy->signSeen++; + } + #endif + #ifdef HAVE_ED448_VERIFY + if (info->pk.type == WC_PK_TYPE_ED448_VERIFY) { + int save = info->pk.ed448verify.key->devId; + info->pk.ed448verify.key->devId = INVALID_DEVID; + ret = wc_ed448_verify_msg_ex( + info->pk.ed448verify.sig, info->pk.ed448verify.sigLen, + info->pk.ed448verify.msg, info->pk.ed448verify.msgLen, + info->pk.ed448verify.res, info->pk.ed448verify.key, + info->pk.ed448verify.type, info->pk.ed448verify.context, + info->pk.ed448verify.contextLen); + info->pk.ed448verify.key->devId = save; + spy->verifySeen++; + } + #endif + } + + return ret; +} +#endif + +int test_wc_ed448_cryptocb(void) +{ + EXPECT_DECLS; +#if defined(WOLF_CRYPTO_CB) && defined(HAVE_ED448) && \ + defined(HAVE_ED448_SIGN) && defined(HAVE_ED448_VERIFY) && \ + !defined(WC_NO_RNG) + int devId = 4448; + ed448SpyCtx spy; + WC_RNG rng; + byte msg[32]; + word32 sigLen = ED448_SIG_SIZE; + int verify = 0; + WC_DECLARE_VAR(key, ed448_key, 1, HEAP_HINT); + WC_DECLARE_VAR(sig, byte, ED448_SIG_SIZE, HEAP_HINT); + + XMEMSET(&rng, 0, sizeof(rng)); + XMEMSET(&spy, 0, sizeof(spy)); + XMEMSET(msg, 0x5a, sizeof(msg)); + + WC_ALLOC_VAR(key, ed448_key, 1, HEAP_HINT); + WC_ALLOC_VAR(sig, byte, ED448_SIG_SIZE, HEAP_HINT); +#ifdef WC_DECLARE_VAR_IS_HEAP_ALLOC + ExpectNotNull(key); + ExpectNotNull(sig); +#endif + if (WC_VAR_OK(sig)) { + XMEMSET(sig, 0, ED448_SIG_SIZE); + } + + ExpectIntEQ(wc_CryptoCb_RegisterDevice(devId, ed448_test_crypto_cb, &spy), + 0); + ExpectIntEQ(wc_InitRng(&rng), 0); + ExpectIntEQ(wc_ed448_init_ex(key, HEAP_HINT, devId), 0); + ExpectIntEQ(wc_ed448_make_key(&rng, ED448_KEY_SIZE, key), 0); + + /* Sign routes through the device callback. */ + ExpectIntEQ(wc_ed448_sign_msg(msg, (word32)sizeof(msg), sig, &sigLen, key, + NULL, 0), 0); + ExpectIntGE(spy.signSeen, 1); + + /* Verify routes through the device callback. */ + ExpectIntEQ(wc_ed448_verify_msg(sig, sigLen, msg, (word32)sizeof(msg), + &verify, key, NULL, 0), 0); + ExpectIntGE(spy.verifySeen, 1); + ExpectIntEQ(verify, 1); + + /* Negative: corrupt the signature. Ed448 reports a bad signature as + * SIG_VERIFY_E, exercising the device verify error path (verify == 0). */ + if (WC_VAR_OK(sig)) { + sig[0] ^= 0xFF; + } + verify = 1; + ExpectIntEQ(wc_ed448_verify_msg(sig, sigLen, msg, (word32)sizeof(msg), + &verify, key, NULL, 0), + WC_NO_ERR_TRACE(SIG_VERIFY_E)); + ExpectIntGE(spy.verifySeen, 2); + ExpectIntEQ(verify, 0); + + wc_ed448_free(key); + DoExpectIntEQ(wc_FreeRng(&rng), 0); + wc_CryptoCb_UnRegisterDevice(devId); + + WC_FREE_VAR(sig, HEAP_HINT); + WC_FREE_VAR(key, HEAP_HINT); +#endif + return EXPECT_RESULT(); +} diff --git a/tests/api/test_ed448.h b/tests/api/test_ed448.h index 169c88a39c..a19dab9e01 100644 --- a/tests/api/test_ed448.h +++ b/tests/api/test_ed448.h @@ -42,6 +42,7 @@ int test_wc_Ed448DecisionCoverage(void); int test_wc_Ed448FeatureCoverage(void); int test_wc_ed448_import_private_only(void); int test_wc_ed448_check_key_decisions(void); +int test_wc_ed448_cryptocb(void); #define TEST_ED448_DECLS \ TEST_DECL_GROUP("ed448", test_wc_ed448_make_key), \ @@ -61,6 +62,7 @@ int test_wc_ed448_check_key_decisions(void); TEST_DECL_GROUP("ed448", test_wc_Ed448DecisionCoverage), \ TEST_DECL_GROUP("ed448", test_wc_Ed448FeatureCoverage), \ TEST_DECL_GROUP("ed448", test_wc_ed448_import_private_only), \ - TEST_DECL_GROUP("ed448", test_wc_ed448_check_key_decisions) + TEST_DECL_GROUP("ed448", test_wc_ed448_check_key_decisions), \ + TEST_DECL_GROUP("ed448", test_wc_ed448_cryptocb) #endif /* WOLFCRYPT_TEST_ED448_H */ diff --git a/tests/api/test_rsa.c b/tests/api/test_rsa.c index bd1c6b4482..4bf190f67e 100644 --- a/tests/api/test_rsa.c +++ b/tests/api/test_rsa.c @@ -36,6 +36,9 @@ #ifdef WOLFSSL_SHA384 #include #endif +#ifdef WOLF_CRYPTO_CB + #include +#endif #include #include @@ -1999,3 +2002,154 @@ int test_wc_RsaFeatureCoverage(void) #endif return EXPECT_RESULT(); } /* END test_wc_RsaFeatureCoverage */ + +/* Test that wc_RsaPSS_VerifyCheck() routes RSA-PSS verification through a + * registered crypto callback (CryptoCb) device. */ +#if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_RSA_PAD) && \ + defined(WC_RSA_PSS) && !defined(NO_RSA) && !defined(WC_NO_RNG) && \ + defined(WOLFSSL_KEY_GEN) && !defined(NO_SHA256) +/* Spy device: on RSA-PSS verify counts the request, verifies in software and + * reports via res; declines other pk types so sign / keygen run in software. */ +static int rsa_pss_test_crypto_cb(int devIdArg, wc_CryptoInfo* info, void* ctx) +{ + int* pssVerifySeen = (int*)ctx; + + (void)devIdArg; + + if (info == NULL) { + return BAD_FUNC_ARG; + } + + if (info->algo_type == WC_ALGO_TYPE_PK && + info->pk.type == WC_PK_TYPE_RSA_PSS_VERIFY) { + RsaKey* key = info->pk.rsa_pss_verify.key; + int save; + int v; + byte* outbuf; + word32 outbufSz = 512; + + outbuf = (byte*)XMALLOC(outbufSz, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (outbuf == NULL) { + return MEMORY_E; + } + + if (pssVerifySeen != NULL) { + (*pssVerifySeen)++; + } + + save = key->devId; + key->devId = INVALID_DEVID; + v = wc_RsaPSS_VerifyCheck( + info->pk.rsa_pss_verify.sig, info->pk.rsa_pss_verify.sigSz, + outbuf, outbufSz, + info->pk.rsa_pss_verify.digest, info->pk.rsa_pss_verify.digestSz, + info->pk.rsa_pss_verify.hash, info->pk.rsa_pss_verify.mgf, + key); + key->devId = save; + + XFREE(outbuf, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + + /* Only a real verdict maps to res; a genuine internal error (e.g. + * MEMORY_E) is propagated so it is not masked as a bad signature. */ + if (v > 0) { + if (info->pk.rsa_pss_verify.res != NULL) + *info->pk.rsa_pss_verify.res = 1; + return 0; + } + if (v == WC_NO_ERR_TRACE(BAD_PADDING_E) || + v == WC_NO_ERR_TRACE(SIG_VERIFY_E)) { + if (info->pk.rsa_pss_verify.res != NULL) + *info->pk.rsa_pss_verify.res = 0; + return 0; + } + return v; + } + + return WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE); +} +#endif + +int test_wc_CryptoCb_RsaPssVerify(void) +{ + EXPECT_DECLS; +#if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_RSA_PAD) && \ + defined(WC_RSA_PSS) && !defined(NO_RSA) && !defined(WC_NO_RNG) && \ + defined(WOLFSSL_KEY_GEN) && !defined(NO_SHA256) + int devId = 4470; + int pssVerifySeen = 0; + WC_RNG rng; + byte digest[WC_SHA256_DIGEST_SIZE]; + word32 sigLen = 0; + int r; + WC_DECLARE_VAR(key, RsaKey, 1, HEAP_HINT); + WC_DECLARE_VAR(sig, byte, 512, HEAP_HINT); + WC_DECLARE_VAR(rec, byte, 512, HEAP_HINT); + + XMEMSET(&rng, 0, sizeof(rng)); + XMEMSET(digest, 0x2b, sizeof(digest)); + + WC_ALLOC_VAR(key, RsaKey, 1, HEAP_HINT); + WC_ALLOC_VAR(sig, byte, 512, HEAP_HINT); + WC_ALLOC_VAR(rec, byte, 512, HEAP_HINT); +#ifdef WC_DECLARE_VAR_IS_HEAP_ALLOC + ExpectNotNull(key); + ExpectNotNull(sig); + ExpectNotNull(rec); +#endif + if (WC_VAR_OK(sig)) { + XMEMSET(sig, 0, 512); + } + if (WC_VAR_OK(rec)) { + XMEMSET(rec, 0, 512); + } + + ExpectIntEQ(wc_CryptoCb_RegisterDevice(devId, rsa_pss_test_crypto_cb, + &pssVerifySeen), 0); + ExpectIntEQ(wc_InitRng(&rng), 0); + ExpectIntEQ(wc_InitRsaKey_ex(key, HEAP_HINT, devId), 0); + ExpectIntEQ(wc_MakeRsaKey(key, 2048, WC_RSA_EXPONENT, &rng), 0); + ExpectIntEQ(wc_RsaSetRNG(key, &rng), 0); + + /* PSS sign runs in software (device declines). */ + ExpectIntGT(sigLen = (word32)wc_RsaPSS_Sign(digest, + (word32)sizeof(digest), sig, 512, WC_HASH_TYPE_SHA256, WC_MGF1SHA256, + key, &rng), 0); + + /* Positive: verify routes through the device and succeeds. */ + pssVerifySeen = 0; + ExpectIntGT(r = wc_RsaPSS_VerifyCheck(sig, sigLen, rec, 512, digest, + (word32)sizeof(digest), WC_HASH_TYPE_SHA256, WC_MGF1SHA256, key), 0); + ExpectIntGE(pssVerifySeen, 1); + + /* Positive: the inline variant also routes through the device; *out is NULL + * on that path. Use a copy of the sig since inline 'in' is reused as out. */ + if (WC_VAR_OK(sig) && WC_VAR_OK(rec)) { + byte* inlineOut = rec; /* non-NULL sentinel, must be cleared to NULL */ + XMEMCPY(rec, sig, sigLen); + pssVerifySeen = 0; + ExpectIntGT(wc_RsaPSS_VerifyCheckInline(rec, sigLen, &inlineOut, digest, + (word32)sizeof(digest), WC_HASH_TYPE_SHA256, WC_MGF1SHA256, key), 0); + ExpectIntGE(pssVerifySeen, 1); + ExpectNull(inlineOut); + } + + /* Negative: corrupt the signature; the device sets res=0 so VerifyCheck + * returns SIG_VERIFY_E (<= 0). */ + if (WC_VAR_OK(sig)) { + sig[0] ^= 0xFF; + } + pssVerifySeen = 0; + ExpectIntLE(wc_RsaPSS_VerifyCheck(sig, sigLen, rec, 512, digest, + (word32)sizeof(digest), WC_HASH_TYPE_SHA256, WC_MGF1SHA256, key), 0); + ExpectIntGE(pssVerifySeen, 1); + + DoExpectIntEQ(wc_FreeRsaKey(key), 0); + DoExpectIntEQ(wc_FreeRng(&rng), 0); + wc_CryptoCb_UnRegisterDevice(devId); + + WC_FREE_VAR(rec, HEAP_HINT); + WC_FREE_VAR(sig, HEAP_HINT); + WC_FREE_VAR(key, HEAP_HINT); +#endif + return EXPECT_RESULT(); +} /* END test_wc_CryptoCb_RsaPssVerify */ diff --git a/tests/api/test_rsa.h b/tests/api/test_rsa.h index 69081a5cc5..13d503101e 100644 --- a/tests/api/test_rsa.h +++ b/tests/api/test_rsa.h @@ -47,6 +47,7 @@ int test_wc_RsaFunctionCheckIn_OversizedModulus(void); int test_wc_RsaKeyToDer_SizeOverflow(void); int test_wc_RsaDecisionCoverage(void); int test_wc_RsaFeatureCoverage(void); +int test_wc_CryptoCb_RsaPssVerify(void); #define TEST_RSA_DECLS \ TEST_DECL_GROUP("rsa", test_wc_InitRsaKey), \ @@ -71,6 +72,7 @@ int test_wc_RsaFeatureCoverage(void); TEST_DECL_GROUP("rsa", test_wc_RsaFunctionCheckIn_OversizedModulus), \ TEST_DECL_GROUP("rsa", test_wc_RsaKeyToDer_SizeOverflow), \ TEST_DECL_GROUP("rsa", test_wc_RsaDecisionCoverage), \ - TEST_DECL_GROUP("rsa", test_wc_RsaFeatureCoverage) + TEST_DECL_GROUP("rsa", test_wc_RsaFeatureCoverage), \ + TEST_DECL_GROUP("rsa", test_wc_CryptoCb_RsaPssVerify) #endif /* WOLFCRYPT_TEST_RSA_H */ diff --git a/wolfcrypt/src/cmac.c b/wolfcrypt/src/cmac.c index cc05015d65..202a3d5809 100644 --- a/wolfcrypt/src/cmac.c +++ b/wolfcrypt/src/cmac.c @@ -366,6 +366,17 @@ int wc_CmacFree(Cmac* cmac) { if (cmac == NULL) return BAD_FUNC_ARG; +#if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_FREE) + /* Let the device release any per-context state it hung off cmac->devCtx + * before the struct is zeroed (e.g. an offload context never finalized). */ + #ifndef WOLF_CRYPTO_CB_FIND + if (cmac->devId != INVALID_DEVID) + #endif + { + (void)wc_CryptoCb_Free(cmac->devId, WC_ALGO_TYPE_CMAC, (int)cmac->type, + 0, cmac); + } +#endif #if defined(WOLFSSL_HASH_KEEP) /* TODO: msg is leaked if wc_CmacFinal() is not called * e.g. when multiple calls to wc_CmacUpdate() and one fails but diff --git a/wolfcrypt/src/cryptocb.c b/wolfcrypt/src/cryptocb.c index cb155e0c1e..4e3ad4b6bf 100644 --- a/wolfcrypt/src/cryptocb.c +++ b/wolfcrypt/src/cryptocb.c @@ -145,12 +145,15 @@ static const char* GetPkTypeStr(int pk) { switch (pk) { case WC_PK_TYPE_RSA: return "RSA"; + case WC_PK_TYPE_RSA_PSS_VERIFY: return "RSA-PSS-Verify"; case WC_PK_TYPE_DH: return "DH"; case WC_PK_TYPE_ECDH: return "ECDH"; case WC_PK_TYPE_ECDSA_SIGN: return "ECDSA-Sign"; case WC_PK_TYPE_ECDSA_VERIFY: return "ECDSA-Verify"; case WC_PK_TYPE_ED25519_SIGN: return "ED25519-Sign"; case WC_PK_TYPE_ED25519_VERIFY: return "ED25519-Verify"; + case WC_PK_TYPE_ED448: return "ED448-Sign"; + case WC_PK_TYPE_ED448_VERIFY: return "ED448-Verify"; case WC_PK_TYPE_CURVE25519: return "CURVE25519"; case WC_PK_TYPE_RSA_KEYGEN: return "RSA KeyGen"; case WC_PK_TYPE_EC_KEYGEN: return "ECC KeyGen"; @@ -627,6 +630,42 @@ int wc_CryptoCb_RsaPad(const byte* in, word32 inLen, byte* out, return wc_CryptoCb_TranslateErrorCode(ret); } + +/* Verify an RSA-PSS signature on the device (padding included). Passes both the + * signature and digest so the device does the whole verify and returns a verdict. */ +int wc_CryptoCb_RsaPssVerify(const byte* sig, word32 sigSz, const byte* digest, + word32 digestSz, enum wc_HashType hash, int mgf, int saltLen, RsaKey* key, + int* res) +{ + int ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE); + CryptoCb* dev; + + if (key == NULL) + return ret; + + /* locate registered callback */ + dev = wc_CryptoCb_FindDevice(key->devId, WC_ALGO_TYPE_PK); + + if (dev && dev->cb) { + wc_CryptoInfo cryptoInfo; + XMEMSET(&cryptoInfo, 0, sizeof(cryptoInfo)); + cryptoInfo.algo_type = WC_ALGO_TYPE_PK; + cryptoInfo.pk.type = WC_PK_TYPE_RSA_PSS_VERIFY; + cryptoInfo.pk.rsa_pss_verify.sig = sig; + cryptoInfo.pk.rsa_pss_verify.sigSz = sigSz; + cryptoInfo.pk.rsa_pss_verify.digest = digest; + cryptoInfo.pk.rsa_pss_verify.digestSz = digestSz; + cryptoInfo.pk.rsa_pss_verify.hash = hash; + cryptoInfo.pk.rsa_pss_verify.mgf = mgf; + cryptoInfo.pk.rsa_pss_verify.saltLen = saltLen; + cryptoInfo.pk.rsa_pss_verify.key = key; + cryptoInfo.pk.rsa_pss_verify.res = res; + + ret = dev->cb(dev->devId, &cryptoInfo, dev->ctx); + } + + return wc_CryptoCb_TranslateErrorCode(ret); +} #endif /* WOLF_CRYPTO_CB_RSA_PAD */ #ifdef WOLFSSL_KEY_GEN @@ -1227,6 +1266,73 @@ int wc_CryptoCb_Ed25519CheckKey(ed25519_key* key) } #endif /* HAVE_ED25519 */ +#ifdef HAVE_ED448 +int wc_CryptoCb_Ed448Sign(const byte* in, word32 inLen, byte* out, + word32 *outLen, ed448_key* key, byte type, const byte* context, + byte contextLen) +{ + int ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE); + CryptoCb* dev; + + if (key == NULL) + return ret; + + /* locate registered callback */ + dev = wc_CryptoCb_FindDevice(key->devId, WC_ALGO_TYPE_PK); + if (dev && dev->cb) { + wc_CryptoInfo cryptoInfo; + XMEMSET(&cryptoInfo, 0, sizeof(cryptoInfo)); + cryptoInfo.algo_type = WC_ALGO_TYPE_PK; + cryptoInfo.pk.type = WC_PK_TYPE_ED448; + cryptoInfo.pk.ed448sign.in = in; + cryptoInfo.pk.ed448sign.inLen = inLen; + cryptoInfo.pk.ed448sign.out = out; + cryptoInfo.pk.ed448sign.outLen = outLen; + cryptoInfo.pk.ed448sign.key = key; + cryptoInfo.pk.ed448sign.type = type; + cryptoInfo.pk.ed448sign.context = context; + cryptoInfo.pk.ed448sign.contextLen = contextLen; + + ret = dev->cb(dev->devId, &cryptoInfo, dev->ctx); + } + + return wc_CryptoCb_TranslateErrorCode(ret); +} + +int wc_CryptoCb_Ed448Verify(const byte* sig, word32 sigLen, + const byte* msg, word32 msgLen, int* res, ed448_key* key, byte type, + const byte* context, byte contextLen) +{ + int ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE); + CryptoCb* dev; + + if (key == NULL) + return ret; + + /* locate registered callback */ + dev = wc_CryptoCb_FindDevice(key->devId, WC_ALGO_TYPE_PK); + if (dev && dev->cb) { + wc_CryptoInfo cryptoInfo; + XMEMSET(&cryptoInfo, 0, sizeof(cryptoInfo)); + cryptoInfo.algo_type = WC_ALGO_TYPE_PK; + cryptoInfo.pk.type = WC_PK_TYPE_ED448_VERIFY; + cryptoInfo.pk.ed448verify.sig = sig; + cryptoInfo.pk.ed448verify.sigLen = sigLen; + cryptoInfo.pk.ed448verify.msg = msg; + cryptoInfo.pk.ed448verify.msgLen = msgLen; + cryptoInfo.pk.ed448verify.res = res; + cryptoInfo.pk.ed448verify.key = key; + cryptoInfo.pk.ed448verify.type = type; + cryptoInfo.pk.ed448verify.context = context; + cryptoInfo.pk.ed448verify.contextLen = contextLen; + + ret = dev->cb(dev->devId, &cryptoInfo, dev->ctx); + } + + return wc_CryptoCb_TranslateErrorCode(ret); +} +#endif /* HAVE_ED448 */ + #if defined(WOLFSSL_HAVE_LMS) || defined(WOLFSSL_HAVE_XMSS) int wc_CryptoCb_PqcStatefulSigGetDevId(int type, void* key) { diff --git a/wolfcrypt/src/ed448.c b/wolfcrypt/src/ed448.c index b25e3ff23f..ba97202849 100644 --- a/wolfcrypt/src/ed448.c +++ b/wolfcrypt/src/ed448.c @@ -47,6 +47,9 @@ #include #include +#ifdef WOLF_CRYPTO_CB + #include +#endif #ifdef NO_INLINE #include #else @@ -447,6 +450,17 @@ int wc_ed448_sign_msg_ex(const byte* in, word32 inLen, byte* out, ((context == NULL) && (contextLen != 0))) { ret = BAD_FUNC_ARG; } + +#ifdef WOLF_CRYPTO_CB + if ((ret == 0) && (key->devId != INVALID_DEVID)) { + ret = wc_CryptoCb_Ed448Sign(in, inLen, out, outLen, key, type, context, + contextLen); + if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) + return ret; + ret = 0; /* device unavailable: fall back to software */ + } +#endif + if ((ret == 0) && (!key->pubKeySet)) { ret = BAD_FUNC_ARG; } @@ -902,6 +916,16 @@ int wc_ed448_verify_msg_ex(const byte* sig, word32 sigLen, const byte* msg, return BAD_LENGTH_E; } +#ifdef WOLF_CRYPTO_CB + if (key->devId != INVALID_DEVID) { + ret = wc_CryptoCb_Ed448Verify(sig, sigLen, msg, msgLen, res, key, type, + context, contextLen); + if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) + return ret; + /* device unavailable: fall back to software */ + } +#endif + #ifdef WOLFSSL_ED448_PERSISTENT_SHA sha = &key->sha; #else diff --git a/wolfcrypt/src/rsa.c b/wolfcrypt/src/rsa.c index 096c0e50e2..0702b1727f 100644 --- a/wolfcrypt/src/rsa.c +++ b/wolfcrypt/src/rsa.c @@ -4635,6 +4635,9 @@ int wc_RsaPSS_CheckPadding_ex(const byte* in, word32 inSz, const byte* sig, * mgf Mask generation function. * key Public RSA key. * returns the length of the PSS data on success and negative indicates failure. + * + * Note: when a crypto callback device performs the verify, *out is set to NULL + * even though a positive length is returned; callers must not dereference *out. */ int wc_RsaPSS_VerifyCheckInline(byte* in, word32 inLen, byte** out, const byte* digest, word32 digestLen, @@ -4670,6 +4673,27 @@ int wc_RsaPSS_VerifyCheckInline(byte* in, word32 inLen, byte** out, saltLen = RSA_PSS_SALT_MAX_SZ; #endif +#if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_RSA_PAD) + /* Let a device verify signature + padding in one shot (it gets the digest, + * which the RsaPad path does not). Fall through to software if unavailable. */ + if (key != NULL && key->devId != INVALID_DEVID) { + int res = 0; + ret = wc_CryptoCb_RsaPssVerify(in, inLen, digest, digestLen, hash, mgf, + saltLen, key, &res); + if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) { + if (ret == 0) { + /* Device verified internally; no recovered PSS block to expose, + * so report no inline output rather than a misleading pointer. */ + if (out != NULL) + *out = NULL; + ret = (res != 0) ? (int)inLen : SIG_VERIFY_E; + } + return ret; + } + ret = 0; + } +#endif + verify = wc_RsaPSS_VerifyInline_ex(in, inLen, out, hash, mgf, saltLen, key); if (verify > 0) ret = wc_RsaPSS_CheckPadding_ex(digest, digestLen, *out, (word32)verify, @@ -4730,6 +4754,22 @@ int wc_RsaPSS_VerifyCheck(const byte* in, word32 inLen, byte* out, word32 outLen saltLen = RSA_PSS_SALT_MAX_SZ; #endif +#if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_RSA_PAD) + /* Let a device verify signature + padding in one shot (it gets the digest, + * which the RsaPad path does not). Fall through to software if unavailable. */ + if (key != NULL && key->devId != INVALID_DEVID) { + int res = 0; + ret = wc_CryptoCb_RsaPssVerify(in, inLen, digest, digestLen, hash, mgf, + saltLen, key, &res); + if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) { + if (ret == 0) + ret = (res != 0) ? (int)inLen : SIG_VERIFY_E; + return ret; + } + ret = 0; + } +#endif + verify = wc_RsaPSS_Verify_ex(in, inLen, out, outLen, hash, mgf, saltLen, key); if (verify > 0) diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index def621bde6..647e13cf45 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -76148,6 +76148,16 @@ typedef struct { * public point, simulating a private scalar * resident in the device (input key->k empty) */ #endif +#ifdef HAVE_ED448 + int ed448SignCount; /* Ed448 sign callback invocations */ + int ed448VerifyCount; /* Ed448 verify callback invocations */ +#endif +#if defined(WOLFSSL_CMAC) && defined(WOLF_CRYPTO_CB_FREE) + int cmacFreeCount; /* CMAC free callback invocations */ +#endif +#if defined(WC_RSA_PSS) && defined(WOLF_CRYPTO_CB_RSA_PAD) + int rsaPssVerifyCount; /* RSA-PSS verify callback invocations */ +#endif } myCryptoDevCtx; #ifdef WOLF_CRYPTO_CB_ONLY_RSA @@ -77108,6 +77118,51 @@ static int myCryptoDevCb(int devIdArg, wc_CryptoInfo* info, void* ctx) WOLFSSL_MSG_EX("CryptoDevCb: Pk Type %d\n", info->pk.type); #endif + #if defined(WC_RSA_PSS) && defined(WOLF_CRYPTO_CB_RSA_PAD) + if (info->pk.type == WC_PK_TYPE_RSA_PSS_VERIFY) { + RsaKey* pssKey = info->pk.rsa_pss_verify.key; + int pssSaveDevId = pssKey->devId; + int pssVer = 0; + byte* pssOut; + word32 pssOutSz = 512; + + pssOut = (byte*)XMALLOC(pssOutSz, HEAP_HINT, + DYNAMIC_TYPE_TMP_BUFFER); + if (pssOut == NULL) + return MEMORY_E; + + myCtx->rsaPssVerifyCount++; + + /* perform software based RSA-PSS verify */ + pssKey->devId = INVALID_DEVID; + pssVer = wc_RsaPSS_VerifyCheck( + info->pk.rsa_pss_verify.sig, info->pk.rsa_pss_verify.sigSz, + pssOut, pssOutSz, + info->pk.rsa_pss_verify.digest, + info->pk.rsa_pss_verify.digestSz, + info->pk.rsa_pss_verify.hash, info->pk.rsa_pss_verify.mgf, + pssKey); + pssKey->devId = pssSaveDevId; + + XFREE(pssOut, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + + /* Only a real verdict maps to res; a genuine internal error (e.g. + * MEMORY_E) is propagated so it is not masked as a bad signature. */ + if (pssVer > 0) { + if (info->pk.rsa_pss_verify.res != NULL) + *info->pk.rsa_pss_verify.res = 1; + return 0; + } + if (pssVer == WC_NO_ERR_TRACE(BAD_PADDING_E) || + pssVer == WC_NO_ERR_TRACE(SIG_VERIFY_E)) { + if (info->pk.rsa_pss_verify.res != NULL) + *info->pk.rsa_pss_verify.res = 0; + return 0; + } + return pssVer; + } + #endif /* WC_RSA_PSS && WOLF_CRYPTO_CB_RSA_PAD */ + #ifndef NO_RSA if (info->pk.type == WC_PK_TYPE_RSA) { /* set devId to invalid, so software is used */ @@ -77574,6 +77629,43 @@ static int myCryptoDevCb(int devIdArg, wc_CryptoInfo* info, void* ctx) info->pk.ed25519checkkey.key->devId = devIdArg; } #endif /* HAVE_ED25519 */ + #ifdef HAVE_ED448 + #ifdef HAVE_ED448_SIGN + if (info->pk.type == WC_PK_TYPE_ED448) { + /* set devId to invalid, so software is used */ + info->pk.ed448sign.key->devId = INVALID_DEVID; + + ret = wc_ed448_sign_msg_ex( + info->pk.ed448sign.in, info->pk.ed448sign.inLen, + info->pk.ed448sign.out, info->pk.ed448sign.outLen, + info->pk.ed448sign.key, info->pk.ed448sign.type, + info->pk.ed448sign.context, info->pk.ed448sign.contextLen); + + /* reset devId */ + info->pk.ed448sign.key->devId = devIdArg; + + myCtx->ed448SignCount++; + } + #endif + #ifdef HAVE_ED448_VERIFY + if (info->pk.type == WC_PK_TYPE_ED448_VERIFY) { + /* set devId to invalid, so software is used */ + info->pk.ed448verify.key->devId = INVALID_DEVID; + + ret = wc_ed448_verify_msg_ex( + info->pk.ed448verify.sig, info->pk.ed448verify.sigLen, + info->pk.ed448verify.msg, info->pk.ed448verify.msgLen, + info->pk.ed448verify.res, info->pk.ed448verify.key, + info->pk.ed448verify.type, info->pk.ed448verify.context, + info->pk.ed448verify.contextLen); + + /* reset devId */ + info->pk.ed448verify.key->devId = devIdArg; + + myCtx->ed448VerifyCount++; + } + #endif + #endif /* HAVE_ED448 */ #if defined(WOLFSSL_HAVE_LMS) || defined(WOLFSSL_HAVE_XMSS) if (info->pk.type == WC_PK_TYPE_PQC_STATEFUL_SIG_KEYGEN) { int pqcType = info->pk.pqc_stateful_sig_kg.type; @@ -78817,6 +78909,13 @@ static int myCryptoDevCb(int devIdArg, wc_CryptoInfo* info, void* ctx) ret = WC_NO_ERR_TRACE(NOT_COMPILED_IN); #endif } +#if defined(WOLFSSL_CMAC) + else if (info->free.algo == WC_ALGO_TYPE_CMAC) { + /* count the CMAC free dispatch and let software do the free */ + myCtx->cmacFreeCount++; + ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE); + } +#endif else { ret = WC_NO_ERR_TRACE(NOT_COMPILED_IN); } @@ -79434,6 +79533,16 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t cryptocb_test(void) myCtx.eccCheckPubSawZeroPoint = 0; myCtx.eccResidentKey = NULL; #endif +#ifdef HAVE_ED448 + myCtx.ed448SignCount = 0; + myCtx.ed448VerifyCount = 0; +#endif +#if defined(WOLFSSL_CMAC) && defined(WOLF_CRYPTO_CB_FREE) + myCtx.cmacFreeCount = 0; +#endif +#if defined(WC_RSA_PSS) && defined(WOLF_CRYPTO_CB_RSA_PAD) + myCtx.rsaPssVerifyCount = 0; +#endif /* set devId to something other than INVALID_DEVID */ devId = 1; @@ -79884,6 +79993,196 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t cryptocb_test(void) ret = cmac_test(); #endif + /* Driver coverage for the new CryptoCb hooks: confirm each op is routed + * through myCryptoDevCb (counter bumped) and the round-trip is correct. */ +#if defined(HAVE_ED448) && defined(HAVE_ED448_SIGN) && \ + defined(HAVE_ED448_VERIFY) && !defined(WC_NO_RNG) + if (ret == 0) { + WC_RNG ed448Rng; + int ed448RngInit = 0; + byte ed448Msg[32]; + word32 ed448SigLen = ED448_SIG_SIZE; + int ed448Verify = 0; + WC_DECLARE_VAR(ed448Key, ed448_key, 1, HEAP_HINT); + WC_DECLARE_VAR(ed448Sig, byte, ED448_SIG_SIZE, HEAP_HINT); + + WC_ALLOC_VAR_EX(ed448Key, ed448_key, 1, HEAP_HINT, + DYNAMIC_TYPE_TMP_BUFFER, ret = WC_TEST_RET_ENC_EC(MEMORY_E)); + if (ret == 0) + WC_ALLOC_VAR_EX(ed448Sig, byte, ED448_SIG_SIZE, HEAP_HINT, + DYNAMIC_TYPE_TMP_BUFFER, ret = WC_TEST_RET_ENC_EC(MEMORY_E)); + + XMEMSET(ed448Msg, 0x5a, sizeof(ed448Msg)); + myCtx.ed448SignCount = 0; + myCtx.ed448VerifyCount = 0; + + if (ret == 0) { + ret = wc_InitRng_ex(&ed448Rng, HEAP_HINT, devId); + if (ret == 0) + ed448RngInit = 1; + else + ret = WC_TEST_RET_ENC_EC(ret); + } + if (ret == 0) { + ret = wc_ed448_init_ex(ed448Key, HEAP_HINT, devId); + if (ret != 0) + ret = WC_TEST_RET_ENC_EC(ret); + } + if (ret == 0) { + ret = wc_ed448_make_key(&ed448Rng, ED448_KEY_SIZE, ed448Key); + if (ret != 0) + ret = WC_TEST_RET_ENC_EC(ret); + } + if (ret == 0) { + ret = wc_ed448_sign_msg(ed448Msg, (word32)sizeof(ed448Msg), + ed448Sig, &ed448SigLen, ed448Key, NULL, 0); + if (ret != 0) + ret = WC_TEST_RET_ENC_EC(ret); + } + if (ret == 0 && myCtx.ed448SignCount == 0) + ret = WC_TEST_RET_ENC_NC; + if (ret == 0) { + ret = wc_ed448_verify_msg(ed448Sig, ed448SigLen, ed448Msg, + (word32)sizeof(ed448Msg), &ed448Verify, ed448Key, NULL, 0); + if (ret != 0) + ret = WC_TEST_RET_ENC_EC(ret); + } + if (ret == 0 && (myCtx.ed448VerifyCount == 0 || ed448Verify != 1)) + ret = WC_TEST_RET_ENC_NC; + + if (WC_VAR_OK(ed448Key)) + wc_ed448_free(ed448Key); + if (ed448RngInit) + wc_FreeRng(&ed448Rng); + WC_FREE_VAR_EX(ed448Sig, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + WC_FREE_VAR_EX(ed448Key, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif /* HAVE_ED448 */ + +#if defined(WOLFSSL_CMAC) && defined(WOLF_CRYPTO_CB_FREE) && \ + !defined(NO_AES) && defined(WOLFSSL_AES_DIRECT) + if (ret == 0) { + byte cmacKey[16] = { + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10 + }; + byte cmacIn[16] = { + 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, + 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x00 + }; + byte cmacTag[WC_AES_BLOCK_SIZE]; + word32 cmacTagSz = (word32)sizeof(cmacTag); + WC_DECLARE_VAR(cmac, Cmac, 1, HEAP_HINT); + + WC_ALLOC_VAR_EX(cmac, Cmac, 1, HEAP_HINT, + DYNAMIC_TYPE_TMP_BUFFER, ret = WC_TEST_RET_ENC_EC(MEMORY_E)); + + if (ret == 0) { + ret = wc_InitCmac_ex(cmac, cmacKey, (word32)sizeof(cmacKey), + WC_CMAC_AES, NULL, HEAP_HINT, devId); + if (ret != 0) + ret = WC_TEST_RET_ENC_EC(ret); + } + if (ret == 0) { + ret = wc_CmacUpdate(cmac, cmacIn, (word32)sizeof(cmacIn)); + if (ret != 0) + ret = WC_TEST_RET_ENC_EC(ret); + } + if (ret == 0) { + /* wc_CmacFinal() frees the Cmac -> free dispatched to device */ + myCtx.cmacFreeCount = 0; + ret = wc_CmacFinal(cmac, cmacTag, &cmacTagSz); + if (ret != 0) + ret = WC_TEST_RET_ENC_EC(ret); + } + if (ret == 0 && myCtx.cmacFreeCount == 0) + ret = WC_TEST_RET_ENC_NC; + + WC_FREE_VAR_EX(cmac, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif /* WOLFSSL_CMAC && WOLF_CRYPTO_CB_FREE */ + +#if defined(WC_RSA_PSS) && defined(WOLF_CRYPTO_CB_RSA_PAD) && \ + !defined(NO_RSA) && !defined(WC_NO_RNG) && defined(WOLFSSL_KEY_GEN) && \ + !defined(NO_SHA256) + if (ret == 0) { + WC_RNG rsaRng; + int rsaRngInit = 0; + int rsaKeyInit = 0; + byte rsaDigest[WC_SHA256_DIGEST_SIZE]; + word32 rsaSigLen = 0; + int rsaVer; + WC_DECLARE_VAR(rsaKey, RsaKey, 1, HEAP_HINT); + WC_DECLARE_VAR(rsaSig, byte, 512, HEAP_HINT); + WC_DECLARE_VAR(rsaRec, byte, 512, HEAP_HINT); + + WC_ALLOC_VAR_EX(rsaKey, RsaKey, 1, HEAP_HINT, + DYNAMIC_TYPE_TMP_BUFFER, ret = WC_TEST_RET_ENC_EC(MEMORY_E)); + if (ret == 0) + WC_ALLOC_VAR_EX(rsaSig, byte, 512, HEAP_HINT, + DYNAMIC_TYPE_TMP_BUFFER, ret = WC_TEST_RET_ENC_EC(MEMORY_E)); + if (ret == 0) + WC_ALLOC_VAR_EX(rsaRec, byte, 512, HEAP_HINT, + DYNAMIC_TYPE_TMP_BUFFER, ret = WC_TEST_RET_ENC_EC(MEMORY_E)); + + XMEMSET(rsaDigest, 0x2b, sizeof(rsaDigest)); + myCtx.rsaPssVerifyCount = 0; + + if (ret == 0) { + ret = wc_InitRng_ex(&rsaRng, HEAP_HINT, devId); + if (ret == 0) + rsaRngInit = 1; + else + ret = WC_TEST_RET_ENC_EC(ret); + } + if (ret == 0) { + ret = wc_InitRsaKey_ex(rsaKey, HEAP_HINT, devId); + if (ret == 0) + rsaKeyInit = 1; + else + ret = WC_TEST_RET_ENC_EC(ret); + } + if (ret == 0) { + ret = wc_MakeRsaKey(rsaKey, 2048, WC_RSA_EXPONENT, &rsaRng); + if (ret != 0) + ret = WC_TEST_RET_ENC_EC(ret); + } + if (ret == 0) { + ret = wc_RsaSetRNG(rsaKey, &rsaRng); + if (ret != 0) + ret = WC_TEST_RET_ENC_EC(ret); + } + if (ret == 0) { + ret = wc_RsaPSS_Sign(rsaDigest, (word32)sizeof(rsaDigest), rsaSig, + 512, WC_HASH_TYPE_SHA256, WC_MGF1SHA256, rsaKey, &rsaRng); + if (ret > 0) { + rsaSigLen = (word32)ret; + ret = 0; + } + else { + ret = WC_TEST_RET_ENC_EC(ret); + } + } + if (ret == 0) { + rsaVer = wc_RsaPSS_VerifyCheck(rsaSig, rsaSigLen, rsaRec, 512, + rsaDigest, (word32)sizeof(rsaDigest), WC_HASH_TYPE_SHA256, + WC_MGF1SHA256, rsaKey); + if (rsaVer <= 0) + ret = WC_TEST_RET_ENC_EC(rsaVer); + } + if (ret == 0 && myCtx.rsaPssVerifyCount == 0) + ret = WC_TEST_RET_ENC_NC; + + if (rsaKeyInit) + wc_FreeRsaKey(rsaKey); + if (rsaRngInit) + wc_FreeRng(&rsaRng); + WC_FREE_VAR_EX(rsaRec, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + WC_FREE_VAR_EX(rsaSig, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + WC_FREE_VAR_EX(rsaKey, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif /* WC_RSA_PSS && WOLF_CRYPTO_CB_RSA_PAD */ + wc_CryptoCb_UnRegisterDevice(devId); /* restore devId */ diff --git a/wolfssl/wolfcrypt/cryptocb.h b/wolfssl/wolfcrypt/cryptocb.h index 8d2e587e54..3a5299d77e 100644 --- a/wolfssl/wolfcrypt/cryptocb.h +++ b/wolfssl/wolfcrypt/cryptocb.h @@ -71,6 +71,9 @@ #ifdef HAVE_ED25519 #include #endif +#ifdef HAVE_ED448 + #include +#endif #ifdef HAVE_CURVE25519 #include #endif @@ -197,6 +200,19 @@ typedef struct wc_CryptoInfo { const RsaKey* key; int* keySize; } rsa_get_size; + #ifdef WOLF_CRYPTO_CB_RSA_PAD + struct { + const byte* sig; + word32 sigSz; + const byte* digest; + word32 digestSz; + enum wc_HashType hash; + int mgf; + int saltLen; + RsaKey* key; + int* res; + } rsa_pss_verify; + #endif #endif #ifdef HAVE_ECC #ifdef HAVE_ECC_DHE @@ -325,6 +341,29 @@ typedef struct wc_CryptoInfo { * priv/pub consistency */ } ed25519checkkey; #endif + #ifdef HAVE_ED448 + struct { + const byte* in; + word32 inLen; + byte* out; + word32* outLen; + ed448_key* key; + byte type; + const byte* context; + byte contextLen; + } ed448sign; + struct { + const byte* sig; + word32 sigLen; + const byte* msg; + word32 msgLen; + int* res; + ed448_key* key; + byte type; + const byte* context; + byte contextLen; + } ed448verify; + #endif #if defined(WOLFSSL_HAVE_MLKEM) || defined(WOLFSSL_HAVE_FRODOKEM) struct { WC_RNG* rng; @@ -775,6 +814,9 @@ WOLFSSL_LOCAL int wc_CryptoCb_Rsa(const byte* in, word32 inLen, byte* out, #ifdef WOLF_CRYPTO_CB_RSA_PAD WOLFSSL_LOCAL int wc_CryptoCb_RsaPad(const byte* in, word32 inLen, byte* out, word32* outLen, int type, RsaKey* key, WC_RNG* rng, RsaPadding *padding); +WOLFSSL_LOCAL int wc_CryptoCb_RsaPssVerify(const byte* sig, word32 sigSz, + const byte* digest, word32 digestSz, enum wc_HashType hash, int mgf, + int saltLen, RsaKey* key, int* res); #endif #ifdef WOLFSSL_KEY_GEN @@ -835,6 +877,15 @@ WOLFSSL_LOCAL int wc_CryptoCb_Ed25519MakePub(ed25519_key* key, byte* pubKey, WOLFSSL_LOCAL int wc_CryptoCb_Ed25519CheckKey(ed25519_key* key); #endif /* HAVE_ED25519 */ +#ifdef HAVE_ED448 +WOLFSSL_LOCAL int wc_CryptoCb_Ed448Sign(const byte* in, word32 inLen, + byte* out, word32 *outLen, ed448_key* key, byte type, const byte* context, + byte contextLen); +WOLFSSL_LOCAL int wc_CryptoCb_Ed448Verify(const byte* sig, word32 sigLen, + const byte* msg, word32 msgLen, int* res, ed448_key* key, byte type, + const byte* context, byte contextLen); +#endif /* HAVE_ED448 */ + #if defined(WOLFSSL_HAVE_LMS) || defined(WOLFSSL_HAVE_XMSS) WOLFSSL_LOCAL int wc_CryptoCb_PqcStatefulSigGetDevId(int type, void* key); diff --git a/wolfssl/wolfcrypt/rsa.h b/wolfssl/wolfcrypt/rsa.h index 0d0b0cecb8..4b76c30dac 100644 --- a/wolfssl/wolfcrypt/rsa.h +++ b/wolfssl/wolfcrypt/rsa.h @@ -414,6 +414,8 @@ WOLFSSL_API int wc_RsaPSS_CheckPadding_ex2(const byte* in, word32 inLen, const byte* sig, word32 sigSz, enum wc_HashType hashType, int saltLen, int bits, void* heap); +/* Crypto callback (WOLF_CRYPTO_CB_RSA_PAD) path: a positive return still means + * success but *out is set to NULL, so callers must not dereference *out. */ WOLFSSL_API int wc_RsaPSS_VerifyCheckInline(byte* in, word32 inLen, byte** out, const byte* digest, word32 digentLen, enum wc_HashType hash, int mgf, diff --git a/wolfssl/wolfcrypt/types.h b/wolfssl/wolfcrypt/types.h index af98e43ba3..34b9aa5ab9 100644 --- a/wolfssl/wolfcrypt/types.h +++ b/wolfssl/wolfcrypt/types.h @@ -1623,8 +1623,11 @@ enum wc_PkType { WC_PK_TYPE_EC_CHECK_PUB_KEY = 35, WC_PK_TYPE_ED25519_MAKE_PUB = 36, WC_PK_TYPE_ED25519_CHECK_KEY = 37, + WC_PK_TYPE_RSA_PSS_VERIFY = 38, + /* Ed448 sign reuses WC_PK_TYPE_ED448 (12); verify needs its own type. */ + WC_PK_TYPE_ED448_VERIFY = 39, #undef _WC_PK_TYPE_MAX - #define _WC_PK_TYPE_MAX WC_PK_TYPE_ED25519_CHECK_KEY + #define _WC_PK_TYPE_MAX WC_PK_TYPE_ED448_VERIFY WC_PK_TYPE_MAX = _WC_PK_TYPE_MAX };