mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2026-07-06 13:30:50 +02:00
@@ -16086,11 +16086,18 @@ static int TLSX_EchChangeSNI(WOLFSSL* ssl, TLSX** pEchX,
|
||||
|
||||
if (serverNameX == NULL && ssl->ctx && ssl->ctx->extensions) {
|
||||
serverNameX = TLSX_Find(ssl->ctx->extensions, TLSX_SERVER_NAME);
|
||||
extensions = &ssl->ctx->extensions;
|
||||
if (serverNameX != NULL)
|
||||
extensions = &ssl->ctx->extensions;
|
||||
}
|
||||
|
||||
/* ECH requires an inner SNI to be present for ClientHelloInner.
|
||||
* Without it, fail instead of mutating extension lists. */
|
||||
if (serverNameX == NULL) {
|
||||
ret = BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
/* store the inner server name */
|
||||
if (serverNameX != NULL) {
|
||||
if (ret == 0 && serverNameX != NULL) {
|
||||
char* hostName = ((SNI*)serverNameX->data)->data.host_name;
|
||||
word32 hostNameSz = (word32)XSTRLEN(hostName) + 1;
|
||||
|
||||
@@ -16101,15 +16108,19 @@ static int TLSX_EchChangeSNI(WOLFSSL* ssl, TLSX** pEchX,
|
||||
XMEMCPY(serverName, hostName, hostNameSz);
|
||||
}
|
||||
|
||||
/* remove the inner server name */
|
||||
TLSX_Remove(extensions, TLSX_SERVER_NAME, ssl->heap);
|
||||
/* only swap the SNI if one was found; extensions is non-NULL if an
|
||||
* SNI entry was found on ssl->extensions or ctx->extensions */
|
||||
if (ret == 0 && extensions != NULL) {
|
||||
/* remove the inner server name */
|
||||
TLSX_Remove(extensions, TLSX_SERVER_NAME, ssl->heap);
|
||||
|
||||
/* set the public name as the server name */
|
||||
if ((ret = TLSX_UseSNI(extensions, WOLFSSL_SNI_HOST_NAME,
|
||||
((WOLFSSL_ECH*)echX->data)->echConfig->publicName,
|
||||
XSTRLEN(((WOLFSSL_ECH*)echX->data)->echConfig->publicName),
|
||||
ssl->heap)) == WOLFSSL_SUCCESS)
|
||||
ret = 0;
|
||||
/* set the public name as the server name */
|
||||
if ((ret = TLSX_UseSNI(extensions, WOLFSSL_SNI_HOST_NAME,
|
||||
((WOLFSSL_ECH*)echX->data)->echConfig->publicName,
|
||||
XSTRLEN(((WOLFSSL_ECH*)echX->data)->echConfig->publicName),
|
||||
ssl->heap)) == WOLFSSL_SUCCESS)
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
*pServerNameX = serverNameX;
|
||||
*pExtensions = extensions;
|
||||
@@ -16122,10 +16133,12 @@ static int TLSX_EchRestoreSNI(WOLFSSL* ssl, char* serverName,
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (serverNameX != NULL) {
|
||||
/* remove the public name SNI */
|
||||
/* always remove the publicName SNI we injected, regardless of whether
|
||||
* there was a prior inner SNI to restore */
|
||||
if (extensions != NULL)
|
||||
TLSX_Remove(extensions, TLSX_SERVER_NAME, ssl->heap);
|
||||
|
||||
if (serverNameX != NULL) {
|
||||
/* restore the inner server name */
|
||||
ret = TLSX_UseSNI(extensions, WOLFSSL_SNI_HOST_NAME,
|
||||
serverName, XSTRLEN(serverName), ssl->heap);
|
||||
|
||||
+10
-1
@@ -318,6 +318,11 @@ static void SetupStoreCtxError_ex(WOLFSSL_X509_STORE_CTX* ctx, int ret,
|
||||
{
|
||||
int error = GetX509Error(ret);
|
||||
|
||||
/* Do not overwrite a previously recorded error with success; preserve
|
||||
* the worst-seen error across the chain walk. */
|
||||
if (error == 0 && ctx->error != 0)
|
||||
return;
|
||||
|
||||
wolfSSL_X509_STORE_CTX_set_error(ctx, error);
|
||||
wolfSSL_X509_STORE_CTX_set_error_depth(ctx, depth);
|
||||
}
|
||||
@@ -635,9 +640,14 @@ int wolfSSL_X509_verify_cert(WOLFSSL_X509_STORE_CTX* ctx)
|
||||
if (ctx->store->verify_cb) {
|
||||
ret = ctx->store->verify_cb(0, ctx);
|
||||
if (ret != WOLFSSL_SUCCESS) {
|
||||
ret = WOLFSSL_FAILURE;
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
else {
|
||||
ret = WOLFSSL_FAILURE;
|
||||
goto exit;
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
@@ -2174,4 +2184,3 @@ int wolfSSL_X509_STORE_set1_param(WOLFSSL_X509_STORE *ctx,
|
||||
#endif /* !WOLFCRYPT_ONLY */
|
||||
|
||||
#endif /* !WOLFSSL_X509_STORE_INCLUDED */
|
||||
|
||||
|
||||
@@ -1915,6 +1915,7 @@ int test_wolfssl_EVP_chacha20_poly1305(void)
|
||||
byte cipherText[sizeof(plainText)];
|
||||
byte decryptedText[sizeof(plainText)];
|
||||
byte tag[CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE];
|
||||
byte badTag[CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE];
|
||||
EVP_CIPHER_CTX* ctx = NULL;
|
||||
int outSz;
|
||||
|
||||
@@ -1979,6 +1980,28 @@ int test_wolfssl_EVP_chacha20_poly1305(void)
|
||||
EVP_CIPHER_CTX_free(ctx);
|
||||
ctx = NULL;
|
||||
|
||||
/* Negative test: forged (all-zero) tag must be rejected. */
|
||||
XMEMSET(badTag, 0, sizeof(badTag));
|
||||
ExpectNotNull((ctx = EVP_CIPHER_CTX_new()));
|
||||
ExpectIntEQ(EVP_DecryptInit_ex(ctx, EVP_chacha20_poly1305(), NULL,
|
||||
NULL, NULL), WOLFSSL_SUCCESS);
|
||||
ExpectIntEQ(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN,
|
||||
CHACHA20_POLY1305_AEAD_IV_SIZE, NULL), WOLFSSL_SUCCESS);
|
||||
ExpectIntEQ(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG,
|
||||
CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE, badTag),
|
||||
WOLFSSL_SUCCESS);
|
||||
ExpectIntEQ(EVP_DecryptInit_ex(ctx, NULL, NULL, key, iv),
|
||||
WOLFSSL_SUCCESS);
|
||||
ExpectIntEQ(EVP_DecryptUpdate(ctx, NULL, &outSz, aad, sizeof(aad)),
|
||||
WOLFSSL_SUCCESS);
|
||||
ExpectIntEQ(EVP_DecryptUpdate(ctx, decryptedText, &outSz, cipherText,
|
||||
sizeof(cipherText)), WOLFSSL_SUCCESS);
|
||||
/* EVP_DecryptFinal_ex MUST return failure on tag mismatch */
|
||||
ExpectIntNE(EVP_DecryptFinal_ex(ctx, decryptedText, &outSz),
|
||||
WOLFSSL_SUCCESS);
|
||||
EVP_CIPHER_CTX_free(ctx);
|
||||
ctx = NULL;
|
||||
|
||||
/* Test partial Inits. CipherInit() allow setting of key and iv
|
||||
* in separate calls. */
|
||||
ExpectNotNull((ctx = EVP_CIPHER_CTX_new()));
|
||||
|
||||
@@ -1074,6 +1074,56 @@ int test_X509_STORE_InvalidCa(void)
|
||||
ExpectIntEQ(X509_STORE_CTX_init(ctx, str, cert, untrusted), 1);
|
||||
ExpectIntEQ(X509_verify_cert(ctx), 1);
|
||||
ExpectIntEQ(last_errcode, X509_V_ERR_INVALID_CA);
|
||||
/* Defense in depth: ctx->error must not be clobbered back to X509_V_OK
|
||||
* by the later successful verification of the intermediate against the
|
||||
* trusted root. The worst-seen error must persist. */
|
||||
ExpectIntEQ(X509_STORE_CTX_get_error(ctx), X509_V_ERR_INVALID_CA);
|
||||
|
||||
X509_free(cert);
|
||||
X509_STORE_free(str);
|
||||
X509_STORE_CTX_free(ctx);
|
||||
sk_X509_pop_free(untrusted, NULL);
|
||||
#endif
|
||||
return EXPECT_RESULT();
|
||||
}
|
||||
|
||||
int test_X509_STORE_InvalidCa_NoCallback(void)
|
||||
{
|
||||
EXPECT_DECLS;
|
||||
#if defined(OPENSSL_ALL) && !defined(NO_RSA) && !defined(NO_FILESYSTEM)
|
||||
const char* filename = "./certs/intermediate/ca_false_intermediate/"
|
||||
"test_int_not_cacert.pem";
|
||||
const char* srvfile = "./certs/intermediate/ca_false_intermediate/"
|
||||
"test_sign_bynoca_srv.pem";
|
||||
X509_STORE_CTX* ctx = NULL;
|
||||
X509_STORE* str = NULL;
|
||||
XFILE fp = XBADFILE;
|
||||
X509* cert = NULL;
|
||||
STACK_OF(X509)* untrusted = NULL;
|
||||
|
||||
ExpectTrue((fp = XFOPEN(srvfile, "rb"))
|
||||
!= XBADFILE);
|
||||
ExpectNotNull(cert = PEM_read_X509(fp, 0, 0, 0 ));
|
||||
if (fp != XBADFILE) {
|
||||
XFCLOSE(fp);
|
||||
fp = XBADFILE;
|
||||
}
|
||||
|
||||
ExpectNotNull(str = X509_STORE_new());
|
||||
ExpectNotNull(ctx = X509_STORE_CTX_new());
|
||||
ExpectNotNull(untrusted = sk_X509_new_null());
|
||||
|
||||
/* Create cert chain stack with an intermediate that is CA:FALSE. */
|
||||
ExpectIntEQ(test_X509_STORE_untrusted_load_cert_to_stack(filename,
|
||||
untrusted), TEST_SUCCESS);
|
||||
|
||||
ExpectIntEQ(X509_STORE_load_locations(str,
|
||||
"./certs/intermediate/ca_false_intermediate/test_ca.pem",
|
||||
NULL), 1);
|
||||
ExpectIntEQ(X509_STORE_CTX_init(ctx, str, cert, untrusted), 1);
|
||||
/* No verify callback: verification must fail on CA:FALSE issuer. */
|
||||
ExpectIntNE(X509_verify_cert(ctx), 1);
|
||||
ExpectIntEQ(X509_STORE_CTX_get_error(ctx), X509_V_ERR_INVALID_CA);
|
||||
|
||||
X509_free(cert);
|
||||
X509_STORE_free(str);
|
||||
@@ -1793,4 +1843,3 @@ int test_X509_STORE_No_SSL_CTX(void)
|
||||
#endif
|
||||
return EXPECT_RESULT();
|
||||
}
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@ int test_wolfSSL_X509_STORE_CTX(void);
|
||||
int test_wolfSSL_X509_STORE_CTX_ex(void);
|
||||
int test_X509_STORE_untrusted(void);
|
||||
int test_X509_STORE_InvalidCa(void);
|
||||
int test_X509_STORE_InvalidCa_NoCallback(void);
|
||||
int test_wolfSSL_X509_STORE_CTX_trusted_stack_cleanup(void);
|
||||
int test_wolfSSL_X509_STORE_CTX_get_issuer(void);
|
||||
int test_wolfSSL_X509_STORE_set_flags(void);
|
||||
@@ -51,6 +52,7 @@ int test_X509_STORE_No_SSL_CTX(void);
|
||||
TEST_DECL_GROUP("ossl_x509_store", test_wolfSSL_X509_STORE_CTX_ex), \
|
||||
TEST_DECL_GROUP("ossl_x509_store", test_X509_STORE_untrusted), \
|
||||
TEST_DECL_GROUP("ossl_x509_store", test_X509_STORE_InvalidCa), \
|
||||
TEST_DECL_GROUP("ossl_x509_store", test_X509_STORE_InvalidCa_NoCallback), \
|
||||
TEST_DECL_GROUP("ossl_x509_store", \
|
||||
test_wolfSSL_X509_STORE_CTX_trusted_stack_cleanup), \
|
||||
TEST_DECL_GROUP("ossl_x509_store", \
|
||||
|
||||
+7
-8
@@ -10217,8 +10217,9 @@ int wc_AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz,
|
||||
/* If the sz is non-zero, both in and out must be set. If sz is 0,
|
||||
* in and out are don't cares, as this is is the GMAC case. */
|
||||
if (aes == NULL || iv == NULL || (sz != 0 && (in == NULL || out == NULL)) ||
|
||||
authTag == NULL || authTagSz > WC_AES_BLOCK_SIZE || authTagSz == 0 ||
|
||||
ivSz == 0 || ((authInSz > 0) && (authIn == NULL)))
|
||||
authTag == NULL || authTagSz > WC_AES_BLOCK_SIZE ||
|
||||
authTagSz < WOLFSSL_MIN_AUTH_TAG_SZ || ivSz == 0 ||
|
||||
((authInSz > 0) && (authIn == NULL)))
|
||||
{
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
@@ -10781,8 +10782,8 @@ int wc_AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz,
|
||||
/* If the sz is non-zero, both in and out must be set. If sz is 0,
|
||||
* in and out are don't cares, as this is is the GMAC case. */
|
||||
if (aes == NULL || iv == NULL || (sz != 0 && (in == NULL || out == NULL)) ||
|
||||
authTag == NULL || authTagSz > WC_AES_BLOCK_SIZE || authTagSz == 0 ||
|
||||
ivSz == 0) {
|
||||
authTag == NULL || authTagSz > WC_AES_BLOCK_SIZE ||
|
||||
authTagSz < WOLFSSL_MIN_AUTH_TAG_SZ || ivSz == 0) {
|
||||
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
@@ -12473,7 +12474,7 @@ int wc_AesGcmEncryptFinal(Aes* aes, byte* authTag, word32 authTagSz)
|
||||
|
||||
/* Check validity of parameters. */
|
||||
if ((aes == NULL) || (authTag == NULL) || (authTagSz > WC_AES_BLOCK_SIZE) ||
|
||||
(authTagSz == 0)) {
|
||||
(authTagSz < WOLFSSL_MIN_AUTH_TAG_SZ)) {
|
||||
ret = BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
@@ -16377,9 +16378,7 @@ int wc_local_CmacUpdateAes(struct Cmac *cmac, const byte* in, word32 inSz) {
|
||||
in += add;
|
||||
|
||||
if (cmac->bufferSz == WC_AES_BLOCK_SIZE && inSz != 0) {
|
||||
if (cmac->totalSz != 0) {
|
||||
xorbuf(cmac->buffer, cmac->digest, WC_AES_BLOCK_SIZE);
|
||||
}
|
||||
xorbuf(cmac->buffer, cmac->digest, WC_AES_BLOCK_SIZE);
|
||||
ret = AesEncrypt_preFetchOpt(aes, cmac->buffer,
|
||||
cmac->digest, &did_prefetches);
|
||||
if (ret == 0) {
|
||||
|
||||
@@ -238,9 +238,7 @@ int wc_CmacUpdate(Cmac* cmac, const byte* in, word32 inSz)
|
||||
inSz -= add;
|
||||
|
||||
if (cmac->bufferSz == WC_AES_BLOCK_SIZE && inSz != 0) {
|
||||
if (cmac->totalSz != 0) {
|
||||
xorbuf(cmac->buffer, cmac->digest, WC_AES_BLOCK_SIZE);
|
||||
}
|
||||
xorbuf(cmac->buffer, cmac->digest, WC_AES_BLOCK_SIZE);
|
||||
wc_AesEncryptDirect(&cmac->aes, cmac->digest,
|
||||
cmac->buffer);
|
||||
cmac->totalSz += WC_AES_BLOCK_SIZE;
|
||||
|
||||
@@ -2159,6 +2159,18 @@ static int eccsi_calc_j(EccsiKey* key, const mp_int* hem, const byte* sig,
|
||||
if (err == 0) {
|
||||
err = eccsi_decode_sig_s(key, sig, sigSz, s);
|
||||
}
|
||||
/* Validate s is in [1, q-1]: reject zero or out-of-range second signature
|
||||
* component. With s=0, [s](...) yields the point at infinity whose
|
||||
* affine x-coordinate is 0, making the final mp_cmp(0,0) accept any
|
||||
* forged signature. */
|
||||
if (err == 0) {
|
||||
if (mp_iszero(s)) {
|
||||
err = MP_ZERO_E;
|
||||
}
|
||||
else if (mp_cmp(s, &key->params.order) != MP_LT) {
|
||||
err = ECC_OUT_OF_RANGE_E;
|
||||
}
|
||||
}
|
||||
/* [s]( [HE]G + [r]Y ) */
|
||||
if (err == 0) {
|
||||
err = eccsi_mulmod_point(key, s, j, j, 1);
|
||||
@@ -2238,6 +2250,19 @@ int wc_VerifyEccsiHash(EccsiKey* key, enum wc_HashType hashType,
|
||||
err = mp_montgomery_setup(¶ms->prime, &mp);
|
||||
}
|
||||
|
||||
/* Validate r is in [1, q-1]: reject zero or out-of-range first signature
|
||||
* component before any scalar multiplication takes place.
|
||||
* Without this check, r=0 causes J_x=0 and the final mp_cmp(0,0)==MP_EQ
|
||||
* comparison accepts the forged signature unconditionally. */
|
||||
if (err == 0) {
|
||||
if (mp_iszero(r)) {
|
||||
err = MP_ZERO_E;
|
||||
}
|
||||
else if (mp_cmp(r, ¶ms->order) != MP_LT) {
|
||||
err = ECC_OUT_OF_RANGE_E;
|
||||
}
|
||||
}
|
||||
|
||||
/* Step 1: Validate PVT is on curve */
|
||||
if (err == 0) {
|
||||
err = wc_ecc_is_point(pvt, ¶ms->a, ¶ms->b, ¶ms->prime);
|
||||
@@ -2273,6 +2298,16 @@ int wc_VerifyEccsiHash(EccsiKey* key, enum wc_HashType hashType,
|
||||
key->params.haveBase = 0;
|
||||
}
|
||||
|
||||
/* Defense-in-depth: reject J = point at infinity before the final
|
||||
* comparison. Catches any future path that might reach this point
|
||||
* with a neutral-element result (e.g. s = 0 mod q for a non-zero
|
||||
* encoded s). */
|
||||
if (err == 0) {
|
||||
if (wc_ecc_point_is_at_infinity(j)) {
|
||||
err = ECC_INF_E;
|
||||
}
|
||||
}
|
||||
|
||||
/* Step 6: Jx fitting, compare with r */
|
||||
if (err == 0) {
|
||||
jx = &key->tmp;
|
||||
|
||||
+36
-5
@@ -1505,16 +1505,33 @@ int wolfSSL_EVP_CipherFinal(WOLFSSL_EVP_CIPHER_CTX *ctx, unsigned char *out,
|
||||
* HAVE_FIPS_VERSION >= 2 */
|
||||
#if defined(HAVE_CHACHA) && defined(HAVE_POLY1305)
|
||||
case WC_CHACHA20_POLY1305_TYPE:
|
||||
{
|
||||
byte computedTag[CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE];
|
||||
if (!ctx->enc) {
|
||||
/* Save the expected tag before _Final() overwrites
|
||||
* ctx->authTag */
|
||||
XMEMCPY(computedTag, ctx->authTag, sizeof(computedTag));
|
||||
}
|
||||
if (wc_ChaCha20Poly1305_Final(&ctx->cipher.chachaPoly,
|
||||
ctx->authTag) != 0) {
|
||||
WOLFSSL_MSG("wc_ChaCha20Poly1305_Final failed");
|
||||
return WOLFSSL_FAILURE;
|
||||
}
|
||||
else {
|
||||
*outl = 0;
|
||||
return WOLFSSL_SUCCESS;
|
||||
if (!ctx->enc) {
|
||||
/* ctx->authTag now holds computed tag; computedTag holds
|
||||
* expected */
|
||||
int tagErr = wc_ChaCha20Poly1305_CheckTag(computedTag,
|
||||
ctx->authTag);
|
||||
ForceZero(computedTag, sizeof(computedTag));
|
||||
if (tagErr != 0) {
|
||||
WOLFSSL_MSG("ChaCha20-Poly1305 tag mismatch");
|
||||
return WOLFSSL_FAILURE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
*outl = 0;
|
||||
return WOLFSSL_SUCCESS;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
#ifdef WOLFSSL_SM4_GCM
|
||||
case WC_SM4_GCM_TYPE:
|
||||
@@ -3704,6 +3721,10 @@ int wolfSSL_EVP_PKEY_keygen_init(WOLFSSL_EVP_PKEY_CTX *ctx)
|
||||
return WOLFSSL_SUCCESS;
|
||||
}
|
||||
|
||||
#ifdef HAVE_ECC
|
||||
static int ECC_populate_EVP_PKEY(WOLFSSL_EVP_PKEY* pkey, WOLFSSL_EC_KEY *key);
|
||||
#endif
|
||||
|
||||
int wolfSSL_EVP_PKEY_keygen(WOLFSSL_EVP_PKEY_CTX *ctx,
|
||||
WOLFSSL_EVP_PKEY **ppkey)
|
||||
{
|
||||
@@ -3758,6 +3779,8 @@ int wolfSSL_EVP_PKEY_keygen(WOLFSSL_EVP_PKEY_CTX *ctx,
|
||||
ret = wolfSSL_EC_KEY_generate_key(pkey->ecc);
|
||||
if (ret == WOLFSSL_SUCCESS) {
|
||||
pkey->ownEcc = 1;
|
||||
if (ECC_populate_EVP_PKEY(pkey, pkey->ecc) != WOLFSSL_SUCCESS)
|
||||
ret = WOLFSSL_FAILURE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -9516,7 +9539,15 @@ static int ECC_populate_EVP_PKEY(WOLFSSL_EVP_PKEY* pkey, WOLFSSL_EC_KEY *key)
|
||||
else
|
||||
#endif /* HAVE_PKCS8 */
|
||||
{
|
||||
if (ecc->type == ECC_PRIVATEKEY_ONLY) {
|
||||
if (ecc->type == ECC_PRIVATEKEY_ONLY ||
|
||||
(ecc->type == ECC_PRIVATEKEY &&
|
||||
mp_iszero(ecc->pubkey.x))) {
|
||||
/* Reconstruct public key from private scalar. This covers
|
||||
* both ECC_PRIVATEKEY_ONLY keys and ECC_PRIVATEKEY keys whose
|
||||
* public-key point was never populated (e.g. when only
|
||||
* EC_KEY_set_private_key was called, SetECKeyInternal copies
|
||||
* the zero-initialized pub_key point and marks the type as
|
||||
* ECC_PRIVATEKEY, leaving pubkey.x == 0). */
|
||||
if (wc_ecc_make_pub(ecc, NULL) != MP_OKAY) {
|
||||
return WOLFSSL_FAILURE;
|
||||
}
|
||||
|
||||
+19
-1
@@ -140,6 +140,7 @@ struct PKCS7State {
|
||||
word32 nonceSz; /* size of nonce stored */
|
||||
word32 aadSz; /* size of additional AEAD data */
|
||||
word32 tagSz; /* size of tag for AEAD */
|
||||
word32 icvSz; /* expected ICV/MAC size from AlgoID parameter */
|
||||
word32 contentSz;
|
||||
word32 currContIdx; /* index of current content */
|
||||
word32 currContSz; /* size of current content */
|
||||
@@ -14241,6 +14242,10 @@ int wc_PKCS7_DecodeAuthEnvelopedData(wc_PKCS7* pkcs7, byte* in,
|
||||
if (ret == 0 && GetMyVersion(pkiMsg, &idx, &macSz, pkiMsgSz) < 0) {
|
||||
ret = ASN_PARSE_E;
|
||||
}
|
||||
if (ret == 0 && (macSz <= 0 || macSz > WC_AES_BLOCK_SIZE)) {
|
||||
WOLFSSL_MSG("AuthEnvelopedData invalid MAC length");
|
||||
ret = ASN_PARSE_E;
|
||||
}
|
||||
|
||||
if (ret == 0) {
|
||||
explicitOctet = 0;
|
||||
@@ -14286,7 +14291,8 @@ int wc_PKCS7_DecodeAuthEnvelopedData(wc_PKCS7* pkcs7, byte* in,
|
||||
break;
|
||||
}
|
||||
|
||||
/* store nonce for later */
|
||||
/* store nonce and macSz for later */
|
||||
pkcs7->stream->icvSz = (word32)macSz;
|
||||
if (nonceSz > 0) {
|
||||
pkcs7->stream->nonceSz = (word32)nonceSz;
|
||||
pkcs7->stream->nonce = (byte*)XMALLOC((word32)nonceSz,
|
||||
@@ -14477,6 +14483,7 @@ authenv_atrbend:
|
||||
encodedAttribSz = pkcs7->stream->aadSz;
|
||||
encodedAttribs = pkcs7->stream->aad;
|
||||
}
|
||||
macSz = (int)pkcs7->stream->icvSz;
|
||||
#endif
|
||||
|
||||
|
||||
@@ -14493,6 +14500,17 @@ authenv_atrbend:
|
||||
ret = ASN_PARSE_E;
|
||||
}
|
||||
authTagSz = (word32)length;
|
||||
if (ret == 0 && authTagSz != (word32)macSz) {
|
||||
WOLFSSL_MSG("AuthEnvelopedData authTag size mismatch");
|
||||
ret = ASN_PARSE_E;
|
||||
}
|
||||
if (ret == 0 &&
|
||||
(encOID == AES128GCMb || encOID == AES192GCMb ||
|
||||
encOID == AES256GCMb) &&
|
||||
authTagSz < WOLFSSL_MIN_AUTH_TAG_SZ) {
|
||||
WOLFSSL_MSG("AuthEnvelopedData GCM authTag too small");
|
||||
ret = ASN_PARSE_E;
|
||||
}
|
||||
|
||||
#ifndef NO_PKCS7_STREAM
|
||||
/* there might not be enough data for the auth tag too */
|
||||
|
||||
@@ -57846,6 +57846,9 @@ static wc_test_ret_t pkcs7authenveloped_run_vectors(byte* rsaCert, word32 rsaCer
|
||||
wc_test_ret_t ret = 0;
|
||||
int testSz = 0, i;
|
||||
int envelopedSz, decodedSz;
|
||||
#ifdef HAVE_AESGCM
|
||||
int tagTruncationChecked = 0;
|
||||
#endif
|
||||
|
||||
byte *enveloped = NULL;
|
||||
byte *decoded = NULL;
|
||||
@@ -58357,6 +58360,45 @@ static wc_test_ret_t pkcs7authenveloped_run_vectors(byte* rsaCert, word32 rsaCer
|
||||
ERROR_OUT(WC_TEST_RET_ENC_NC, out);
|
||||
}
|
||||
|
||||
#ifdef HAVE_AESGCM
|
||||
if (tagTruncationChecked == 0 &&
|
||||
(testVectors[i].encryptOID == AES128GCMb ||
|
||||
testVectors[i].encryptOID == AES192GCMb ||
|
||||
testVectors[i].encryptOID == AES256GCMb) &&
|
||||
testVectors[i].authAttribsSz == 0 &&
|
||||
testVectors[i].unauthAttribsSz == 0 &&
|
||||
envelopedSz > (WC_AES_BLOCK_SIZE + 2)) {
|
||||
int macIdx = envelopedSz - (WC_AES_BLOCK_SIZE + 2);
|
||||
byte* tampered = NULL;
|
||||
|
||||
/* For plain DER output without unauthenticated attributes, the
|
||||
* MAC OCTET STRING is the final field. */
|
||||
if (enveloped[macIdx] == ASN_OCTET_STRING &&
|
||||
enveloped[macIdx + 1] == WC_AES_BLOCK_SIZE) {
|
||||
tampered = (byte*)XMALLOC((word32)envelopedSz, HEAP_HINT,
|
||||
DYNAMIC_TYPE_TMP_BUFFER);
|
||||
if (tampered == NULL) {
|
||||
wc_PKCS7_Free(pkcs7);
|
||||
ERROR_OUT(WC_TEST_RET_ENC_ERRNO, out);
|
||||
}
|
||||
XMEMCPY(tampered, enveloped, (word32)envelopedSz);
|
||||
tampered[macIdx + 1] = 1;
|
||||
|
||||
decodedSz = wc_PKCS7_DecodeAuthEnvelopedData(pkcs7, tampered,
|
||||
(word32)envelopedSz, decoded, PKCS7_BUF_SIZE);
|
||||
|
||||
XFREE(tampered, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
tampered = NULL;
|
||||
|
||||
if (decodedSz > 0) {
|
||||
wc_PKCS7_Free(pkcs7);
|
||||
ERROR_OUT(WC_TEST_RET_ENC_NC, out);
|
||||
}
|
||||
tagTruncationChecked = 1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef PKCS7_OUTPUT_TEST_BUNDLES
|
||||
/* output pkcs7 envelopedData for external testing */
|
||||
pkcs7File = XFOPEN(testVectors[i].outFileName, "wb");
|
||||
|
||||
@@ -3452,6 +3452,8 @@ extern void uITRON4_free(void *p) ;
|
||||
/* Default AES minimum auth tag sz, allow user to override */
|
||||
#ifndef WOLFSSL_MIN_AUTH_TAG_SZ
|
||||
#define WOLFSSL_MIN_AUTH_TAG_SZ 12
|
||||
#elif WOLFSSL_MIN_AUTH_TAG_SZ < 1
|
||||
#error WOLFSSL_MIN_AUTH_TAG_SZ must be at least 1
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user