mirror of https://github.com/wolfSSL/wolfssl.git
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
parent
33e03a5ce4
commit
375febc944
|
|
@ -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"]},
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in New Issue