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:
171
src/tls13.c
171
src/tls13.c
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user