소스 검색

dtls13: record number encryption and decryption

Marco Oliverio 2 년 전
부모
커밋
de04973051
5개의 변경된 파일280개의 추가작업 그리고 2개의 파일을 삭제
  1. 188 1
      src/dtls13.c
  2. 31 0
      src/internal.c
  3. 5 0
      src/keys.c
  4. 32 1
      src/tls13.c
  5. 24 0
      wolfssl/internal.h

+ 188 - 1
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 */

+ 31 - 0
src/internal.c

@@ -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 */
 }
 
 

+ 5 - 0
src/keys.c

@@ -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) {

+ 32 - 1
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);

+ 24 - 0
wolfssl/internal.h

@@ -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);