Extend the RSA-PSS verify callback and harden the Ed448/CMAC hooks

The PSS hook can hand back the recovered block through out/outSz/outLen.
A device that reports only a verdict leaves outLen at 0; wolfSSL then
zeroes the buffer and returns saltLen + hLen, and rejects a buffer
smaller than that with RSA_BUFFER_E. A reported length is clamped to the
buffer size, and any positive handler return maps to SIG_VERIFY_E.

Move the Ed448 sign WOLFSSL_CHECK_MEM_ZERO registration below the crypto
callback hook so the device path no longer returns past it, and guard the
RSA-PSS test callback against WOLF_CRYPTO_CB_ONLY_RSA.

Adds tests for the recovered-data, over-claimed-length and undersized
buffer paths, and an os-check config that builds the hooks under
WOLFSSL_CHECK_MEM_ZERO.
pull/10886/head
night1rider 2026-08-08 15:10:06 -06:00
parent 33e03a5ce4
commit 375febc944
11 changed files with 337 additions and 58 deletions

View File

@ -130,6 +130,11 @@
"comment": "Exercises the AES-CFB/OFB crypto callback wiring (wc_CryptoCb_AesCfb/Ofb Encrypt/Decrypt, the aes.c hooks, and the dedicated offload unit tests). A normal (non-ONLY) cryptocb build keeps the host software AES present as the callbacks' offload fallback; WOLF_CRYPTO_CB_ONLY_AES (no software fallback) is covered separately by cryptocb-only.yml via swdev.",
"configure": ["--enable-cryptocb", "--enable-aescfb",
"--enable-aesofb", "--enable-aesctr"]},
{"name": "cryptocb-hooks-check-mem-zero", "minutes": 2.2,
"comment": "Ed448/CMAC/RSA-PSS crypto callback hooks under WOLFSSL_CHECK_MEM_ZERO. The Ed448 sign hook returns early past the secret-buffer registration, which a cryptocb build without this define does not catch.",
"configure": ["--enable-cryptocb", "--enable-ed448", "--enable-cmac",
"--enable-rsapss", "--enable-keygen",
"CPPFLAGS=-DWOLFSSL_CHECK_MEM_ZERO -DWOLF_CRYPTO_CB_FREE -DWOLF_CRYPTO_CB_RSA_PAD"]},
{"name": "opensslall-rng-seed-cb-no-getpid", "minutes": 2.1,
"configure": ["--enable-opensslall", "--enable-opensslextra",
"CPPFLAGS=-DWC_RNG_SEED_CB -DWOLFSSL_NO_GETPID"]},

View File

@ -597,11 +597,16 @@ int wc_RsaPSS_VerifyInline(byte* in, word32 inLen, byte** out,
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.
A crypto callback device that returns recovered data fills out and the
return is that length. A device that reports only a verdict recovers
nothing: out is zeroed and the return is the length the data would have
been, so callers must not read out on that path.
\return MEMORY_E memory exception.
\param in The byte array to be decrypted.
\param inLen The length of in.
\param out Pointer to address containing the PSS data.
\param out Pointer to address containing the PSS data. Zeroed when a
crypto callback device reported only a verdict (see \return).
\param outLen The length of out.
\param digest Hash of the data that is being verified.
\param digestLen Length of hash.
@ -742,13 +747,15 @@ 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.
A crypto callback device that returns recovered data points *out into in and
the return is that length. A device that reports only a verdict recovers
nothing: *out is set to NULL though the return stays positive, so callers
must check *out before dereferencing it.
\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. Set to NULL
when a crypto callback device performed the verify (see \return).
when a crypto callback device reported only a verdict (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

View File

@ -720,7 +720,7 @@ 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
/* Test that wc_CmacFree() sends 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)

View File

@ -2049,8 +2049,8 @@ static int rsa_pss_test_crypto_cb(int devIdArg, wc_CryptoInfo* info, void* ctx)
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. */
/* Only a pass or fail sets res. A real error such as MEMORY_E is
* returned as-is, so it is not mistaken for a bad signature. */
if (v > 0) {
if (info->pk.rsa_pss_verify.res != NULL)
*info->pk.rsa_pss_verify.res = 1;
@ -2080,6 +2080,7 @@ int test_wc_CryptoCb_RsaPssVerify(void)
WC_RNG rng;
byte digest[WC_SHA256_DIGEST_SIZE];
word32 sigLen = 0;
int sigSz = 0;
int r;
WC_DECLARE_VAR(key, RsaKey, 1, HEAP_HINT);
WC_DECLARE_VAR(sig, byte, 512, HEAP_HINT);
@ -2111,9 +2112,12 @@ int test_wc_CryptoCb_RsaPssVerify(void)
ExpectIntEQ(wc_RsaSetRNG(key, &rng), 0);
/* PSS sign runs in software (device declines). */
ExpectIntGT(sigLen = (word32)wc_RsaPSS_Sign(digest,
ExpectIntGT(sigSz = wc_RsaPSS_Sign(digest,
(word32)sizeof(digest), sig, 512, WC_HASH_TYPE_SHA256, WC_MGF1SHA256,
key, &rng), 0);
if (sigSz > 0) {
sigLen = (word32)sigSz;
}
/* Positive: verify routes through the device and succeeds. */
pssVerifySeen = 0;
@ -2123,7 +2127,7 @@ int test_wc_CryptoCb_RsaPssVerify(void)
/* 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)) {
if (EXPECT_SUCCESS() && 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;
@ -2153,3 +2157,222 @@ int test_wc_CryptoCb_RsaPssVerify(void)
#endif
return EXPECT_RESULT();
} /* END test_wc_CryptoCb_RsaPssVerify */
/* Test that a crypto callback device which returns recovered PSS data is
* reported to the caller, and that an over-claimed length is ignored. */
#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)
#define PSS_CB_RECOVER 0
#define PSS_CB_OVERCLAIM 1
typedef struct {
int seen;
int mode;
} rsaPssRecoverCtx;
/* Spy device that verifies in software and, depending on mode, hands the
* recovered block back through out/outLen or over-claims the length. */
static int rsa_pss_recover_crypto_cb(int devIdArg, wc_CryptoInfo* info,
void* ctx)
{
rsaPssRecoverCtx* c = (rsaPssRecoverCtx*)ctx;
(void)devIdArg;
if (info == NULL || c == 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;
}
c->seen++;
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;
if (v > 0) {
if (info->pk.rsa_pss_verify.res != NULL) {
*info->pk.rsa_pss_verify.res = 1;
}
if (c->mode == PSS_CB_RECOVER) {
if ((info->pk.rsa_pss_verify.out != NULL) &&
((word32)v <= info->pk.rsa_pss_verify.outSz)) {
XMEMCPY(info->pk.rsa_pss_verify.out, outbuf, (word32)v);
if (info->pk.rsa_pss_verify.outLen != NULL) {
*info->pk.rsa_pss_verify.outLen = (word32)v;
}
}
}
else {
/* Claim more than the buffer holds; must be ignored. */
if (info->pk.rsa_pss_verify.outLen != NULL) {
*info->pk.rsa_pss_verify.outLen =
info->pk.rsa_pss_verify.outSz + 1;
}
}
XFREE(outbuf, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
return 0;
}
XFREE(outbuf, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
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_RsaPssVerifyRecover(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 = 4471;
rsaPssRecoverCtx cbCtx;
WC_RNG rng;
byte digest[WC_SHA256_DIGEST_SIZE];
word32 sigLen = 0;
int sigSz = 0;
int swRet = 0;
int i;
int allZero;
WC_DECLARE_VAR(key, RsaKey, 1, HEAP_HINT);
WC_DECLARE_VAR(sig, byte, 512, HEAP_HINT);
WC_DECLARE_VAR(rec, byte, 512, HEAP_HINT);
WC_DECLARE_VAR(swRec, byte, 512, HEAP_HINT);
XMEMSET(&rng, 0, sizeof(rng));
XMEMSET(&cbCtx, 0, sizeof(cbCtx));
XMEMSET(digest, 0x3c, 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);
WC_ALLOC_VAR(swRec, byte, 512, HEAP_HINT);
#ifdef WC_DECLARE_VAR_IS_HEAP_ALLOC
ExpectNotNull(key);
ExpectNotNull(sig);
ExpectNotNull(rec);
ExpectNotNull(swRec);
#endif
if (WC_VAR_OK(sig)) {
XMEMSET(sig, 0, 512);
}
if (WC_VAR_OK(rec)) {
XMEMSET(rec, 0, 512);
}
if (WC_VAR_OK(swRec)) {
XMEMSET(swRec, 0, 512);
}
ExpectIntEQ(wc_InitRng(&rng), 0);
ExpectIntEQ(wc_InitRsaKey_ex(key, HEAP_HINT, INVALID_DEVID), 0);
ExpectIntEQ(wc_MakeRsaKey(key, 2048, WC_RSA_EXPONENT, &rng), 0);
ExpectIntEQ(wc_RsaSetRNG(key, &rng), 0);
ExpectIntGT(sigSz = wc_RsaPSS_Sign(digest, (word32)sizeof(digest), sig,
512, WC_HASH_TYPE_SHA256, WC_MGF1SHA256, key, &rng), 0);
if (sigSz > 0) {
sigLen = (word32)sigSz;
}
/* Software baseline: no device registered on the key yet. */
ExpectIntGT(swRet = wc_RsaPSS_VerifyCheck(sig, sigLen, swRec, 512, digest,
(word32)sizeof(digest), WC_HASH_TYPE_SHA256, WC_MGF1SHA256, key), 0);
/* Device that recovers: same return as software, same bytes in out. */
ExpectIntEQ(wc_CryptoCb_RegisterDevice(devId, rsa_pss_recover_crypto_cb,
&cbCtx), 0);
if (EXPECT_SUCCESS()) {
key->devId = devId;
cbCtx.mode = PSS_CB_RECOVER;
cbCtx.seen = 0;
XMEMSET(rec, 0, 512);
ExpectIntEQ(wc_RsaPSS_VerifyCheck(sig, sigLen, rec, 512, digest,
(word32)sizeof(digest), WC_HASH_TYPE_SHA256, WC_MGF1SHA256, key),
swRet);
ExpectIntGE(cbCtx.seen, 1);
ExpectIntEQ(XMEMCMP(rec, swRec, (word32)swRet), 0);
}
/* Device that over-claims the length: treated as verdict only, so out is
* zeroed and the return is still the software length. */
if (EXPECT_SUCCESS()) {
cbCtx.mode = PSS_CB_OVERCLAIM;
cbCtx.seen = 0;
XMEMSET(rec, 0xA5, 512);
ExpectIntEQ(wc_RsaPSS_VerifyCheck(sig, sigLen, rec, 512, digest,
(word32)sizeof(digest), WC_HASH_TYPE_SHA256, WC_MGF1SHA256, key),
swRet);
ExpectIntGE(cbCtx.seen, 1);
allZero = 1;
if (WC_VAR_OK(rec)) {
for (i = 0; i < swRet; i++) {
if (rec[i] != 0) {
allZero = 0;
break;
}
}
}
ExpectIntEQ(allZero, 1);
}
/* Inline variant with a recovering device: *out points into in. */
if (EXPECT_SUCCESS() && WC_VAR_OK(sig) && WC_VAR_OK(rec)) {
byte* inlineOut = NULL;
cbCtx.mode = PSS_CB_RECOVER;
cbCtx.seen = 0;
XMEMCPY(rec, sig, sigLen);
ExpectIntEQ(wc_RsaPSS_VerifyCheckInline(rec, sigLen, &inlineOut, digest,
(word32)sizeof(digest), WC_HASH_TYPE_SHA256, WC_MGF1SHA256, key),
swRet);
ExpectIntGE(cbCtx.seen, 1);
ExpectPtrEq(inlineOut, rec);
ExpectIntEQ(XMEMCMP(rec, swRec, (word32)swRet), 0);
}
if (WC_VAR_OK(key)) {
key->devId = INVALID_DEVID;
}
DoExpectIntEQ(wc_FreeRsaKey(key), 0);
DoExpectIntEQ(wc_FreeRng(&rng), 0);
wc_CryptoCb_UnRegisterDevice(devId);
WC_FREE_VAR(swRec, HEAP_HINT);
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_RsaPssVerifyRecover */

View File

@ -48,6 +48,7 @@ int test_wc_RsaKeyToDer_SizeOverflow(void);
int test_wc_RsaDecisionCoverage(void);
int test_wc_RsaFeatureCoverage(void);
int test_wc_CryptoCb_RsaPssVerify(void);
int test_wc_CryptoCb_RsaPssVerifyRecover(void);
#define TEST_RSA_DECLS \
TEST_DECL_GROUP("rsa", test_wc_InitRsaKey), \
@ -73,6 +74,7 @@ int test_wc_CryptoCb_RsaPssVerify(void);
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_CryptoCb_RsaPssVerify)
TEST_DECL_GROUP("rsa", test_wc_CryptoCb_RsaPssVerify), \
TEST_DECL_GROUP("rsa", test_wc_CryptoCb_RsaPssVerifyRecover)
#endif /* WOLFCRYPT_TEST_RSA_H */

View File

@ -160,9 +160,7 @@ static int _InitCmac_common(Cmac* cmac, const byte* key, word32 keySz,
#ifdef WOLF_CRYPTO_CB
/* Set devId regardless of value (invalid or not) */
cmac->devId = devId;
/* Set type up front so wc_CmacFree can clean up properly when the
* callback handles the init and returns before the software path
* below has a chance to set it. */
/* Set before the cryptocb early return so wc_CmacFree can clean up. */
cmac->type = (CmacType)type;
#ifndef WOLF_CRYPTO_CB_FIND
if (devId != INVALID_DEVID)

View File

@ -637,7 +637,7 @@ int wc_CryptoCb_RsaPad(const byte* in, word32 inLen, byte* out,
* 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* res, byte* out, word32 outSz, word32* outLen)
{
int ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE);
CryptoCb* dev;
@ -662,6 +662,9 @@ int wc_CryptoCb_RsaPssVerify(const byte* sig, word32 sigSz, const byte* digest,
cryptoInfo.pk.rsa_pss_verify.saltLen = saltLen;
cryptoInfo.pk.rsa_pss_verify.key = key;
cryptoInfo.pk.rsa_pss_verify.res = res;
cryptoInfo.pk.rsa_pss_verify.out = out;
cryptoInfo.pk.rsa_pss_verify.outSz = outSz;
cryptoInfo.pk.rsa_pss_verify.outLen = outLen;
ret = dev->cb(dev->devId, &cryptoInfo, dev->ctx);
}

View File

@ -446,20 +446,6 @@ int wc_ed448_sign_msg_ex(const byte* in, word32 inLen, byte* out,
WC_DECLARE_VAR(sha, wc_Shake, 1, key ? key->heap : NULL);
#endif
#ifdef WOLFSSL_CHECK_MEM_ZERO
/* Register the secret nonce/expanded-key buffers up front so that any exit
* path from here to the ForceZero below is checked for proper zeroization.
* XMEMSET gives them a defined value before the hash steps fill them. */
XMEMSET(az, 0, sizeof(az));
XMEMSET(nonce, 0, sizeof(nonce));
wc_MemZero_Add("wc_ed448_sign_msg_ex az", az, sizeof(az));
wc_MemZero_Add("wc_ed448_sign_msg_ex nonce", nonce, sizeof(nonce));
#ifdef WOLFSSL_EDDSA_CHECK_PRIV_ON_SIGN
XMEMSET(orig_k, 0, sizeof(orig_k));
wc_MemZero_Add("wc_ed448_sign_msg_ex orig_k", orig_k, sizeof(orig_k));
#endif
#endif
/* sanity check on arguments */
if ((in == NULL) || (out == NULL) || (outLen == NULL) || (key == NULL) ||
((context == NULL) && (contextLen != 0))) {
@ -478,24 +464,27 @@ int wc_ed448_sign_msg_ex(const byte* in, word32 inLen, byte* out,
{
ret = wc_CryptoCb_Ed448Sign(in, inLen, out, outLen, key, type,
context, contextLen);
if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) {
#ifdef WOLFSSL_CHECK_MEM_ZERO
/* The device signed, so this returns without reaching the
* ForceZero below. Release the registrations made above or
* they outlive the stack frame and trip a later check. */
#ifdef WOLFSSL_EDDSA_CHECK_PRIV_ON_SIGN
wc_MemZero_Check(orig_k, sizeof(orig_k));
#endif
wc_MemZero_Check(nonce, sizeof(nonce));
wc_MemZero_Check(az, sizeof(az));
#endif
if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE))
return ret;
}
ret = 0; /* fall-through when unavailable */
}
}
#endif
#ifdef WOLFSSL_CHECK_MEM_ZERO
/* Register the secret nonce/expanded-key buffers up front so that any exit
* path from here to the ForceZero below is checked for proper zeroization.
* XMEMSET gives them a defined value before the hash steps fill them. */
XMEMSET(az, 0, sizeof(az));
XMEMSET(nonce, 0, sizeof(nonce));
wc_MemZero_Add("wc_ed448_sign_msg_ex az", az, sizeof(az));
wc_MemZero_Add("wc_ed448_sign_msg_ex nonce", nonce, sizeof(nonce));
#ifdef WOLFSSL_EDDSA_CHECK_PRIV_ON_SIGN
XMEMSET(orig_k, 0, sizeof(orig_k));
wc_MemZero_Add("wc_ed448_sign_msg_ex orig_k", orig_k, sizeof(orig_k));
#endif
#endif
if ((ret == 0) && (!key->pubKeySet)) {
ret = BAD_FUNC_ARG;
}

View File

@ -4645,8 +4645,7 @@ int wc_RsaPSS_CheckPadding_ex(const byte* in, word32 inSz, const byte* sig,
* 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.
* Note: a device that recovers nothing sets *out to NULL, so check *out first.
*/
int wc_RsaPSS_VerifyCheckInline(byte* in, word32 inLen, byte** out,
const byte* digest, word32 digestLen,
@ -4691,16 +4690,39 @@ int wc_RsaPSS_VerifyCheckInline(byte* in, word32 inLen, byte** out,
if (key != NULL)
#endif
{
int res = 0;
int res = 0;
word32 recovered = 0;
ret = wc_CryptoCb_RsaPssVerify(in, inLen, digest, digestLen, hash, mgf,
saltLen, key, &res);
saltLen, key, &res, in, inLen,
&recovered);
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;
if (recovered > inLen) {
recovered = 0;
}
if (res == 0) {
ret = SIG_VERIFY_E;
}
else if (recovered > 0) {
if (out != NULL) {
*out = in;
}
ret = (int)recovered;
}
else if (inLen < (word32)(saltLen + hLen)) {
ret = RSA_BUFFER_E;
}
else {
/* Device gave a verdict only; nothing to expose. */
if (out != NULL) {
*out = NULL;
}
ret = saltLen + hLen;
}
}
else if (ret > 0) {
ret = SIG_VERIFY_E;
}
return ret;
}
@ -4777,12 +4799,37 @@ int wc_RsaPSS_VerifyCheck(const byte* in, word32 inLen, byte* out, word32 outLen
if (key != NULL)
#endif
{
int res = 0;
int res = 0;
word32 recovered = 0;
ret = wc_CryptoCb_RsaPssVerify(in, inLen, digest, digestLen, hash, mgf,
saltLen, key, &res);
saltLen, key, &res, out, outLen,
&recovered);
if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) {
if (ret == 0)
ret = (res != 0) ? (int)inLen : SIG_VERIFY_E;
if (ret == 0) {
if (recovered > outLen) {
recovered = 0;
}
if (res == 0) {
ret = SIG_VERIFY_E;
}
else if (recovered > 0) {
ret = (int)recovered;
}
else if (outLen < (word32)(saltLen + hLen)) {
ret = RSA_BUFFER_E;
}
else {
/* Device gave a verdict only; leave no stale data behind. */
if (out != NULL) {
XMEMSET(out, 0, (word32)(saltLen + hLen));
}
ret = saltLen + hLen;
}
}
else if (ret > 0) {
ret = SIG_VERIFY_E;
}
return ret;
}
ret = 0;

View File

@ -78848,7 +78848,8 @@ 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 defined(WC_RSA_PSS) && defined(WOLF_CRYPTO_CB_RSA_PAD) && \
!defined(WOLF_CRYPTO_CB_ONLY_RSA)
if (info->pk.type == WC_PK_TYPE_RSA_PSS_VERIFY) {
RsaKey* pssKey = info->pk.rsa_pss_verify.key;
int pssSaveDevId = pssKey->devId;
@ -78876,8 +78877,8 @@ static int myCryptoDevCb(int devIdArg, wc_CryptoInfo* info, void* ctx)
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. */
/* Only a pass or fail sets res. A real error such as MEMORY_E is
* returned as-is, so it is not mistaken for a bad signature. */
if (pssVer > 0) {
if (info->pk.rsa_pss_verify.res != NULL)
*info->pk.rsa_pss_verify.res = 1;
@ -78891,7 +78892,7 @@ static int myCryptoDevCb(int devIdArg, wc_CryptoInfo* info, void* ctx)
}
return pssVer;
}
#endif /* WC_RSA_PSS && WOLF_CRYPTO_CB_RSA_PAD */
#endif /* WC_RSA_PSS && WOLF_CRYPTO_CB_RSA_PAD && !WOLF_CRYPTO_CB_ONLY_RSA */
#ifndef NO_RSA
if (info->pk.type == WC_PK_TYPE_RSA) {

View File

@ -211,6 +211,9 @@ typedef struct wc_CryptoInfo {
int saltLen;
RsaKey* key;
int* res;
byte* out;
word32 outSz;
word32* outLen;
} rsa_pss_verify;
#endif
#endif
@ -851,7 +854,8 @@ 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);
int saltLen, RsaKey* key, int* res, byte* out, word32 outSz,
word32* outLen);
#endif
#ifdef WOLFSSL_KEY_GEN