Skip to content

Commit 4c9116c

Browse files
authored
Merge pull request #10462 from kareem-wolfssl/zd21507
Fix alert type for missing cert. Prevent building with RNG disabled and blinding enabled by default. Enforce bounds for AES CMAC size in verify.
2 parents d982aa2 + 213bcb3 commit 4c9116c

6 files changed

Lines changed: 99 additions & 20 deletions

File tree

.wolfssl_known_macro_extras

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -651,6 +651,7 @@ WC_ASYNC_NO_SHA384
651651
WC_ASYNC_NO_SHA512
652652
WC_ASYNC_NO_X25519
653653
WC_ASYNC_THREAD_BIND
654+
WC_BLINDING_NO_RNG_ACKNOWLEDGE_WEAKNESS
654655
WC_CACHE_RESISTANT_BASE64_TABLE
655656
WC_DILITHIUM_FIXED_ARRAY
656657
WC_DISABLE_RADIX_ZERO_PAD

doc/dox_comments/header_files/cmac.h

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -174,8 +174,11 @@ int wc_AesCmacGenerate(byte* out, word32* outSz,
174174
\ingroup CMAC
175175
\brief Single shot function for validating a CMAC
176176
\return 0 on success
177-
\param check CMAC value to verify
178-
\param checkSz size of check buffer
177+
\return BAD_FUNC_ARG if parameters are invalid
178+
\return MAC_CMP_FAILED_E if the supplied tag does not match
179+
\param check Expected MAC value to verify
180+
\param checkSz size of expected MAC value; must be in
181+
[\c WC_CMAC_TAG_MIN_SZ, \c WC_AES_BLOCK_SIZE]
179182
\param in input data to process
180183
\param inSz size of input data
181184
\param key key pointer
@@ -211,10 +214,8 @@ int wc_CMAC_Grow(Cmac* cmac, const byte* in, int inSz);
211214
\ingroup CMAC
212215
\brief Single shot AES-CMAC generation with extended parameters
213216
including heap and device ID.
214-
215217
\return 0 on success
216218
\return BAD_FUNC_ARG if parameters are invalid
217-
218219
\param cmac Pointer to Cmac structure (can be NULL for one-shot)
219220
\param out Buffer to store MAC output
220221
\param outSz Pointer to output size (in/out)
@@ -249,14 +250,13 @@ int wc_AesCmacGenerate_ex(Cmac *cmac, byte* out, word32* outSz,
249250
\ingroup CMAC
250251
\brief Single shot AES-CMAC verification with extended parameters
251252
including heap and device ID.
252-
253253
\return 0 on success
254254
\return BAD_FUNC_ARG if parameters are invalid
255255
\return MAC_CMP_FAILED_E if MAC verification fails
256-
257-
\param cmac Pointer to Cmac structure (can be NULL for one-shot)
256+
\param cmac Pointer to Cmac structure
258257
\param check Expected MAC value to verify
259-
\param checkSz Size of expected MAC
258+
\param checkSz Size of expected MAC; must be in
259+
[\c WC_CMAC_TAG_MIN_SZ, \c WC_AES_BLOCK_SIZE]
260260
\param in Input data to authenticate
261261
\param inSz Length of input data
262262
\param key AES key
@@ -267,17 +267,24 @@ int wc_AesCmacGenerate_ex(Cmac *cmac, byte* out, word32* outSz,
267267
268268
_Example_
269269
\code
270-
byte mac[AES_BLOCK_SIZE];
270+
Cmac cmac;
271+
byte mac[WC_AES_BLOCK_SIZE];
271272
byte key[16], msg[64];
273+
int ret;
272274
273-
int ret = wc_AesCmacVerify_ex(NULL, mac, sizeof(mac), msg,
275+
ret = wc_InitCmac_ex(&cmac, key, sizeof(key), WC_CMAC_AES, NULL,
276+
NULL, INVALID_DEVID);
277+
if (ret == 0) {
278+
ret = wc_AesCmacVerify_ex(&cmac, mac, sizeof(mac), msg,
274279
sizeof(msg), key, sizeof(key),
275280
NULL, INVALID_DEVID);
281+
}
276282
if (ret == MAC_CMP_FAILED_E) {
277283
// MAC verification failed
278284
}
279285
\endcode
280286
287+
\sa wc_InitCmac_ex
281288
\sa wc_AesCmacVerify
282289
\sa wc_AesCmacGenerate_ex
283290
*/

src/tls13.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6156,7 +6156,10 @@ static int DoTls13CertificateRequest(WOLFSSL* ssl, const byte* input,
61566156
ssl->options.sendVerify = SEND_BLANK_CERT;
61576157
#else
61586158
WOLFSSL_MSG("Certificate required but none set on client");
6159-
SendAlert(ssl, alert_fatal, illegal_parameter);
6159+
/* RFC 8446 Section 4.4.2.4: send certificate_required when a
6160+
* peer (here, the client) cannot provide a certificate that the
6161+
* other peer required. */
6162+
SendAlert(ssl, alert_fatal, certificate_required);
61606163
WOLFSSL_ERROR_VERBOSE(NO_CERT_ERROR);
61616164
return NO_CERT_ERROR;
61626165
#endif

tests/api/test_cmac.c

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,49 @@ int test_wc_AesCmacGenerate(void)
244244
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
245245
ExpectIntEQ(wc_AesCmacVerify(mac, macSz, NULL, msgSz, key, keySz),
246246
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
247+
248+
#if !defined(HAVE_FIPS)
249+
ExpectIntEQ(wc_AesCmacVerify(mac, 1, msg, msgSz, key, keySz),
250+
WC_NO_ERR_TRACE(BAD_FUNC_ARG));
251+
ExpectIntEQ(wc_AesCmacVerify(mac, WC_CMAC_TAG_MIN_SZ - 1, msg, msgSz,
252+
key, keySz), WC_NO_ERR_TRACE(BAD_FUNC_ARG));
253+
ExpectIntEQ(wc_AesCmacVerify(mac, WC_AES_BLOCK_SIZE + 1, msg, msgSz,
254+
key, keySz), WC_NO_ERR_TRACE(BAD_FUNC_ARG));
255+
256+
/* Truncated tags within the supported range must verify correctly when
257+
* the generator was asked to produce the same length */
258+
{
259+
byte truncMac[WC_AES_BLOCK_SIZE];
260+
word32 truncSz;
261+
word32 lengths[] = { WC_CMAC_TAG_MIN_SZ, 8, WC_AES_BLOCK_SIZE - 1 };
262+
word32 lengthsSz = (word32)(sizeof(lengths)/sizeof(lengths[0]));
263+
word32 li;
264+
for (li = 0; li < lengthsSz; li++) {
265+
XMEMSET(truncMac, 0, sizeof(truncMac));
266+
truncSz = lengths[li];
267+
ExpectIntEQ(wc_AesCmacGenerate(truncMac, &truncSz, msg, msgSz,
268+
key, keySz), 0);
269+
ExpectIntEQ(truncSz, lengths[li]);
270+
ExpectIntEQ(wc_AesCmacVerify(truncMac, truncSz, msg, msgSz,
271+
key, keySz), 0);
272+
/* Flipping a bit in the truncated tag must yield
273+
* MAC_CMP_FAILED_E, not silent success from comparing a too
274+
* short prefix. */
275+
truncMac[0] ^= 0x01;
276+
ExpectIntEQ(wc_AesCmacVerify(truncMac, truncSz, msg, msgSz,
277+
key, keySz), WC_NO_ERR_TRACE(MAC_CMP_FAILED_E));
278+
}
279+
}
280+
281+
/* A full-length tag that does not match must return MAC_CMP_FAILED_E. */
282+
{
283+
byte badMac[WC_AES_BLOCK_SIZE];
284+
XMEMCPY(badMac, mac, WC_AES_BLOCK_SIZE);
285+
badMac[0] ^= 0x01;
286+
ExpectIntEQ(wc_AesCmacVerify(badMac, WC_AES_BLOCK_SIZE, msg, msgSz,
287+
key, keySz), WC_NO_ERR_TRACE(MAC_CMP_FAILED_E));
288+
}
289+
#endif
247290
#endif
248291
return EXPECT_RESULT();
249292

wolfcrypt/src/cmac.c

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -574,24 +574,32 @@ int wc_AesCmacVerify_ex(Cmac* cmac,
574574
{
575575
int ret = 0;
576576
byte a[WC_AES_BLOCK_SIZE];
577-
word32 aSz = sizeof(a);
577+
word32 aSz;
578578
int compareRet;
579579

580-
if (cmac == NULL || check == NULL || checkSz == 0 ||
581-
(in == NULL && inSz != 0)) {
580+
if (cmac == NULL || check == NULL || checkSz < WC_CMAC_TAG_MIN_SZ ||
581+
checkSz > WC_AES_BLOCK_SIZE || (in == NULL && inSz != 0)) {
582582
return BAD_FUNC_ARG;
583583
}
584584

585-
XMEMSET(a, 0, aSz);
585+
aSz = checkSz;
586+
XMEMSET(a, 0, sizeof(a));
586587
ret = wc_AesCmacGenerate_ex(cmac,
587588
a, &aSz,
588589
in, inSz,
589590
key, keySz,
590591
heap,
591592
devId);
593+
/* aSz is passed by reference to wc_AesCmacGenerate_ex, which on the
594+
* WOLF_CRYPTO_CB path forwards it to a user-supplied callback that may
595+
* write back any value. Reject anything that does not match the user
596+
* provided length. */
597+
if (ret == 0 && aSz != checkSz) {
598+
ret = BAD_STATE_E;
599+
}
592600
if (ret == 0) {
593-
compareRet = ConstantCompare(check, a, (int)min(checkSz, aSz));
594-
ret = compareRet ? 1 : 0;
601+
compareRet = ConstantCompare(check, a, (int)aSz);
602+
ret = compareRet ? MAC_CMP_FAILED_E : 0;
595603
}
596604

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

608-
if (check == NULL || checkSz == 0 || (in == NULL && inSz > 0) ||
616+
if (check == NULL || checkSz < WC_CMAC_TAG_MIN_SZ ||
617+
checkSz > WC_AES_BLOCK_SIZE || (in == NULL && inSz > 0) ||
609618
key == NULL || keySz == 0) {
610619
return BAD_FUNC_ARG;
611620
}

wolfssl/wolfcrypt/settings.h

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4202,7 +4202,8 @@ extern void uITRON4_free(void *p) ;
42024202
#if defined(HAVE_CURVE25519) && !defined(CURVE25519_SMALL) && \
42034203
!defined(FREESCALE_LTC_ECC) && !defined(WOLFSSL_ARMASM) && \
42044204
(!defined(USE_INTEL_SPEEDUP) || defined(NO_CURVED25519_X64)) && \
4205-
!defined(WOLFSSL_CURVE25519_BLINDING) && !defined(NO_CURVE25519_BLINDING)
4205+
!defined(WOLFSSL_CURVE25519_BLINDING) && !defined(NO_CURVE25519_BLINDING) \
4206+
&& !defined(WC_NO_RNG)
42064207
#define WOLFSSL_CURVE25519_BLINDING
42074208
#endif
42084209

@@ -4212,7 +4213,8 @@ extern void uITRON4_free(void *p) ;
42124213
#if (defined(USE_FAST_MATH) && !defined(TFM_TIMING_RESISTANT)) || \
42134214
(defined(HAVE_ECC) && !defined(ECC_TIMING_RESISTANT)) || \
42144215
(!defined(NO_RSA) && !defined(WC_RSA_BLINDING) && !defined(HAVE_FIPS) && \
4215-
!defined(WC_NO_RNG))
4216+
!defined(WC_NO_RNG) && !defined(WOLFSSL_RSA_PUBLIC_ONLY) && \
4217+
!defined(WOLFSSL_RSA_VERIFY_ONLY))
42164218

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

4227+
/* WC_NO_RNG silently removes RSA blinding, as blinding depends on the RNG.
4228+
* Refuse to build until the conflict is resolved or the loss of hardening is
4229+
* explicitly acknowledged via WC_BLINDING_NO_RNG_ACKNOWLEDGE_WEAKNESS. */
4230+
#if defined(WC_NO_RNG) && ((defined(WC_RSA_BLINDING) && !defined(NO_RSA) && \
4231+
!defined(WOLFSSL_RSA_PUBLIC_ONLY) && !defined(WOLFSSL_RSA_VERIFY_ONLY)) || \
4232+
(defined(HAVE_CURVE25519) && defined(WOLFSSL_CURVE25519_BLINDING)) || \
4233+
(defined(HAVE_ECC) && defined(WOLFSSL_ECC_BLIND_K))) && \
4234+
!defined(WC_BLINDING_NO_RNG_ACKNOWLEDGE_WEAKNESS)
4235+
#error "Blinding is enabled but the RNG is disabled. Either remove \
4236+
WC_NO_RNG to enable the RNG, disable blinding by removing WC_RSA_BLINDING/\
4237+
WOLFSSL_CURVE25519_BLINDING/WOLFSSL_ECC_BLIND_K, or acknowledge the loss of \
4238+
blinding by defining WC_BLINDING_NO_RNG_ACKNOWLEDGE_WEAKNESS."
4239+
#endif
4240+
42254241
#ifdef OPENSSL_COEXIST
42264242
/* make sure old names are disabled */
42274243
#ifndef NO_OLD_SSL_NAMES

0 commit comments

Comments
 (0)