forked from wolfSSL/wolfssl
dtls13: record number encryption and decryption
This commit is contained in:
committed by
David Garske
parent
60834ba516
commit
de04973051
189
src/dtls13.c
189
src/dtls13.c
@@ -27,8 +27,17 @@
|
||||
|
||||
#ifdef WOLFSSL_DTLS13
|
||||
|
||||
#include <wolfssl/ssl.h>
|
||||
#include <wolfssl/error-ssl.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)
|
||||
{
|
||||
@@ -70,4 +79,182 @@ WOLFSSL_METHOD* wolfDTLSv1_3_server_method(void)
|
||||
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 */
|
||||
|
@@ -2589,6 +2589,14 @@ void InitCiphers(WOLFSSL* ssl)
|
||||
#ifdef HAVE_ONE_TIME_AUTH
|
||||
ssl->auth.setup = 0;
|
||||
#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->decrypt.hmac, ssl->heap, DYNAMIC_TYPE_CIPHER);
|
||||
#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 */
|
||||
}
|
||||
|
||||
|
||||
|
@@ -2959,6 +2959,11 @@ int SetKeysSide(WOLFSSL* ssl, enum encrypt_side side)
|
||||
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 WOLFSSL_DTLS
|
||||
if (ret == 0 && ssl->options.dtls) {
|
||||
|
33
src/tls13.c
33
src/tls13.c
@@ -153,6 +153,11 @@
|
||||
/* The protocol label for TLS v1.3. */
|
||||
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.
|
||||
*
|
||||
* ssl The SSL/TLS object.
|
||||
@@ -234,7 +239,15 @@ static int DeriveKeyMsg(WOLFSSL* ssl, byte* output, int outputLen,
|
||||
protocol = tls13ProtocolLabel;
|
||||
protocolLen = TLS13_PROTOCOL_LABEL_SZ;
|
||||
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:
|
||||
return VERSION_ERROR;
|
||||
}
|
||||
@@ -308,10 +321,16 @@ int Tls13DeriveKey(WOLFSSL* ssl, byte* output, int outputLen,
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
/* Only one protocol version defined at this time. */
|
||||
protocol = tls13ProtocolLabel;
|
||||
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)
|
||||
outputLen = hashSz;
|
||||
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. */
|
||||
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:
|
||||
#ifdef WOLFSSL_SMALL_STACK
|
||||
XFREE(key_dig, ssl->heap, DYNAMIC_TYPE_DIGEST);
|
||||
|
@@ -2242,6 +2242,11 @@ typedef struct Keys {
|
||||
byte aead_dec_imp_IV[AEAD_MAX_IMP_SZ];
|
||||
#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_lo;
|
||||
word32 sequence_number_hi;
|
||||
@@ -3314,6 +3319,16 @@ typedef struct Ciphers {
|
||||
#endif
|
||||
} 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
|
||||
/* Ciphers for one time authentication such as poly1305 */
|
||||
@@ -4496,6 +4511,11 @@ struct WOLFSSL {
|
||||
* (selected profiles - up to 16) */
|
||||
word16 dtlsSrtpId; /* DTLS-with-SRTP profile ID selected */
|
||||
#endif
|
||||
#ifdef WOLFSSL_DTLS13
|
||||
RecordNumberCiphers dtlsRecordNumberEncrypt;
|
||||
RecordNumberCiphers dtlsRecordNumberDecrypt;
|
||||
#endif /* WOLFSSL_DTLS13 */
|
||||
|
||||
#endif /* WOLFSSL_DTLS */
|
||||
#ifdef WOLFSSL_CALLBACKS
|
||||
TimeoutInfo timeoutInfo; /* info saved during handshake */
|
||||
@@ -5240,6 +5260,10 @@ WOLFSSL_LOCAL word32 nid2oid(int nid, int grp);
|
||||
|
||||
#ifdef WOLFSSL_DTLS13
|
||||
|
||||
WOLFSSL_LOCAL int Dtls13DeriveSnKeys(WOLFSSL* ssl, int provision);
|
||||
WOLFSSL_LOCAL int Dtls13SetRecordNumberKeys(WOLFSSL* ssl,
|
||||
enum encrypt_side side);
|
||||
|
||||
#endif /* WOLFSSL_DTLS13 */
|
||||
#ifdef WOLFSSL_STATIC_EPHEMERAL
|
||||
WOLFSSL_LOCAL int wolfSSL_StaticEphemeralKeyLoad(WOLFSSL* ssl, int keyAlgo, void* keyPtr);
|
||||
|
Reference in New Issue
Block a user