dtls13: record number encryption and decryption

This commit is contained in:
Marco Oliverio
2022-05-20 09:59:29 +02:00
committed by David Garske
parent 60834ba516
commit de04973051
5 changed files with 280 additions and 2 deletions

View File

@@ -27,8 +27,17 @@
#ifdef WOLFSSL_DTLS13 #ifdef WOLFSSL_DTLS13
#include <wolfssl/ssl.h> #include <wolfssl/error-ssl.h>
#include <wolfssl/internal.h> #include <wolfssl/internal.h>
#include <wolfssl/ssl.h>
#include <wolfssl/wolfcrypt/aes.h>
#ifdef NO_INLINE
#include <wolfssl/wolfcrypt/misc.h>
#else
#define WOLFSSL_MISC_INCLUDED
#include <wolfcrypt/src/misc.c>
#endif
WOLFSSL_METHOD* wolfDTLSv1_3_client_method_ex(void* heap) WOLFSSL_METHOD* wolfDTLSv1_3_client_method_ex(void* heap)
{ {
@@ -70,4 +79,182 @@ WOLFSSL_METHOD* wolfDTLSv1_3_server_method(void)
return wolfDTLSv1_3_server_method_ex(NULL); return wolfDTLSv1_3_server_method_ex(NULL);
} }
#define SN_LABEL_SZ 2
static const byte snLabel[SN_LABEL_SZ + 1] = "sn";
/**
* Dtls13DeriveSnKeys() - derive the key used to encrypt the record number
* @ssl: ssl object
* @provision: which side (CLIENT or SERVER) to provision
*/
int Dtls13DeriveSnKeys(WOLFSSL* ssl, int provision)
{
byte key_dig[MAX_PRF_DIG];
int ret = 0;
if (provision & PROVISION_CLIENT) {
WOLFSSL_MSG("Derive SN Client key");
ret = Tls13DeriveKey(ssl, key_dig, ssl->specs.key_size,
ssl->clientSecret, snLabel, SN_LABEL_SZ, ssl->specs.mac_algorithm,
0);
if (ret != 0)
goto end;
XMEMCPY(ssl->keys.client_sn_key, key_dig, ssl->specs.key_size);
}
if (provision & PROVISION_SERVER) {
WOLFSSL_MSG("Derive SN Server key");
ret = Tls13DeriveKey(ssl, key_dig, ssl->specs.key_size,
ssl->serverSecret, snLabel, SN_LABEL_SZ, ssl->specs.mac_algorithm,
0);
if (ret != 0)
goto end;
XMEMCPY(ssl->keys.server_sn_key, key_dig, ssl->specs.key_size);
}
end:
ForceZero(key_dig, MAX_PRF_DIG);
return ret;
}
static int Dtls13InitAesCipher(WOLFSSL* ssl, RecordNumberCiphers* cipher,
const byte* key, word16 keySize)
{
int ret;
if (cipher->aes == NULL) {
cipher->aes =
(Aes*)XMALLOC(sizeof(Aes), ssl->heap, DYNAMIC_TYPE_CIPHER);
if (cipher->aes == NULL)
return MEMORY_E;
}
else {
wc_AesFree(cipher->aes);
}
XMEMSET(cipher->aes, 0, sizeof(*cipher->aes));
ret = wc_AesInit(cipher->aes, ssl->heap, INVALID_DEVID);
if (ret != 0)
return ret;
return wc_AesSetKey(cipher->aes, key, keySize, NULL, AES_ENCRYPTION);
}
#ifdef HAVE_CHACHA
static int Dtls13InitChaChaCipher(RecordNumberCiphers* c, byte* key,
word16 keySize, void* heap)
{
(void)heap;
if (c->chacha == NULL) {
c->chacha = (ChaCha*)XMALLOC(sizeof(ChaCha), heap, DYNAMIC_TYPE_CIPHER);
if (c->chacha == NULL)
return MEMORY_E;
}
return wc_Chacha_SetKey(c->chacha, key, keySize);
}
#endif /* HAVE_CHACHA */
int Dtls13SetRecordNumberKeys(WOLFSSL* ssl, enum encrypt_side side)
{
RecordNumberCiphers* enc = NULL;
RecordNumberCiphers* dec = NULL;
byte *encKey, *decKey;
int ret;
if (ssl == NULL) {
return BAD_FUNC_ARG;
}
switch (side) {
case ENCRYPT_SIDE_ONLY:
enc = &ssl->dtlsRecordNumberEncrypt;
break;
case DECRYPT_SIDE_ONLY:
dec = &ssl->dtlsRecordNumberDecrypt;
break;
case ENCRYPT_AND_DECRYPT_SIDE:
enc = &ssl->dtlsRecordNumberEncrypt;
dec = &ssl->dtlsRecordNumberDecrypt;
break;
}
if (enc) {
if (ssl->options.side == WOLFSSL_CLIENT_END)
encKey = ssl->keys.client_sn_key;
else
encKey = ssl->keys.server_sn_key;
}
if (dec) {
if (ssl->options.side == WOLFSSL_CLIENT_END)
decKey = ssl->keys.server_sn_key;
else
decKey = ssl->keys.client_sn_key;
}
/* DTLSv1.3 supports only AEAD algorithm. */
#if defined(BUILD_AESGCM) || defined(HAVE_AESCCM)
if (ssl->specs.bulk_cipher_algorithm == wolfssl_aes_gcm ||
ssl->specs.bulk_cipher_algorithm == wolfssl_aes_ccm) {
if (enc) {
ret = Dtls13InitAesCipher(ssl, enc, encKey, ssl->specs.key_size);
if (ret != 0)
return ret;
#ifdef WOLFSSL_DEBUG_TLS
WOLFSSL_MSG("Provisioning AES Record Number enc key:");
WOLFSSL_BUFFER(encKey, ssl->specs.key_size);
#endif /* WOLFSSL_DEBUG_TLS */
}
if (dec) {
ret = Dtls13InitAesCipher(ssl, dec, decKey, ssl->specs.key_size);
if (ret != 0)
return ret;
#ifdef WOLFSSL_DEBUG_TLS
WOLFSSL_MSG("Provisioning AES Record Number dec key:");
WOLFSSL_BUFFER(decKey, ssl->specs.key_size);
#endif /* WOLFSSL_DEBUG_TLS */
}
return 0;
}
#endif /* BUILD_AESGCM || HAVE_AESCCM */
#ifdef HAVE_CHACHA
if (ssl->specs.bulk_cipher_algorithm == wolfssl_chacha) {
if (enc) {
ret = Dtls13InitChaChaCipher(enc, encKey, ssl->specs.key_size,
ssl->heap);
if (ret != 0)
return ret;
#ifdef WOLFSSL_DEBUG_TLS
WOLFSSL_MSG("Provisioning CHACHA Record Number enc key:");
WOLFSSL_BUFFER(encKey, ssl->specs.key_size);
#endif /* WOLFSSL_DEBUG_TLS */
}
if (dec) {
ret = Dtls13InitChaChaCipher(dec, decKey, ssl->specs.key_size,
ssl->heap);
if (ret != 0)
return ret;
#ifdef WOLFSSL_DEBUG_TLS
WOLFSSL_MSG("Provisioning CHACHA Record Number dec key:");
WOLFSSL_BUFFER(decKey, ssl->specs.key_size);
#endif /* WOLFSSL_DEBUG_TLS */
}
return 0;
}
#endif /* HAVE_CHACHA */
return NOT_COMPILED_IN;
}
#endif /* WOLFSSL_DTLS13 */ #endif /* WOLFSSL_DTLS13 */

View File

@@ -2589,6 +2589,14 @@ void InitCiphers(WOLFSSL* ssl)
#ifdef HAVE_ONE_TIME_AUTH #ifdef HAVE_ONE_TIME_AUTH
ssl->auth.setup = 0; ssl->auth.setup = 0;
#endif #endif
#ifdef WOLFSSL_DTLS13
XMEMSET(&ssl->dtlsRecordNumberEncrypt, 0,
sizeof(ssl->dtlsRecordNumberEncrypt));
XMEMSET(&ssl->dtlsRecordNumberDecrypt, 0,
sizeof(ssl->dtlsRecordNumberEncrypt));
#endif /* WOLFSSL_DTLS13 */
} }
@@ -2642,6 +2650,29 @@ void FreeCiphers(WOLFSSL* ssl)
XFREE(ssl->encrypt.hmac, ssl->heap, DYNAMIC_TYPE_CIPHER); XFREE(ssl->encrypt.hmac, ssl->heap, DYNAMIC_TYPE_CIPHER);
XFREE(ssl->decrypt.hmac, ssl->heap, DYNAMIC_TYPE_CIPHER); XFREE(ssl->decrypt.hmac, ssl->heap, DYNAMIC_TYPE_CIPHER);
#endif #endif
#ifdef WOLFSSL_DTLS13
#ifdef BUILD_AES
if (ssl->dtlsRecordNumberEncrypt.aes != NULL) {
wc_AesFree(ssl->dtlsRecordNumberEncrypt.aes);
XFREE(ssl->dtlsRecordNumberEncrypt.aes, ssl->heap, DYNAMIC_TYPE_CIPHER);
ssl->dtlsRecordNumberEncrypt.aes = NULL;
}
if (ssl->dtlsRecordNumberDecrypt.aes != NULL) {
wc_AesFree(ssl->dtlsRecordNumberDecrypt.aes);
XFREE(ssl->dtlsRecordNumberDecrypt.aes, ssl->heap, DYNAMIC_TYPE_CIPHER);
ssl->dtlsRecordNumberDecrypt.aes = NULL;
}
#endif /* BUILD_AES */
#ifdef HAVE_CHACHA
XFREE(ssl->dtlsRecordNumberEncrypt.chacha,
ssl->heap, DYNAMIC_TYPE_CIPHER);
XFREE(ssl->dtlsRecordNumberDecrypt.chacha,
ssl->heap, DYNAMIC_TYPE_CIPHER);
ssl->dtlsRecordNumberEncrypt.chacha = NULL;
ssl->dtlsRecordNumberDecrypt.chacha = NULL;
#endif /* HAVE_CHACHA */
#endif /* WOLFSSL_DTLS13 */
} }

View File

@@ -2959,6 +2959,11 @@ int SetKeysSide(WOLFSSL* ssl, enum encrypt_side side)
ssl->heap, ssl->devId, ssl->rng, ssl->options.tls1_3); ssl->heap, ssl->devId, ssl->rng, ssl->options.tls1_3);
} }
#ifdef WOLFSSL_DTLS13
if (ret == 0 && ssl->options.dtls && IsAtLeastTLSv1_3(ssl->version))
ret = Dtls13SetRecordNumberKeys(ssl, side);
#endif /* WOLFSSL_DTLS13 */
#ifdef HAVE_SECURE_RENEGOTIATION #ifdef HAVE_SECURE_RENEGOTIATION
#ifdef WOLFSSL_DTLS #ifdef WOLFSSL_DTLS
if (ret == 0 && ssl->options.dtls) { if (ret == 0 && ssl->options.dtls) {

View File

@@ -153,6 +153,11 @@
/* The protocol label for TLS v1.3. */ /* The protocol label for TLS v1.3. */
static const byte tls13ProtocolLabel[TLS13_PROTOCOL_LABEL_SZ + 1] = "tls13 "; static const byte tls13ProtocolLabel[TLS13_PROTOCOL_LABEL_SZ + 1] = "tls13 ";
#ifdef WOLFSSL_DTLS13
#define DTLS13_PROTOCOL_LABEL_SZ 6
static const byte dtls13ProtocolLabel[DTLS13_PROTOCOL_LABEL_SZ + 1] = "dtls13";
#endif /* WOLFSSL_DTLS13 */
/* Derive a key from a message. /* Derive a key from a message.
* *
* ssl The SSL/TLS object. * ssl The SSL/TLS object.
@@ -234,7 +239,15 @@ static int DeriveKeyMsg(WOLFSSL* ssl, byte* output, int outputLen,
protocol = tls13ProtocolLabel; protocol = tls13ProtocolLabel;
protocolLen = TLS13_PROTOCOL_LABEL_SZ; protocolLen = TLS13_PROTOCOL_LABEL_SZ;
break; break;
#ifdef WOLFSSL_DTLS13
case DTLSv1_3_MINOR:
if (!ssl->options.dtls)
return VERSION_ERROR;
protocol = dtls13ProtocolLabel;
protocolLen = DTLS13_PROTOCOL_LABEL_SZ;
break;
#endif /* WOLFSSL_DTLS13 */
default: default:
return VERSION_ERROR; return VERSION_ERROR;
} }
@@ -308,10 +321,16 @@ int Tls13DeriveKey(WOLFSSL* ssl, byte* output, int outputLen,
if (ret != 0) if (ret != 0)
return ret; return ret;
/* Only one protocol version defined at this time. */
protocol = tls13ProtocolLabel; protocol = tls13ProtocolLabel;
protocolLen = TLS13_PROTOCOL_LABEL_SZ; protocolLen = TLS13_PROTOCOL_LABEL_SZ;
#ifdef WOLFSSL_DTLS13
if (ssl->options.dtls) {
protocol = dtls13ProtocolLabel;
protocolLen = DTLS13_PROTOCOL_LABEL_SZ;
}
#endif /* WOLFSSL_DTLS13 */
if (outputLen == -1) if (outputLen == -1)
outputLen = hashSz; outputLen = hashSz;
if (includeMsgs) if (includeMsgs)
@@ -1263,6 +1282,18 @@ int DeriveTls13Keys(WOLFSSL* ssl, int secret, int side, int store)
/* Store keys and IVs but don't activate them. */ /* Store keys and IVs but don't activate them. */
ret = StoreKeys(ssl, key_dig, provision); ret = StoreKeys(ssl, key_dig, provision);
#ifdef WOLFSSL_DTLS13
if (ret != 0)
goto end;
if (ssl->options.dtls) {
ret = Dtls13DeriveSnKeys(ssl, provision);
if (ret != 0)
return ret;
}
#endif /* WOLFSSL_DTLS13 */
end: end:
#ifdef WOLFSSL_SMALL_STACK #ifdef WOLFSSL_SMALL_STACK
XFREE(key_dig, ssl->heap, DYNAMIC_TYPE_DIGEST); XFREE(key_dig, ssl->heap, DYNAMIC_TYPE_DIGEST);

View File

@@ -2242,6 +2242,11 @@ typedef struct Keys {
byte aead_dec_imp_IV[AEAD_MAX_IMP_SZ]; byte aead_dec_imp_IV[AEAD_MAX_IMP_SZ];
#endif #endif
#ifdef WOLFSSL_DTLS13
byte client_sn_key[MAX_SYM_KEY_SIZE];
byte server_sn_key[MAX_SYM_KEY_SIZE];
#endif /* WOLFSSL_DTLS13 */
word32 peer_sequence_number_hi; word32 peer_sequence_number_hi;
word32 peer_sequence_number_lo; word32 peer_sequence_number_lo;
word32 sequence_number_hi; word32 sequence_number_hi;
@@ -3314,6 +3319,16 @@ typedef struct Ciphers {
#endif #endif
} Ciphers; } Ciphers;
#ifdef WOLFSSL_DTLS13
typedef struct RecordNumberCiphers {
#if defined(BUILD_AES) || defined(BUILD_AESGCM)
Aes *aes;
#endif /* BUILD_AES || BUILD_AESGCM */
#ifdef HAVE_CHACHA
ChaCha *chacha;
#endif
} RecordNumberCiphers;
#endif /* WOLFSSL_DTLS13 */
#ifdef HAVE_ONE_TIME_AUTH #ifdef HAVE_ONE_TIME_AUTH
/* Ciphers for one time authentication such as poly1305 */ /* Ciphers for one time authentication such as poly1305 */
@@ -4496,6 +4511,11 @@ struct WOLFSSL {
* (selected profiles - up to 16) */ * (selected profiles - up to 16) */
word16 dtlsSrtpId; /* DTLS-with-SRTP profile ID selected */ word16 dtlsSrtpId; /* DTLS-with-SRTP profile ID selected */
#endif #endif
#ifdef WOLFSSL_DTLS13
RecordNumberCiphers dtlsRecordNumberEncrypt;
RecordNumberCiphers dtlsRecordNumberDecrypt;
#endif /* WOLFSSL_DTLS13 */
#endif /* WOLFSSL_DTLS */ #endif /* WOLFSSL_DTLS */
#ifdef WOLFSSL_CALLBACKS #ifdef WOLFSSL_CALLBACKS
TimeoutInfo timeoutInfo; /* info saved during handshake */ TimeoutInfo timeoutInfo; /* info saved during handshake */
@@ -5240,6 +5260,10 @@ WOLFSSL_LOCAL word32 nid2oid(int nid, int grp);
#ifdef WOLFSSL_DTLS13 #ifdef WOLFSSL_DTLS13
WOLFSSL_LOCAL int Dtls13DeriveSnKeys(WOLFSSL* ssl, int provision);
WOLFSSL_LOCAL int Dtls13SetRecordNumberKeys(WOLFSSL* ssl,
enum encrypt_side side);
#endif /* WOLFSSL_DTLS13 */ #endif /* WOLFSSL_DTLS13 */
#ifdef WOLFSSL_STATIC_EPHEMERAL #ifdef WOLFSSL_STATIC_EPHEMERAL
WOLFSSL_LOCAL int wolfSSL_StaticEphemeralKeyLoad(WOLFSSL* ssl, int keyAlgo, void* keyPtr); WOLFSSL_LOCAL int wolfSSL_StaticEphemeralKeyLoad(WOLFSSL* ssl, int keyAlgo, void* keyPtr);