Skip to content

Commit f1e8c1b

Browse files
authored
Merge pull request #9787 from holtrop-wolfssl/fix-integrity-only-cipher-nonce-calculation
Fix integrity-only cipher nonce calculation
2 parents 936d20a + b4427dd commit f1e8c1b

7 files changed

Lines changed: 176 additions & 59 deletions

File tree

scripts/openssl.test

Lines changed: 129 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -387,15 +387,22 @@ do_openssl_client() {
387387
openssl_caCert1="-CAfile"
388388
openssl_caCert2="$caCert"
389389
fi
390+
# Integrity-only cipher suites require SECLEVEL=0 to allow NULL encryption
391+
openssl_seclevel=""
392+
if [ "$tls13_integrity_only" = "yes" ]
393+
then
394+
openssl_seclevel="-cipher ALL:@SECLEVEL=0"
395+
fi
396+
390397
if [ "$tls13_cipher" = "" ]
391398
then
392399
echo "#"
393400
echo "# $OPENSSL s_client -connect localhost:$port -reconnect -legacy_renegotiation -cipher $cmpSuite $openssl_version $openssl_psk $openssl_cert1 \"$openssl_cert2\" $openssl_key1 \"$openssl_key2\" $openssl_caCert1 \"$openssl_caCert2\""
394401
echo "Hello" | eval "$OPENSSL s_client -connect localhost:$port -reconnect -legacy_renegotiation -cipher $cmpSuite $openssl_version $openssl_psk $openssl_cert1 \"$openssl_cert2\" $openssl_key1 \"$openssl_key2\" $openssl_caCert1 \"$openssl_caCert2\""
395402
else
396403
echo "#"
397-
echo "# $OPENSSL s_client -connect localhost:$port -reconnect -legacy_renegotiation -ciphersuites=$cmpSuite $openssl_version $openssl_psk $openssl_cert1 \"$openssl_cert2\" $openssl_key1 \"$openssl_key2\" $openssl_caCert1 \"$openssl_caCert2\""
398-
echo "Hello" | eval "$OPENSSL s_client -connect localhost:$port -reconnect -legacy_renegotiation -ciphersuites=$cmpSuite $openssl_version $openssl_psk $openssl_cert1 \"$openssl_cert2\" $openssl_key1 \"$openssl_key2\" $openssl_caCert1 \"$openssl_caCert2\""
404+
echo "# $OPENSSL s_client -connect localhost:$port -reconnect -legacy_renegotiation -ciphersuites=$cmpSuite $openssl_seclevel $openssl_version $openssl_psk $openssl_cert1 \"$openssl_cert2\" $openssl_key1 \"$openssl_key2\" $openssl_caCert1 \"$openssl_caCert2\""
405+
echo "Hello" | eval "$OPENSSL s_client -connect localhost:$port -reconnect -legacy_renegotiation -ciphersuites=$cmpSuite $openssl_seclevel $openssl_version $openssl_psk $openssl_cert1 \"$openssl_cert2\" $openssl_key1 \"$openssl_key2\" $openssl_caCert1 \"$openssl_caCert2\""
399406
fi
400407

401408
client_result=$?
@@ -941,8 +948,9 @@ do
941948
echo -e "trying wolfSSL cipher suite $wolfSuite"
942949
wolf_temp_cases_total=$((wolf_temp_cases_total + 1))
943950
open_temp_cases_total=$((open_temp_cases_total + 1))
944-
matchSuite=0;
951+
matchSuite=0
945952
tls13_suite=
953+
tls13_integrity_only=
946954

947955
case $wolfSuite in
948956
"TLS13-AES128-GCM-SHA256")
@@ -966,10 +974,22 @@ do
966974
tls13_suite="yes"
967975
;;
968976
"TLS13-SHA256-SHA256")
969-
continue
977+
cmpSuite="TLS_SHA256_SHA256"
978+
tls13_suite="yes"
979+
tls13_integrity_only="yes"
980+
# OpenSSL does not enable TLS_SHA256_SHA256 in openssl ciphers
981+
# output by default, but it can be specified with -ciphersuite as
982+
# done in do_openssl_client()
983+
matchSuite=1
970984
;;
971985
"TLS13-SHA384-SHA384")
972-
continue
986+
cmpSuite="TLS_SHA384_SHA384"
987+
tls13_suite="yes"
988+
tls13_integrity_only="yes"
989+
# OpenSSL does not enable TLS_SHA256_SHA256 in openssl ciphers
990+
# output by default, but it can be specified with -ciphersuite as
991+
# done in do_openssl_client()
992+
matchSuite=1
973993
;;
974994
"TLS13-"*)
975995
echo -e "Suite = $wolfSuite not recognized!"
@@ -982,35 +1002,38 @@ do
9821002
;;
9831003
esac
9841004

985-
case ":$openssl_ciphers:" in *":$cmpSuite:"*) # add extra : for edge cases
986-
case "$cmpSuite" in
987-
"TLS_"*)
988-
if [ "$version" != "4" -a "$version" != "d" ]
989-
then
990-
echo -e "TLS 1.3 cipher suite but not TLS 1.3 protocol"
991-
matchSuite=0
992-
else
993-
echo -e "Matched to OpenSSL suite support"
994-
matchSuite=1
995-
fi
996-
;;
997-
*)
998-
if [ "$version" = "d" -a "$wolfdowngrade" = "4" ]
999-
then
1000-
echo -e "Not TLS 1.3 cipher suite but TLS 1.3 downgrade"
1001-
matchSuite=0
1002-
elif [ "$version" != "4" ]
1003-
then
1004-
echo -e "Matched to OpenSSL suite support"
1005-
matchSuite=1
1006-
else
1007-
echo -e "Not TLS 1.3 cipher suite but TLS 1.3 protocol"
1008-
matchSuite=0
1009-
fi
1005+
if [ $matchSuite = 0 ]
1006+
then
1007+
case ":$openssl_ciphers:" in *":$cmpSuite:"*) # add extra : for edge cases
1008+
case "$cmpSuite" in
1009+
"TLS_"*)
1010+
if [ "$version" != "4" -a "$version" != "d" ]
1011+
then
1012+
echo -e "TLS 1.3 cipher suite but not TLS 1.3 protocol"
1013+
matchSuite=0
1014+
else
1015+
echo -e "Matched to OpenSSL suite support"
1016+
matchSuite=1
1017+
fi
1018+
;;
1019+
*)
1020+
if [ "$version" = "d" -a "$wolfdowngrade" = "4" ]
1021+
then
1022+
echo -e "Not TLS 1.3 cipher suite but TLS 1.3 downgrade"
1023+
matchSuite=0
1024+
elif [ "$version" != "4" ]
1025+
then
1026+
echo -e "Matched to OpenSSL suite support"
1027+
matchSuite=1
1028+
else
1029+
echo -e "Not TLS 1.3 cipher suite but TLS 1.3 protocol"
1030+
matchSuite=0
1031+
fi
1032+
;;
1033+
esac
10101034
;;
10111035
esac
1012-
;;
1013-
esac
1036+
fi
10141037

10151038
if [ $matchSuite = 0 ]
10161039
then
@@ -1130,6 +1153,80 @@ do
11301153
continue
11311154
fi
11321155
tls13_cipher=yes
1156+
# Integrity-only cipher suites (NULL encryption)
1157+
if [ "$tls13_integrity_only" = "yes" ]
1158+
then
1159+
# Only run integrity-only tests with TLS 1.3 (version 4)
1160+
if [ "$version" != "4" ]
1161+
then
1162+
tls13_cipher=
1163+
tls13_integrity_only=
1164+
continue
1165+
fi
1166+
1167+
# Integrity-only cipher suites require OpenSSL 3.4 or later
1168+
$OPENSSL version | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1 | \
1169+
awk -F. '{if ($1 > 3 || ($1 == 3 && $2 >= 4)) exit 1; else exit 0;}'
1170+
if [ $? -eq 0 ]
1171+
then
1172+
echo -e "OpenSSL version too old for integrity-only ciphers, skipping"
1173+
tls13_cipher=
1174+
tls13_integrity_only=
1175+
continue
1176+
fi
1177+
1178+
# Test with RSA certs if available
1179+
if [ $openssl_pid != $no_pid -a "$wolf_rsa" != "" ]
1180+
then
1181+
cert="${CERT_DIR}/client-cert.pem"
1182+
key="${CERT_DIR}/client-key.pem"
1183+
caCert="${CERT_DIR}/ca-cert.pem"
1184+
1185+
# Start a dedicated OpenSSL server for integrity-only tests
1186+
generate_port
1187+
integrity_openssl_port=$port
1188+
$OPENSSL s_server -accept $integrity_openssl_port -cert "${CERT_DIR}/server-cert.pem" -key "${CERT_DIR}/server-key.pem" -quiet -CAfile "${CERT_DIR}/client-cert.pem" -www -cipher "ALL:eNULL:@SECLEVEL=0" -ciphersuites "$cmpSuite" -verify 10 -verify_return_error &
1189+
integrity_openssl_pid=$!
1190+
sleep 0.1
1191+
1192+
port=$integrity_openssl_port
1193+
do_wolfssl_client
1194+
1195+
# Kill the dedicated server
1196+
kill $integrity_openssl_pid 2>/dev/null
1197+
1198+
port=$wolfssl_port
1199+
do_openssl_client
1200+
fi
1201+
# Test with ECC certs if available
1202+
if [ $ecdsa_openssl_pid != $no_pid -a "$wolf_ecc" != "" ]
1203+
then
1204+
cert="${CERT_DIR}/client-ecc-cert.pem"
1205+
key="${CERT_DIR}/ecc-client-key.pem"
1206+
caCert="${CERT_DIR}/ca-ecc-cert.pem"
1207+
1208+
# Start a dedicated OpenSSL server for integrity-only tests (ECC)
1209+
generate_port
1210+
integrity_openssl_port=$port
1211+
$OPENSSL s_server -accept $integrity_openssl_port -cert "${CERT_DIR}/server-ecc.pem" -key "${CERT_DIR}/ecc-key.pem" -quiet -CAfile "${CERT_DIR}/client-ecc-cert.pem" -www -cipher "ALL:eNULL:@SECLEVEL=0" -ciphersuites "$cmpSuite" -verify 10 -verify_return_error &
1212+
integrity_openssl_pid=$!
1213+
sleep 0.1
1214+
1215+
wolf_temp_cases_total=$((wolf_temp_cases_total + 1))
1216+
port=$integrity_openssl_port
1217+
do_wolfssl_client
1218+
1219+
# Kill the dedicated server
1220+
kill $integrity_openssl_pid 2>/dev/null
1221+
1222+
open_temp_cases_total=$((open_temp_cases_total + 1))
1223+
port=$ecdsa_wolfssl_port
1224+
do_openssl_client
1225+
fi
1226+
tls13_cipher=
1227+
tls13_integrity_only=
1228+
continue
1229+
fi
11331230
# RSA
11341231
if [ $openssl_pid != $no_pid -a "$ecdhe_avail" = "yes" ]
11351232
then

src/internal.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -938,7 +938,7 @@ static int ExportKeyState(WOLFSSL* ssl, byte* exp, word32 len, byte ver,
938938
XMEMCPY(exp + idx, keys->aead_exp_IV, AEAD_MAX_EXP_SZ);
939939
idx += AEAD_MAX_EXP_SZ;
940940

941-
sz = (small)? 0: AEAD_MAX_IMP_SZ;
941+
sz = (small)? 0: ssl->specs.iv_size;
942942
if (idx + (sz * 2) + OPAQUE8_LEN > len) {
943943
WOLFSSL_MSG("Buffer not large enough for imp IVs");
944944
return BUFFER_E;

src/keys.c

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1239,7 +1239,7 @@ int GetCipherSpec(word16 side, byte cipherSuite0, byte cipherSuite,
12391239
specs->static_ecdh = 0;
12401240
specs->key_size = WC_SHA256_DIGEST_SIZE;
12411241
specs->block_size = 0;
1242-
specs->iv_size = HMAC_NONCE_SZ;
1242+
specs->iv_size = WC_SHA256_DIGEST_SIZE;
12431243
specs->aead_mac_size = WC_SHA256_DIGEST_SIZE;
12441244

12451245
break;
@@ -1257,7 +1257,7 @@ int GetCipherSpec(word16 side, byte cipherSuite0, byte cipherSuite,
12571257
specs->static_ecdh = 0;
12581258
specs->key_size = WC_SHA384_DIGEST_SIZE;
12591259
specs->block_size = 0;
1260-
specs->iv_size = HMAC_NONCE_SZ;
1260+
specs->iv_size = WC_SHA384_DIGEST_SIZE;
12611261
specs->aead_mac_size = WC_SHA384_DIGEST_SIZE;
12621262

12631263
break;
@@ -2827,7 +2827,7 @@ int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs,
28272827
(defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)))
28282828
if (!tls13) {
28292829
CcmRet = wc_AesCcmSetNonce(enc->aes, keys->client_write_IV,
2830-
AEAD_MAX_IMP_SZ);
2830+
AEAD_NONCE_SZ);
28312831
if (CcmRet != 0) return CcmRet;
28322832
}
28332833
#endif
@@ -2856,7 +2856,7 @@ int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs,
28562856
(defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)))
28572857
if (!tls13) {
28582858
CcmRet = wc_AesCcmSetNonce(enc->aes, keys->server_write_IV,
2859-
AEAD_MAX_IMP_SZ);
2859+
AEAD_NONCE_SZ);
28602860
if (CcmRet != 0) return CcmRet;
28612861
}
28622862
#endif
@@ -3357,14 +3357,14 @@ int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs,
33573357
if (side == WOLFSSL_CLIENT_END) {
33583358
if (enc) {
33593359
XMEMCPY(keys->aead_enc_imp_IV, keys->client_write_IV,
3360-
HMAC_NONCE_SZ);
3360+
specs->iv_size);
33613361
hmacRet = wc_HmacSetKey(enc->hmac, hashType,
33623362
keys->client_write_key, specs->key_size);
33633363
if (hmacRet != 0) return hmacRet;
33643364
}
33653365
if (dec) {
33663366
XMEMCPY(keys->aead_dec_imp_IV, keys->server_write_IV,
3367-
HMAC_NONCE_SZ);
3367+
specs->iv_size);
33683368
hmacRet = wc_HmacSetKey(dec->hmac, hashType,
33693369
keys->server_write_key, specs->key_size);
33703370
if (hmacRet != 0) return hmacRet;
@@ -3373,14 +3373,14 @@ int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs,
33733373
else {
33743374
if (enc) {
33753375
XMEMCPY(keys->aead_enc_imp_IV, keys->server_write_IV,
3376-
HMAC_NONCE_SZ);
3376+
specs->iv_size);
33773377
hmacRet = wc_HmacSetKey(enc->hmac, hashType,
33783378
keys->server_write_key, specs->key_size);
33793379
if (hmacRet != 0) return hmacRet;
33803380
}
33813381
if (dec) {
33823382
XMEMCPY(keys->aead_dec_imp_IV, keys->client_write_IV,
3383-
HMAC_NONCE_SZ);
3383+
specs->iv_size);
33843384
hmacRet = wc_HmacSetKey(dec->hmac, hashType,
33853385
keys->client_write_key, specs->key_size);
33863386
if (hmacRet != 0) return hmacRet;

src/tls13.c

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2426,9 +2426,13 @@ static WC_INLINE void WriteSEQTls13(WOLFSSL* ssl, int verifyOrder, byte* out)
24262426
* order The side on which the message is to be or was sent.
24272427
*/
24282428
static WC_INLINE void BuildTls13Nonce(WOLFSSL* ssl, byte* nonce, const byte* iv,
2429-
int order)
2429+
int ivSz, int order)
24302430
{
2431-
int seq_offset = AEAD_NONCE_SZ - SEQ_SZ;
2431+
int seq_offset;
2432+
/* Ensure minimum nonce size for standard AEAD ciphers */
2433+
if (ivSz < AEAD_NONCE_SZ)
2434+
ivSz = AEAD_NONCE_SZ;
2435+
seq_offset = ivSz - SEQ_SZ;
24322436
/* The nonce is the IV with the sequence XORed into the last bytes. */
24332437
WriteSEQTls13(ssl, order, nonce + seq_offset);
24342438
XMEMCPY(nonce, iv, seq_offset);
@@ -2521,7 +2525,7 @@ static int Tls13IntegrityOnly_Encrypt(WOLFSSL* ssl, byte* output,
25212525
int ret;
25222526

25232527
/* HMAC: nonce | aad | input */
2524-
ret = wc_HmacUpdate(ssl->encrypt.hmac, nonce, HMAC_NONCE_SZ);
2528+
ret = wc_HmacUpdate(ssl->encrypt.hmac, nonce, ssl->specs.iv_size);
25252529
if (ret == 0)
25262530
ret = wc_HmacUpdate(ssl->encrypt.hmac, aad, aadSz);
25272531
if (ret == 0)
@@ -2604,20 +2608,20 @@ static int EncryptTls13(WOLFSSL* ssl, byte* output, const byte* input,
26042608

26052609
#ifdef CIPHER_NONCE
26062610
if (ssl->encrypt.nonce == NULL) {
2607-
ssl->encrypt.nonce = (byte*)XMALLOC(AEAD_NONCE_SZ,
2611+
ssl->encrypt.nonce = (byte*)XMALLOC(AEAD_MAX_IMP_SZ,
26082612
ssl->heap, DYNAMIC_TYPE_CIPHER);
26092613
#ifdef WOLFSSL_CHECK_MEM_ZERO
26102614
if (ssl->encrypt.nonce != NULL) {
26112615
wc_MemZero_Add("EncryptTls13 nonce", ssl->encrypt.nonce,
2612-
AEAD_NONCE_SZ);
2616+
ssl->specs.iv_size);
26132617
}
26142618
#endif
26152619
}
26162620
if (ssl->encrypt.nonce == NULL)
26172621
return MEMORY_E;
26182622

26192623
BuildTls13Nonce(ssl, ssl->encrypt.nonce, ssl->keys.aead_enc_imp_IV,
2620-
CUR_ORDER);
2624+
ssl->specs.iv_size, CUR_ORDER);
26212625
#endif
26222626

26232627
/* Advance state and proceed */
@@ -2799,7 +2803,7 @@ static int EncryptTls13(WOLFSSL* ssl, byte* output, const byte* input,
27992803
#endif
28002804

28012805
#ifdef CIPHER_NONCE
2802-
ForceZero(ssl->encrypt.nonce, AEAD_NONCE_SZ);
2806+
ForceZero(ssl->encrypt.nonce, ssl->specs.iv_size);
28032807
#endif
28042808

28052809
break;
@@ -2913,7 +2917,7 @@ static int Tls13IntegrityOnly_Decrypt(WOLFSSL* ssl, byte* output,
29132917
byte hmac[WC_MAX_DIGEST_SIZE];
29142918

29152919
/* HMAC: nonce | aad | input */
2916-
ret = wc_HmacUpdate(ssl->decrypt.hmac, nonce, HMAC_NONCE_SZ);
2920+
ret = wc_HmacUpdate(ssl->decrypt.hmac, nonce, ssl->specs.iv_size);
29172921
if (ret == 0)
29182922
ret = wc_HmacUpdate(ssl->decrypt.hmac, aad, aadSz);
29192923
if (ret == 0)
@@ -3005,20 +3009,20 @@ int DecryptTls13(WOLFSSL* ssl, byte* output, const byte* input, word16 sz,
30053009

30063010
#ifdef CIPHER_NONCE
30073011
if (ssl->decrypt.nonce == NULL) {
3008-
ssl->decrypt.nonce = (byte*)XMALLOC(AEAD_NONCE_SZ,
3012+
ssl->decrypt.nonce = (byte*)XMALLOC(AEAD_MAX_IMP_SZ,
30093013
ssl->heap, DYNAMIC_TYPE_CIPHER);
30103014
#ifdef WOLFSSL_CHECK_MEM_ZERO
30113015
if (ssl->decrypt.nonce != NULL) {
30123016
wc_MemZero_Add("DecryptTls13 nonce", ssl->decrypt.nonce,
3013-
AEAD_NONCE_SZ);
3017+
ssl->specs.iv_size);
30143018
}
30153019
#endif
30163020
}
30173021
if (ssl->decrypt.nonce == NULL)
30183022
return MEMORY_E;
30193023

30203024
BuildTls13Nonce(ssl, ssl->decrypt.nonce, ssl->keys.aead_dec_imp_IV,
3021-
PEER_ORDER);
3025+
ssl->specs.iv_size, PEER_ORDER);
30223026
#endif
30233027

30243028
/* Advance state and proceed */
@@ -3171,7 +3175,7 @@ int DecryptTls13(WOLFSSL* ssl, byte* output, const byte* input, word16 sz,
31713175
#endif
31723176

31733177
#ifdef CIPHER_NONCE
3174-
ForceZero(ssl->decrypt.nonce, AEAD_NONCE_SZ);
3178+
ForceZero(ssl->decrypt.nonce, ssl->specs.iv_size);
31753179
#endif
31763180

31773181
break;

wolfcrypt/src/port/Renesas/renesas_fspsm_util.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -853,8 +853,8 @@ int wc_fspsm_generateSessionKey(WOLFSSL *ssl,
853853
SCE_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 ||
854854
cbInfo->internal->cipher ==
855855
SCE_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256) {
856-
enc->aes->nonceSz = AEAD_MAX_IMP_SZ;
857-
dec->aes->nonceSz = AEAD_MAX_IMP_SZ;
856+
enc->aes->nonceSz = AEAD_NONCE_SZ;
857+
dec->aes->nonceSz = AEAD_NONCE_SZ;
858858
}
859859
enc->aes->devId = devId;
860860
dec->aes->devId = devId;

0 commit comments

Comments
 (0)