Skip to content
Open
1 change: 1 addition & 0 deletions .wolfssl_known_macro_extras
Original file line number Diff line number Diff line change
Expand Up @@ -651,6 +651,7 @@ WC_ASYNC_NO_SHA384
WC_ASYNC_NO_SHA512
WC_ASYNC_NO_X25519
WC_ASYNC_THREAD_BIND
WC_BLINDING_NO_RNG_ACKNOWLEDGE_WEAKNESS
WC_CACHE_RESISTANT_BASE64_TABLE
WC_DILITHIUM_FIXED_ARRAY
WC_DISABLE_RADIX_ZERO_PAD
Expand Down
27 changes: 17 additions & 10 deletions doc/dox_comments/header_files/cmac.h
Original file line number Diff line number Diff line change
Expand Up @@ -174,8 +174,11 @@ int wc_AesCmacGenerate(byte* out, word32* outSz,
\ingroup CMAC
\brief Single shot function for validating a CMAC
\return 0 on success
\param check CMAC value to verify
\param checkSz size of check buffer
\return BAD_FUNC_ARG if parameters are invalid
\return MAC_CMP_FAILED_E if the supplied tag does not match
\param check Expected MAC value to verify
\param checkSz size of expected MAC value; must be in
[\c WC_CMAC_TAG_MIN_SZ, \c WC_AES_BLOCK_SIZE]
\param in input data to process
\param inSz size of input data
\param key key pointer
Expand Down Expand Up @@ -211,10 +214,8 @@ int wc_CMAC_Grow(Cmac* cmac, const byte* in, int inSz);
\ingroup CMAC
\brief Single shot AES-CMAC generation with extended parameters
including heap and device ID.

\return 0 on success
\return BAD_FUNC_ARG if parameters are invalid

\param cmac Pointer to Cmac structure (can be NULL for one-shot)
\param out Buffer to store MAC output
\param outSz Pointer to output size (in/out)
Expand Down Expand Up @@ -249,14 +250,13 @@ int wc_AesCmacGenerate_ex(Cmac *cmac, byte* out, word32* outSz,
\ingroup CMAC
\brief Single shot AES-CMAC verification with extended parameters
including heap and device ID.

\return 0 on success
\return BAD_FUNC_ARG if parameters are invalid
\return MAC_CMP_FAILED_E if MAC verification fails

\param cmac Pointer to Cmac structure (can be NULL for one-shot)
\param cmac Pointer to Cmac structure
\param check Expected MAC value to verify
\param checkSz Size of expected MAC
\param checkSz Size of expected MAC; must be in
[\c WC_CMAC_TAG_MIN_SZ, \c WC_AES_BLOCK_SIZE]
\param in Input data to authenticate
\param inSz Length of input data
\param key AES key
Expand All @@ -267,17 +267,24 @@ int wc_AesCmacGenerate_ex(Cmac *cmac, byte* out, word32* outSz,

_Example_
\code
byte mac[AES_BLOCK_SIZE];
Cmac cmac;
Comment thread
kareem-wolfssl marked this conversation as resolved.
byte mac[WC_AES_BLOCK_SIZE];
byte key[16], msg[64];
int ret;

int ret = wc_AesCmacVerify_ex(NULL, mac, sizeof(mac), msg,
ret = wc_InitCmac_ex(&cmac, key, sizeof(key), WC_CMAC_AES, NULL,
NULL, INVALID_DEVID);
if (ret == 0) {
ret = wc_AesCmacVerify_ex(&cmac, mac, sizeof(mac), msg,
sizeof(msg), key, sizeof(key),
NULL, INVALID_DEVID);
}
if (ret == MAC_CMP_FAILED_E) {
// MAC verification failed
}
\endcode

\sa wc_InitCmac_ex
\sa wc_AesCmacVerify
\sa wc_AesCmacGenerate_ex
*/
Expand Down
5 changes: 4 additions & 1 deletion src/tls13.c
Original file line number Diff line number Diff line change
Expand Up @@ -6156,7 +6156,10 @@ static int DoTls13CertificateRequest(WOLFSSL* ssl, const byte* input,
ssl->options.sendVerify = SEND_BLANK_CERT;
#else
WOLFSSL_MSG("Certificate required but none set on client");
SendAlert(ssl, alert_fatal, illegal_parameter);
/* RFC 8446 Section 4.4.2.4: send certificate_required when a
* peer (here, the client) cannot provide a certificate that the
* other peer required. */
SendAlert(ssl, alert_fatal, certificate_required);
WOLFSSL_ERROR_VERBOSE(NO_CERT_ERROR);
return NO_CERT_ERROR;
#endif
Expand Down
43 changes: 43 additions & 0 deletions tests/api/test_cmac.c
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,49 @@ int test_wc_AesCmacGenerate(void)
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
ExpectIntEQ(wc_AesCmacVerify(mac, macSz, NULL, msgSz, key, keySz),
WC_NO_ERR_TRACE(BAD_FUNC_ARG));

#if !defined(HAVE_FIPS)
ExpectIntEQ(wc_AesCmacVerify(mac, 1, msg, msgSz, key, keySz),
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
ExpectIntEQ(wc_AesCmacVerify(mac, WC_CMAC_TAG_MIN_SZ - 1, msg, msgSz,
key, keySz), WC_NO_ERR_TRACE(BAD_FUNC_ARG));
ExpectIntEQ(wc_AesCmacVerify(mac, WC_AES_BLOCK_SIZE + 1, msg, msgSz,
key, keySz), WC_NO_ERR_TRACE(BAD_FUNC_ARG));

/* Truncated tags within the supported range must verify correctly when
* the generator was asked to produce the same length */
{
byte truncMac[WC_AES_BLOCK_SIZE];
word32 truncSz;
word32 lengths[] = { WC_CMAC_TAG_MIN_SZ, 8, WC_AES_BLOCK_SIZE - 1 };
word32 lengthsSz = (word32)(sizeof(lengths)/sizeof(lengths[0]));
word32 li;
Comment thread
kareem-wolfssl marked this conversation as resolved.
for (li = 0; li < lengthsSz; li++) {
XMEMSET(truncMac, 0, sizeof(truncMac));
truncSz = lengths[li];
ExpectIntEQ(wc_AesCmacGenerate(truncMac, &truncSz, msg, msgSz,
key, keySz), 0);
ExpectIntEQ(truncSz, lengths[li]);
ExpectIntEQ(wc_AesCmacVerify(truncMac, truncSz, msg, msgSz,
key, keySz), 0);
/* Flipping a bit in the truncated tag must yield
* MAC_CMP_FAILED_E, not silent success from comparing a too
* short prefix. */
truncMac[0] ^= 0x01;
ExpectIntEQ(wc_AesCmacVerify(truncMac, truncSz, msg, msgSz,
key, keySz), WC_NO_ERR_TRACE(MAC_CMP_FAILED_E));
}
}

/* A full-length tag that does not match must return MAC_CMP_FAILED_E. */
{
byte badMac[WC_AES_BLOCK_SIZE];
XMEMCPY(badMac, mac, WC_AES_BLOCK_SIZE);
badMac[0] ^= 0x01;
ExpectIntEQ(wc_AesCmacVerify(badMac, WC_AES_BLOCK_SIZE, msg, msgSz,
key, keySz), WC_NO_ERR_TRACE(MAC_CMP_FAILED_E));
}
#endif
#endif
return EXPECT_RESULT();

Expand Down
23 changes: 16 additions & 7 deletions wolfcrypt/src/cmac.c
Original file line number Diff line number Diff line change
Expand Up @@ -574,24 +574,32 @@ int wc_AesCmacVerify_ex(Cmac* cmac,
{
int ret = 0;
byte a[WC_AES_BLOCK_SIZE];
word32 aSz = sizeof(a);
word32 aSz;
int compareRet;

if (cmac == NULL || check == NULL || checkSz == 0 ||
(in == NULL && inSz != 0)) {
if (cmac == NULL || check == NULL || checkSz < WC_CMAC_TAG_MIN_SZ ||
checkSz > WC_AES_BLOCK_SIZE || (in == NULL && inSz != 0)) {
return BAD_FUNC_ARG;
}

XMEMSET(a, 0, aSz);
aSz = checkSz;
XMEMSET(a, 0, sizeof(a));
ret = wc_AesCmacGenerate_ex(cmac,
a, &aSz,
in, inSz,
key, keySz,
heap,
devId);
/* aSz is passed by reference to wc_AesCmacGenerate_ex, which on the
* WOLF_CRYPTO_CB path forwards it to a user-supplied callback that may
* write back any value. Reject anything that does not match the user
* provided length. */
if (ret == 0 && aSz != checkSz) {
ret = BAD_STATE_E;
}
if (ret == 0) {
compareRet = ConstantCompare(check, a, (int)min(checkSz, aSz));
ret = compareRet ? 1 : 0;
compareRet = ConstantCompare(check, a, (int)aSz);
ret = compareRet ? MAC_CMP_FAILED_E : 0;
}

return ret;
Expand All @@ -605,7 +613,8 @@ int wc_AesCmacVerify(const byte* check, word32 checkSz,
int ret = 0;
WC_DECLARE_VAR(cmac, Cmac, 1, 0);

if (check == NULL || checkSz == 0 || (in == NULL && inSz > 0) ||
if (check == NULL || checkSz < WC_CMAC_TAG_MIN_SZ ||
checkSz > WC_AES_BLOCK_SIZE || (in == NULL && inSz > 0) ||
key == NULL || keySz == 0) {
return BAD_FUNC_ARG;
}
Expand Down
20 changes: 18 additions & 2 deletions wolfssl/wolfcrypt/settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -4202,7 +4202,8 @@ extern void uITRON4_free(void *p) ;
#if defined(HAVE_CURVE25519) && !defined(CURVE25519_SMALL) && \
!defined(FREESCALE_LTC_ECC) && !defined(WOLFSSL_ARMASM) && \
(!defined(USE_INTEL_SPEEDUP) || defined(NO_CURVED25519_X64)) && \
!defined(WOLFSSL_CURVE25519_BLINDING) && !defined(NO_CURVE25519_BLINDING)
!defined(WOLFSSL_CURVE25519_BLINDING) && !defined(NO_CURVE25519_BLINDING) \
&& !defined(WC_NO_RNG)
#define WOLFSSL_CURVE25519_BLINDING
#endif

Expand All @@ -4212,7 +4213,8 @@ extern void uITRON4_free(void *p) ;
#if (defined(USE_FAST_MATH) && !defined(TFM_TIMING_RESISTANT)) || \
(defined(HAVE_ECC) && !defined(ECC_TIMING_RESISTANT)) || \
(!defined(NO_RSA) && !defined(WC_RSA_BLINDING) && !defined(HAVE_FIPS) && \
!defined(WC_NO_RNG))
!defined(WC_NO_RNG) && !defined(WOLFSSL_RSA_PUBLIC_ONLY) && \
!defined(WOLFSSL_RSA_VERIFY_ONLY))

#if !defined(_MSC_VER) && !defined(__TASKING__)
#warning "For timing resistance / side-channel attack prevention consider using harden options"
Expand All @@ -4222,6 +4224,20 @@ extern void uITRON4_free(void *p) ;
#endif
#endif

/* WC_NO_RNG silently removes RSA blinding, as blinding depends on the RNG.
* Refuse to build until the conflict is resolved or the loss of hardening is
* explicitly acknowledged via WC_BLINDING_NO_RNG_ACKNOWLEDGE_WEAKNESS. */
#if defined(WC_NO_RNG) && ((defined(WC_RSA_BLINDING) && !defined(NO_RSA) && \
!defined(WOLFSSL_RSA_PUBLIC_ONLY) && !defined(WOLFSSL_RSA_VERIFY_ONLY)) || \
(defined(HAVE_CURVE25519) && defined(WOLFSSL_CURVE25519_BLINDING)) || \
(defined(HAVE_ECC) && defined(WOLFSSL_ECC_BLIND_K))) && \
!defined(WC_BLINDING_NO_RNG_ACKNOWLEDGE_WEAKNESS)
#error "Blinding is enabled but the RNG is disabled. Either remove \
WC_NO_RNG to enable the RNG, disable blinding by removing WC_RSA_BLINDING/\
WOLFSSL_CURVE25519_BLINDING/WOLFSSL_ECC_BLIND_K, or acknowledge the loss of \
blinding by defining WC_BLINDING_NO_RNG_ACKNOWLEDGE_WEAKNESS."
#endif
Comment thread
kareem-wolfssl marked this conversation as resolved.

#ifdef OPENSSL_COEXIST
/* make sure old names are disabled */
#ifndef NO_OLD_SSL_NAMES
Expand Down
Loading