Skip to content

Commit cd98f59

Browse files
committed
Add TLS 1.3 crypto callback pending support for transcript HMAC
1 parent 7e4d2de commit cd98f59

5 files changed

Lines changed: 112 additions & 1 deletion

File tree

src/internal.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9741,6 +9741,13 @@ void wolfSSL_ResourceFree(WOLFSSL* ssl)
97419741
#ifdef WOLFSSL_ASYNC_IO
97429742
/* Cleanup async */
97439743
FreeAsyncCtx(ssl, 1);
9744+
#endif
9745+
#ifdef WOLFSSL_ASYNC_REINVOKE
9746+
if (ssl->hsHmac != NULL) {
9747+
wc_HmacFree(ssl->hsHmac);
9748+
XFREE(ssl->hsHmac, ssl->heap, DYNAMIC_TYPE_HMAC);
9749+
ssl->hsHmac = NULL;
9750+
}
97449751
#endif
97459752
if (ssl->options.weOwnRng) {
97469753
wc_FreeRng(ssl->rng);

src/ssl.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5716,6 +5716,14 @@ size_t wolfSSL_get_client_random(const WOLFSSL* ssl, unsigned char* out,
57165716
ssl->kdfDeriveStep = TLS13_SEND_KDF_NONE;
57175717
ssl->kdfMsgStep = TLS13_MSG_KDF_NONE;
57185718
ssl->kdfMsgType = 0;
5719+
#ifdef WOLFSSL_ASYNC_REINVOKE
5720+
if (ssl->hsHmac != NULL) {
5721+
wc_HmacFree(ssl->hsHmac);
5722+
XFREE(ssl->hsHmac, ssl->heap, DYNAMIC_TYPE_HMAC);
5723+
ssl->hsHmac = NULL;
5724+
}
5725+
ssl->hsHmacStep = 0;
5726+
#endif
57195727
#ifdef WOLFSSL_ASYNC_CRYPT
57205728
ssl->options.buildArgs13Set = 0;
57215729
/* An abandoned handshake can leave a mid-flight handler resume

src/tls13.c

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1508,7 +1508,9 @@ int DeriveResumptionPSK(WOLFSSL* ssl, byte* nonce, byte nonceLen, byte* secret)
15081508
static int BuildTls13HandshakeHmac(WOLFSSL* ssl, byte* key, byte* hash,
15091509
word32* pHashSz)
15101510
{
1511+
#ifndef WOLFSSL_ASYNC_REINVOKE
15111512
WC_DECLARE_VAR(verifyHmac, Hmac, 1, 0);
1513+
#endif
15121514
int hashType = WC_SHA256;
15131515
int hashSz = WC_SHA256_DIGEST_SIZE;
15141516
int ret = WC_NO_ERR_TRACE(BAD_FUNC_ARG);
@@ -1561,6 +1563,48 @@ static int BuildTls13HandshakeHmac(WOLFSSL* ssl, byte* key, byte* hash,
15611563
WOLFSSL_BUFFER(hash, hashSz);
15621564
#endif
15631565

1566+
#ifdef WOLFSSL_ASYNC_REINVOKE
1567+
/* Held on the SSL object so a crypto callback WC_PENDING_E resumes by
1568+
* re-invoking the same Hmac with identical arguments; the transcript
1569+
* hash input is recomputed deterministically by the caller's retry. */
1570+
if (ssl->hsHmac == NULL) {
1571+
ssl->hsHmac = (Hmac*)XMALLOC(sizeof(Hmac), ssl->heap,
1572+
DYNAMIC_TYPE_HMAC);
1573+
if (ssl->hsHmac == NULL)
1574+
return MEMORY_E;
1575+
ret = wc_HmacInit(ssl->hsHmac, ssl->heap, ssl->devId);
1576+
if (ret == 0)
1577+
ret = wc_HmacSetKey(ssl->hsHmac, hashType, key,
1578+
ssl->specs.hash_size);
1579+
if (ret != 0) {
1580+
XFREE(ssl->hsHmac, ssl->heap, DYNAMIC_TYPE_HMAC);
1581+
ssl->hsHmac = NULL;
1582+
return ret;
1583+
}
1584+
ssl->hsHmacStep = 0;
1585+
}
1586+
ret = 0;
1587+
if (ssl->hsHmacStep == 0) {
1588+
ret = wc_HmacUpdate(ssl->hsHmac, hash, (word32)hashSz);
1589+
if (ret == 0)
1590+
ssl->hsHmacStep = 1;
1591+
}
1592+
if (ret == 0 && ssl->hsHmacStep == 1)
1593+
ret = wc_HmacFinal(ssl->hsHmac, hash);
1594+
if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) {
1595+
int aret = Tls13KdfAsyncInit(ssl);
1596+
if (aret != 0)
1597+
ret = aret;
1598+
else
1599+
ret = wolfSSL_AsyncPush(ssl, &ssl->kdfAsyncDev);
1600+
}
1601+
if (ret != WC_NO_ERR_TRACE(WC_PENDING_E)) {
1602+
wc_HmacFree(ssl->hsHmac);
1603+
XFREE(ssl->hsHmac, ssl->heap, DYNAMIC_TYPE_HMAC);
1604+
ssl->hsHmac = NULL;
1605+
ssl->hsHmacStep = 0;
1606+
}
1607+
#else
15641608
WC_ALLOC_VAR_EX(verifyHmac, Hmac, 1, NULL, DYNAMIC_TYPE_HMAC,
15651609
return MEMORY_E);
15661610

@@ -1576,6 +1620,7 @@ static int BuildTls13HandshakeHmac(WOLFSSL* ssl, byte* key, byte* hash,
15761620
}
15771621

15781622
WC_FREE_VAR_EX(verifyHmac, NULL, DYNAMIC_TYPE_HMAC);
1623+
#endif /* WOLFSSL_ASYNC_REINVOKE */
15791624

15801625
#ifdef WOLFSSL_DEBUG_TLS
15811626
WOLFSSL_MSG(" Hash");

tests/api/test_tls13.c

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9543,7 +9543,8 @@ enum TestTls13PendTarget {
95439543
TEST_TLS13_PEND_ECC_KEYGEN,
95449544
TEST_TLS13_PEND_ECDSA_SIGN,
95459545
TEST_TLS13_PEND_ECDSA_VERIFY,
9546-
TEST_TLS13_PEND_KDF
9546+
TEST_TLS13_PEND_KDF,
9547+
TEST_TLS13_PEND_HMAC
95479548
};
95489549

95499550
typedef struct TestTls13PendCtx {
@@ -9585,6 +9586,9 @@ static int TestTls13PendMatches(int target, wc_CryptoInfo* info)
95859586
case TEST_TLS13_PEND_KDF:
95869587
match = (info->algo_type == WC_ALGO_TYPE_KDF);
95879588
break;
9589+
case TEST_TLS13_PEND_HMAC:
9590+
match = (info->algo_type == WC_ALGO_TYPE_HMAC);
9591+
break;
95889592
default:
95899593
break;
95909594
}
@@ -9615,10 +9619,43 @@ static int TestTls13PendCb(int devIdArg, wc_CryptoInfo* info, void* ctx)
96159619

96169620
if (info == NULL || c == NULL)
96179621
return WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE);
9622+
#if defined(HAVE_HKDF) && !defined(NO_HMAC) && !defined(HAVE_SELFTEST) && \
9623+
(!defined(HAVE_FIPS) || FIPS_VERSION_GE(7,0))
9624+
if (c->target == TEST_TLS13_PEND_HMAC &&
9625+
info->algo_type == WC_ALGO_TYPE_KDF) {
9626+
/* Serve the key schedule synchronously in software; falling back
9627+
* with the devId set would route its internal HMACs back here and
9628+
* those cannot resume (see wolfcrypt/src/hmac.c). Only the
9629+
* TLS-layer transcript HMACs are left to pend. */
9630+
if (info->kdf.type == WC_KDF_TYPE_HKDF_EXTRACT) {
9631+
return wc_HKDF_Extract_ex(info->kdf.hkdf_extract.hashType,
9632+
info->kdf.hkdf_extract.salt, info->kdf.hkdf_extract.saltSz,
9633+
info->kdf.hkdf_extract.inKey, info->kdf.hkdf_extract.inKeySz,
9634+
info->kdf.hkdf_extract.out, NULL, INVALID_DEVID);
9635+
}
9636+
if (info->kdf.type == WC_KDF_TYPE_HKDF_EXPAND) {
9637+
return wc_HKDF_Expand_ex(info->kdf.hkdf_expand.hashType,
9638+
info->kdf.hkdf_expand.inKey, info->kdf.hkdf_expand.inKeySz,
9639+
info->kdf.hkdf_expand.info, info->kdf.hkdf_expand.infoSz,
9640+
info->kdf.hkdf_expand.out, info->kdf.hkdf_expand.outSz,
9641+
NULL, INVALID_DEVID);
9642+
}
9643+
if (info->kdf.type == WC_KDF_TYPE_HKDF) {
9644+
return wc_HKDF_ex(info->kdf.hkdf.hashType,
9645+
info->kdf.hkdf.inKey, info->kdf.hkdf.inKeySz,
9646+
info->kdf.hkdf.salt, info->kdf.hkdf.saltSz,
9647+
info->kdf.hkdf.info, info->kdf.hkdf.infoSz,
9648+
info->kdf.hkdf.out, info->kdf.hkdf.outSz,
9649+
NULL, INVALID_DEVID);
9650+
}
9651+
}
9652+
#endif
9653+
96189654
if (!TestTls13PendMatches(c->target, info))
96199655
return WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE);
96209656

96219657
c->seen++;
9658+
96229659
h = TestTls13PendHash(info);
96239660
for (i = 0; i < c->jobCount; i++) {
96249661
if (c->jobs[i] == h) {
@@ -9849,6 +9886,14 @@ int test_tls13_cryptocb_async(void)
98499886
TEST_SUCCESS);
98509887
ExpectIntEQ(test_tls13_cryptocb_pend_one(TEST_TLS13_PEND_KDF, 1),
98519888
TEST_SUCCESS);
9889+
#if !defined(HAVE_SELFTEST) && \
9890+
(!defined(HAVE_FIPS) || FIPS_VERSION_GE(7,0))
9891+
/* Transcript HMACs (Finished verify_data) pending on both sides. */
9892+
ExpectIntEQ(test_tls13_cryptocb_pend_one(TEST_TLS13_PEND_HMAC, 0),
9893+
TEST_SUCCESS);
9894+
ExpectIntEQ(test_tls13_cryptocb_pend_one(TEST_TLS13_PEND_HMAC, 1),
9895+
TEST_SUCCESS);
9896+
#endif
98529897
#endif
98539898
#endif
98549899
return EXPECT_RESULT();

wolfssl/internal.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7076,6 +7076,12 @@ struct WOLFSSL {
70767076
byte kdfDeriveStep; /* enum Tls13KdfSendStep (send side) */
70777077
byte kdfMsgStep; /* enum Tls13KdfMsgStep (receive side) */
70787078
byte kdfMsgType; /* handshake type kdfMsgStep belongs to */
7079+
#ifdef WOLFSSL_ASYNC_REINVOKE
7080+
/* Transcript HMAC (Finished verify_data, PSK binders) held across a
7081+
* WC_PENDING_E so the retry re-invokes the same object and arguments. */
7082+
Hmac* hsHmac;
7083+
byte hsHmacStep;
7084+
#endif
70797085
};
70807086

70817087
#if defined(WOLFSSL_SYS_CRYPTO_POLICY)

0 commit comments

Comments
 (0)