1
0
mirror of https://github.com/wolfSSL/wolfssl.git synced 2026-10-24 04:09:07 +03:00

tls13: factor the record key expansion out of DeriveTls13Keys

The second half of DeriveTls13Keys() - the "key"/"iv" labels, the provision
computation and the four Tls13DeriveKey() calls, plus Dtls13DeriveSnKeys() -
is the expansion of a pair of traffic secrets into the record keys. It is
reachable only through a full secret derivation, so a caller that already
holds the secrets cannot use it.

- add Tls13DeriveRecordKeys(), which expands the traffic secrets in
  ssl->clientSecret/serverSecret into ssl->keys and derives the DTLS 1.3
  record number key; it owns the key_dig buffer and its zeroization
- DeriveTls13Keys() keeps the secret derivation, the store gate and the
  DTLS 1.3 epoch bookkeeping, and no longer allocates key_dig when store is 0

No functional change.
This commit is contained in:
Marco Oliverio
2026-08-26 15:28:38 +02:00
parent 3f9f17e010
commit a09ec82b9b
2 changed files with 97 additions and 75 deletions

View File

@@ -1510,6 +1510,101 @@ static const byte writeKeyLabel[WRITE_KEY_LABEL_SZ+1] = "key";
/* The label to use when deriving IVs. */
static const byte writeIVLabel[WRITE_IV_LABEL_SZ+1] = "iv";
/* Expand the traffic secrets held in ssl->clientSecret/serverSecret into the
* record layer key and IV of ssl->keys, and, for DTLS 1.3, into the record
* number key. RFC 8446 Section 7.3 and RFC 9147 Section 4.2.3.
*
* ssl The SSL/TLS object.
* provision PROVISION_CLIENT, PROVISION_SERVER or both, naming the
* direction(s) whose secret is expanded.
* returns 0 on success, otherwise failure.
*/
int Tls13DeriveRecordKeys(WOLFSSL* ssl, int provision)
{
int ret = 0;
int i = 0;
WC_DECLARE_VAR(key_dig, byte, MAX_PRF_DIG, 0);
WC_ALLOC_VAR_EX(key_dig, byte, MAX_PRF_DIG, ssl->heap,
DYNAMIC_TYPE_DIGEST, return MEMORY_E);
#ifdef WOLFSSL_CHECK_MEM_ZERO
XMEMSET(key_dig, 0xff, MAX_PRF_DIG);
wc_MemZero_Add("Tls13DeriveRecordKeys key_dig", key_dig, MAX_PRF_DIG);
#endif
/* Key data = client key | server key | client IV | server IV */
if (provision & PROVISION_CLIENT) {
/* Derive the client key. */
WOLFSSL_MSG("Derive Client Key");
ret = Tls13DeriveKey(ssl, &key_dig[i], ssl->specs.key_size,
ssl->clientSecret, writeKeyLabel,
WRITE_KEY_LABEL_SZ, ssl->specs.mac_algorithm, 0,
WOLFSSL_CLIENT_END);
if (ret != 0)
goto end;
i += ssl->specs.key_size;
}
if (provision & PROVISION_SERVER) {
/* Derive the server key. */
WOLFSSL_MSG("Derive Server Key");
ret = Tls13DeriveKey(ssl, &key_dig[i], ssl->specs.key_size,
ssl->serverSecret, writeKeyLabel,
WRITE_KEY_LABEL_SZ, ssl->specs.mac_algorithm, 0,
WOLFSSL_SERVER_END);
if (ret != 0)
goto end;
i += ssl->specs.key_size;
}
if (provision & PROVISION_CLIENT) {
/* Derive the client IV. */
WOLFSSL_MSG("Derive Client IV");
ret = Tls13DeriveKey(ssl, &key_dig[i], ssl->specs.iv_size,
ssl->clientSecret, writeIVLabel,
WRITE_IV_LABEL_SZ, ssl->specs.mac_algorithm, 0,
WOLFSSL_CLIENT_END);
if (ret != 0)
goto end;
i += ssl->specs.iv_size;
}
if (provision & PROVISION_SERVER) {
/* Derive the server IV. */
WOLFSSL_MSG("Derive Server IV");
ret = Tls13DeriveKey(ssl, &key_dig[i], ssl->specs.iv_size,
ssl->serverSecret, writeIVLabel,
WRITE_IV_LABEL_SZ, ssl->specs.mac_algorithm, 0,
WOLFSSL_SERVER_END);
if (ret != 0)
goto end;
/* Server IV is the last key material written to key_dig, so i is not
* advanced here; the whole buffer is zeroed at end regardless. */
}
/* Store keys and IVs but don't activate them. */
ret = StoreKeys(ssl, key_dig, provision);
#ifdef WOLFSSL_DTLS13
if (ret == 0 && ssl->options.dtls)
ret = Dtls13DeriveSnKeys(ssl, provision);
#endif
end:
/* Zero the whole key_dig buffer (not just the i bytes derived) so no
* key-schedule material can linger in the unused tail. */
ForceZero(key_dig, MAX_PRF_DIG);
#ifdef WOLFSSL_SMALL_STACK
XFREE(key_dig, ssl->heap, DYNAMIC_TYPE_DIGEST);
#elif defined(WOLFSSL_CHECK_MEM_ZERO)
wc_MemZero_Check(key_dig, MAX_PRF_DIG);
#endif
return ret;
}
/* Derive the keys and IVs for TLS v1.3.
*
* ssl The SSL/TLS object.
@@ -1533,8 +1628,6 @@ static const byte writeIVLabel[WRITE_IV_LABEL_SZ+1] = "iv";
int DeriveTls13Keys(WOLFSSL* ssl, int secret, int side, int store)
{
int ret = WC_NO_ERR_TRACE(BAD_FUNC_ARG); /* Assume failure */
int i = 0;
WC_DECLARE_VAR(key_dig, byte, MAX_PRF_DIG, 0);
int provision;
#if defined(WOLFSSL_RENESAS_TSIP_TLS)
@@ -1545,14 +1638,6 @@ int DeriveTls13Keys(WOLFSSL* ssl, int secret, int side, int store)
ret = WC_NO_ERR_TRACE(BAD_FUNC_ARG); /* Assume failure */
#endif
WC_ALLOC_VAR_EX(key_dig, byte, MAX_PRF_DIG, ssl->heap,
DYNAMIC_TYPE_DIGEST, return MEMORY_E);
#ifdef WOLFSSL_CHECK_MEM_ZERO
XMEMSET(key_dig, 0xff, MAX_PRF_DIG);
wc_MemZero_Add("DeriveTls13Keys key_dig", key_dig, MAX_PRF_DIG);
#endif
if (side == ENCRYPT_AND_DECRYPT_SIDE) {
provision = PROVISION_CLIENT_SERVER;
}
@@ -1638,59 +1723,7 @@ int DeriveTls13Keys(WOLFSSL* ssl, int secret, int side, int store)
if (!store)
goto end;
/* Key data = client key | server key | client IV | server IV */
if (provision & PROVISION_CLIENT) {
/* Derive the client key. */
WOLFSSL_MSG("Derive Client Key");
ret = Tls13DeriveKey(ssl, &key_dig[i], ssl->specs.key_size,
ssl->clientSecret, writeKeyLabel,
WRITE_KEY_LABEL_SZ, ssl->specs.mac_algorithm, 0,
WOLFSSL_CLIENT_END);
if (ret != 0)
goto end;
i += ssl->specs.key_size;
}
if (provision & PROVISION_SERVER) {
/* Derive the server key. */
WOLFSSL_MSG("Derive Server Key");
ret = Tls13DeriveKey(ssl, &key_dig[i], ssl->specs.key_size,
ssl->serverSecret, writeKeyLabel,
WRITE_KEY_LABEL_SZ, ssl->specs.mac_algorithm, 0,
WOLFSSL_SERVER_END);
if (ret != 0)
goto end;
i += ssl->specs.key_size;
}
if (provision & PROVISION_CLIENT) {
/* Derive the client IV. */
WOLFSSL_MSG("Derive Client IV");
ret = Tls13DeriveKey(ssl, &key_dig[i], ssl->specs.iv_size,
ssl->clientSecret, writeIVLabel,
WRITE_IV_LABEL_SZ, ssl->specs.mac_algorithm, 0,
WOLFSSL_CLIENT_END);
if (ret != 0)
goto end;
i += ssl->specs.iv_size;
}
if (provision & PROVISION_SERVER) {
/* Derive the server IV. */
WOLFSSL_MSG("Derive Server IV");
ret = Tls13DeriveKey(ssl, &key_dig[i], ssl->specs.iv_size,
ssl->serverSecret, writeIVLabel,
WRITE_IV_LABEL_SZ, ssl->specs.mac_algorithm, 0,
WOLFSSL_SERVER_END);
if (ret != 0)
goto end;
/* Server IV is the last key material written to key_dig, so i is not
* advanced here; the whole buffer is zeroed at end regardless. */
}
/* Store keys and IVs but don't activate them. */
ret = StoreKeys(ssl, key_dig, provision);
ret = Tls13DeriveRecordKeys(ssl, provision);
#ifdef WOLFSSL_DTLS13
if (ret != 0)
@@ -1698,9 +1731,6 @@ int DeriveTls13Keys(WOLFSSL* ssl, int secret, int side, int store)
if (ssl->options.dtls) {
w64wrapper epochNumber;
ret = Dtls13DeriveSnKeys(ssl, provision);
if (ret != 0)
goto end;
switch (secret) {
case early_data_key:
@@ -1738,15 +1768,6 @@ int DeriveTls13Keys(WOLFSSL* ssl, int secret, int side, int store)
#endif /* WOLFSSL_DTLS13 */
end:
/* Zero the whole key_dig buffer (not just the i bytes derived) so no
* key-schedule material can linger in the unused tail. */
ForceZero(key_dig, MAX_PRF_DIG);
#ifdef WOLFSSL_SMALL_STACK
XFREE(key_dig, ssl->heap, DYNAMIC_TYPE_DIGEST);
#elif defined(WOLFSSL_CHECK_MEM_ZERO)
wc_MemZero_Check(key_dig, MAX_PRF_DIG);
#endif
if (ret != 0) {
WOLFSSL_ERROR_VERBOSE(ret);
}

View File

@@ -4083,6 +4083,7 @@ WOLFSSL_LOCAL int DeriveHandshakeSecret(WOLFSSL* ssl);
#define DeriveTls13Keys wolfSSL_DeriveTls13Keys
#endif
WOLFSSL_TEST_VIS int DeriveTls13Keys(WOLFSSL* ssl, int secret, int side, int store);
WOLFSSL_LOCAL int Tls13DeriveRecordKeys(WOLFSSL* ssl, int provision);
WOLFSSL_LOCAL int DeriveMasterSecret(WOLFSSL* ssl);
WOLFSSL_LOCAL int DeriveResumptionPSK(WOLFSSL* ssl, byte* nonce, byte nonceLen, byte* secret);
WOLFSSL_LOCAL int DeriveResumptionSecret(WOLFSSL* ssl, byte* key);