]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
Added the CHACHA20-POLY1305 ciphersuites (with random IDs)
authorNikos Mavrogiannopoulos <nmav@gnutls.org>
Sat, 28 Mar 2015 09:40:47 +0000 (10:40 +0100)
committerNikos Mavrogiannopoulos <nmav@gnutls.org>
Sat, 28 Mar 2015 09:53:17 +0000 (10:53 +0100)
lib/algorithms.h
lib/algorithms/ciphersuites.c
lib/gnutls_cipher.c
lib/gnutls_constate.c
lib/gnutls_int.h

index 97e6935de204aab2981f66376472033bf5fd0b24..1ac400125592ee0cb525082456bfa7fabb3acb34 100644 (file)
@@ -179,6 +179,8 @@ _gnutls_cipher_suite_get_id(gnutls_kx_algorithm_t kx_algorithm,
                            gnutls_mac_algorithm_t mac_algorithm,
                            uint8_t suite[2]);
 
+const gnutls_cipher_suite_entry_st *ciphersuite_to_entry(const uint8_t suite[2]);
+
 /* Functions for ciphers. */
 const cipher_entry_st *cipher_to_entry(gnutls_cipher_algorithm_t c);
 
index bfd93e5f8011ebe124bdcb2aef0a01afbf04e13a..d0f3c77f3c933e9ea32e4299f0990185deb19cb9 100644 (file)
 
 /* Cipher SUITES */
 #define ENTRY( name, block_algorithm, kx_algorithm, mac_algorithm, min_version, dtls_version ) \
-       { #name, name, block_algorithm, kx_algorithm, mac_algorithm, min_version, dtls_version, GNUTLS_MAC_SHA256}
+       { #name, name, block_algorithm, kx_algorithm, mac_algorithm, min_version, dtls_version, GNUTLS_MAC_SHA256, NONCE_IS_SENT}
 #define ENTRY_PRF( name, block_algorithm, kx_algorithm, mac_algorithm, min_version, dtls_version, prf ) \
-       { #name, name, block_algorithm, kx_algorithm, mac_algorithm, min_version, dtls_version, prf}
-
-typedef struct {
-       const char *name;
-       const uint8_t id[2];
-       gnutls_cipher_algorithm_t block_algorithm;
-       gnutls_kx_algorithm_t kx_algorithm;
-       gnutls_mac_algorithm_t mac_algorithm;
-       gnutls_protocol_t min_version;  /* this cipher suite is supported
-                                        * from 'version' and above;
-                                        */
-       gnutls_protocol_t min_dtls_version;     /* DTLS min version */
-       gnutls_mac_algorithm_t prf;
-} gnutls_cipher_suite_entry;
+       { #name, name, block_algorithm, kx_algorithm, mac_algorithm, min_version, dtls_version, prf, NONCE_IS_SENT}
+#define ENTRY_CNONCE( name, block_algorithm, kx_algorithm, mac_algorithm, min_version, dtls_version ) \
+       { #name, name, block_algorithm, kx_algorithm, mac_algorithm, min_version, dtls_version, GNUTLS_MAC_SHA256, NONCE_IS_COUNTER}
 
 /* RSA with NULL cipher and MD5 MAC
  * for test purposes.
@@ -116,6 +105,16 @@ typedef struct {
 #define GNUTLS_DH_ANON_AES_128_CBC_SHA256 { 0x00, 0x6C }
 #define GNUTLS_DH_ANON_AES_256_CBC_SHA256 { 0x00, 0x6D }
 
+/* draft-mavrogiannopoulos-chacha-tls-04 */
+#define GNUTLS_RSA_CHACHA20_POLY1305           { 0xFF, 0x30 }
+#define GNUTLS_ECDHE_RSA_CHACHA20_POLY1305      { 0xFF, 0x31 }
+#define GNUTLS_ECDHE_ECDSA_CHACHA20_POLY1305   { 0xFF, 0x32 }
+#define GNUTLS_DHE_RSA_CHACHA20_POLY1305       { 0xFF, 0x33 }
+#define GNUTLS_DHE_PSK_CHACHA20_POLY1305       { 0xFF, 0x34 }
+#define GNUTLS_PSK_CHACHA20_POLY1305           { 0xFF, 0x35 }
+#define GNUTLS_ECDHE_PSK_CHACHA20_POLY1305     { 0xFF, 0x36 }
+#define GNUTLS_RSA_PSK_CHACHA20_POLY1305       { 0xFF, 0x37 }
+
 /* PSK (not in TLS 1.0)
  * draft-ietf-tls-psk:
  */
@@ -308,12 +307,12 @@ typedef struct {
 #define GNUTLS_ECDHE_PSK_NULL_SHA256 { 0xC0, 0x3A }
 #define GNUTLS_ECDHE_PSK_NULL_SHA384 { 0xC0, 0x3B }
 
-#define CIPHER_SUITES_COUNT (sizeof(cs_algorithms)/sizeof(gnutls_cipher_suite_entry)-1)
+#define CIPHER_SUITES_COUNT (sizeof(cs_algorithms)/sizeof(gnutls_cipher_suite_entry_st)-1)
 
 /* The following is a potential list of ciphersuites. For the options to be
  * available, the ciphers and MACs must be available to gnutls as well.
  */
-static const gnutls_cipher_suite_entry cs_algorithms[] = {
+static const gnutls_cipher_suite_entry_st cs_algorithms[] = {
        /* RSA-NULL */
        ENTRY(GNUTLS_RSA_NULL_MD5,
              GNUTLS_CIPHER_NULL,
@@ -391,6 +390,10 @@ static const gnutls_cipher_suite_entry cs_algorithms[] = {
                  GNUTLS_CIPHER_CAMELLIA_256_GCM, GNUTLS_KX_RSA,
                  GNUTLS_MAC_AEAD, GNUTLS_TLS1_2,
                  GNUTLS_DTLS1_2, GNUTLS_MAC_SHA384),
+       ENTRY_CNONCE(GNUTLS_RSA_CHACHA20_POLY1305,
+               GNUTLS_CIPHER_CHACHA20_POLY1305, GNUTLS_KX_RSA,
+               GNUTLS_MAC_AEAD, GNUTLS_TLS1_2,
+               GNUTLS_DTLS1_2),
 
 /* CCM */
        ENTRY(GNUTLS_RSA_AES_128_CCM,
@@ -419,22 +422,6 @@ static const gnutls_cipher_suite_entry cs_algorithms[] = {
              GNUTLS_MAC_AEAD, GNUTLS_TLS1_2,
              GNUTLS_DTLS1_2),
 
-       ENTRY(GNUTLS_PSK_AES_128_CCM,
-             GNUTLS_CIPHER_AES_128_CCM, GNUTLS_KX_PSK,
-             GNUTLS_MAC_AEAD, GNUTLS_TLS1_2,
-             GNUTLS_DTLS1_2),
-       ENTRY(GNUTLS_PSK_AES_256_CCM,
-             GNUTLS_CIPHER_AES_256_CCM, GNUTLS_KX_PSK,
-             GNUTLS_MAC_AEAD, GNUTLS_TLS1_2,
-             GNUTLS_DTLS1_2),
-       ENTRY(GNUTLS_DHE_PSK_AES_128_CCM,
-             GNUTLS_CIPHER_AES_128_CCM, GNUTLS_KX_DHE_PSK,
-             GNUTLS_MAC_AEAD, GNUTLS_TLS1_2,
-             GNUTLS_DTLS1_2),
-       ENTRY(GNUTLS_DHE_PSK_AES_256_CCM,
-             GNUTLS_CIPHER_AES_256_CCM, GNUTLS_KX_DHE_PSK,
-             GNUTLS_MAC_AEAD, GNUTLS_TLS1_2,
-             GNUTLS_DTLS1_2),
 
        /* DHE_DSS */
 #ifdef ENABLE_DHE
@@ -559,6 +546,11 @@ static const gnutls_cipher_suite_entry cs_algorithms[] = {
                  GNUTLS_CIPHER_CAMELLIA_256_GCM, GNUTLS_KX_DHE_RSA,
                  GNUTLS_MAC_AEAD, GNUTLS_TLS1_2,
                  GNUTLS_DTLS1_2, GNUTLS_MAC_SHA384),
+
+       ENTRY_CNONCE(GNUTLS_DHE_RSA_CHACHA20_POLY1305,
+             GNUTLS_CIPHER_CHACHA20_POLY1305, GNUTLS_KX_DHE_RSA,
+             GNUTLS_MAC_AEAD, GNUTLS_TLS1_2, GNUTLS_DTLS1_2),
+
 #endif                         /* DHE */
 #ifdef ENABLE_ECDHE
 /* ECC-RSA */
@@ -672,6 +664,16 @@ static const gnutls_cipher_suite_entry cs_algorithms[] = {
                  GNUTLS_CIPHER_CAMELLIA_256_GCM, GNUTLS_KX_ECDHE_RSA,
                  GNUTLS_MAC_AEAD, GNUTLS_TLS1_2,
                  GNUTLS_DTLS1_2, GNUTLS_MAC_SHA384),
+
+       ENTRY_CNONCE(GNUTLS_ECDHE_RSA_CHACHA20_POLY1305,
+             GNUTLS_CIPHER_CHACHA20_POLY1305, GNUTLS_KX_ECDHE_RSA,
+             GNUTLS_MAC_AEAD, GNUTLS_TLS1_2,
+             GNUTLS_DTLS1_2),
+
+       ENTRY_CNONCE(GNUTLS_ECDHE_ECDSA_CHACHA20_POLY1305,
+             GNUTLS_CIPHER_CHACHA20_POLY1305, GNUTLS_KX_ECDHE_RSA,
+             GNUTLS_MAC_AEAD, GNUTLS_TLS1_2,
+             GNUTLS_DTLS1_2),
 #endif
 #ifdef ENABLE_PSK
        /* ECC - PSK */
@@ -911,6 +913,38 @@ static const gnutls_cipher_suite_entry cs_algorithms[] = {
                  GNUTLS_CIPHER_CAMELLIA_256_GCM, GNUTLS_KX_DHE_PSK,
                  GNUTLS_MAC_AEAD, GNUTLS_TLS1_2,
                  GNUTLS_DTLS1_2, GNUTLS_MAC_SHA384),
+
+       ENTRY(GNUTLS_PSK_AES_128_CCM,
+             GNUTLS_CIPHER_AES_128_CCM, GNUTLS_KX_PSK,
+             GNUTLS_MAC_AEAD, GNUTLS_TLS1_2,
+             GNUTLS_DTLS1_2),
+       ENTRY(GNUTLS_PSK_AES_256_CCM,
+             GNUTLS_CIPHER_AES_256_CCM, GNUTLS_KX_PSK,
+             GNUTLS_MAC_AEAD, GNUTLS_TLS1_2,
+             GNUTLS_DTLS1_2),
+       ENTRY(GNUTLS_DHE_PSK_AES_128_CCM,
+             GNUTLS_CIPHER_AES_128_CCM, GNUTLS_KX_DHE_PSK,
+             GNUTLS_MAC_AEAD, GNUTLS_TLS1_2,
+             GNUTLS_DTLS1_2),
+       ENTRY(GNUTLS_DHE_PSK_AES_256_CCM,
+             GNUTLS_CIPHER_AES_256_CCM, GNUTLS_KX_DHE_PSK,
+             GNUTLS_MAC_AEAD, GNUTLS_TLS1_2,
+             GNUTLS_DTLS1_2),
+       ENTRY_CNONCE(GNUTLS_DHE_PSK_CHACHA20_POLY1305,
+             GNUTLS_CIPHER_CHACHA20_POLY1305, GNUTLS_KX_DHE_PSK,
+             GNUTLS_MAC_AEAD, GNUTLS_TLS1_2, GNUTLS_DTLS1_2),
+       ENTRY_CNONCE(GNUTLS_ECDHE_PSK_CHACHA20_POLY1305,
+             GNUTLS_CIPHER_CHACHA20_POLY1305, GNUTLS_KX_ECDHE_PSK,
+             GNUTLS_MAC_AEAD, GNUTLS_TLS1_2, GNUTLS_DTLS1_2),
+
+       ENTRY_CNONCE(GNUTLS_RSA_PSK_CHACHA20_POLY1305,
+             GNUTLS_CIPHER_CHACHA20_POLY1305, GNUTLS_KX_RSA_PSK,
+             GNUTLS_MAC_AEAD, GNUTLS_TLS1_2, GNUTLS_DTLS1_2),
+
+       ENTRY_CNONCE(GNUTLS_PSK_CHACHA20_POLY1305,
+             GNUTLS_CIPHER_CHACHA20_POLY1305, GNUTLS_KX_PSK,
+             GNUTLS_MAC_AEAD, GNUTLS_TLS1_2, GNUTLS_DTLS1_2),
+
 #endif
 #ifdef ENABLE_ANON
        /* DH_ANON */
@@ -1042,11 +1076,13 @@ static const gnutls_cipher_suite_entry cs_algorithms[] = {
              GNUTLS_MAC_SHA1, GNUTLS_SSL3,
              GNUTLS_DTLS_VERSION_MIN),
 #endif
+
+
        {0, {0, 0}, 0, 0, 0, 0, 0, 0}
 };
 
 #define CIPHER_SUITE_LOOP(b) { \
-        const gnutls_cipher_suite_entry *p; \
+        const gnutls_cipher_suite_entry_st *p; \
                 for(p = cs_algorithms; p->name != NULL; p++) { b ; } }
 
 #define CIPHER_SUITE_ALG_LOOP(a, suite) \
@@ -1054,6 +1090,12 @@ static const gnutls_cipher_suite_entry cs_algorithms[] = {
 
 
 /* Cipher Suite's functions */
+const gnutls_cipher_suite_entry_st *ciphersuite_to_entry(const uint8_t suite[2])
+{
+       CIPHER_SUITE_ALG_LOOP(return p, suite);
+       return NULL;
+}
+
 const cipher_entry_st *_gnutls_cipher_suite_get_cipher_algo(const uint8_t
                                                            suite[2])
 {
@@ -1101,12 +1143,12 @@ const char *_gnutls_cipher_suite_get_name(const uint8_t suite[2])
 }
 
 
-static const gnutls_cipher_suite_entry
+static const gnutls_cipher_suite_entry_st
     *cipher_suite_get(gnutls_kx_algorithm_t kx_algorithm,
                      gnutls_cipher_algorithm_t cipher_algorithm,
                      gnutls_mac_algorithm_t mac_algorithm)
 {
-       const gnutls_cipher_suite_entry *ret = NULL;
+       const gnutls_cipher_suite_entry_st *ret = NULL;
 
        CIPHER_SUITE_LOOP(
                if (kx_algorithm == p->kx_algorithm &&
@@ -1230,7 +1272,7 @@ _gnutls_remove_unwanted_ciphersuites(gnutls_session_t session,
        int alg_size = MAX_ALGOS;
        uint8_t new_list[cipher_suites_size]; /* it's safe to use that size because it's provided by _gnutls_supported_ciphersuites() */
        int i, new_list_size = 0;
-       const gnutls_cipher_suite_entry *entry;
+       const gnutls_cipher_suite_entry_st *entry;
        const uint8_t *cp;
 
        /* if we should use a specific certificate, 
@@ -1354,7 +1396,7 @@ const char *gnutls_cipher_suite_get_name(gnutls_kx_algorithm_t
                                         gnutls_mac_algorithm_t
                                         mac_algorithm)
 {
-       const gnutls_cipher_suite_entry *ce;
+       const gnutls_cipher_suite_entry_st *ce;
 
        ce = cipher_suite_get(kx_algorithm, cipher_algorithm,
                              mac_algorithm);
@@ -1381,7 +1423,7 @@ _gnutls_cipher_suite_get_id(gnutls_kx_algorithm_t kx_algorithm,
                            gnutls_mac_algorithm_t mac_algorithm,
                            uint8_t suite[2])
 {
-       const gnutls_cipher_suite_entry *ce;
+       const gnutls_cipher_suite_entry_st *ce;
 
        ce = cipher_suite_get(kx_algorithm, cipher_algorithm,
                              mac_algorithm);
@@ -1470,7 +1512,7 @@ _gnutls_supported_ciphersuites(gnutls_session_t session,
 {
 
        unsigned int i, ret_count, j, z, k = 0;
-       const gnutls_cipher_suite_entry *ce;
+       const gnutls_cipher_suite_entry_st *ce;
        const version_entry_st *version = get_version(session);
        unsigned int is_dtls = IS_DTLS(session);
 
index c345ce23929600ca321cca2ed807d1f2316d561f..b98db6cae62f36ffe3e90c0e671d6d55b7c807b0 100644 (file)
@@ -236,12 +236,12 @@ calc_enc_length_block(gnutls_session_t session,
 inline static int
 calc_enc_length_stream(gnutls_session_t session, int data_size,
                       int hash_size, unsigned auth_cipher,
-                      unsigned exp_iv_size)
+                      unsigned exp_iv_size, unsigned send_nonce)
 {
        unsigned int length;
 
        length = data_size + hash_size;
-       if (auth_cipher)
+       if (auth_cipher && send_nonce)
                length += exp_iv_size;
 
        return length;
@@ -302,6 +302,7 @@ compressed_to_ciphertext(gnutls_session_t session,
        int explicit_iv = _gnutls_version_has_explicit_iv(ver);
        int auth_cipher =
            _gnutls_auth_cipher_is_aead(&params->write.cipher_state);
+       unsigned send_nonce = params->send_nonce;
        uint8_t nonce[MAX_CIPHER_BLOCK_SIZE];
        unsigned imp_iv_size = 0, exp_iv_size = 0;
        bool etm = 0;
@@ -339,7 +340,7 @@ compressed_to_ciphertext(gnutls_session_t session,
                pad = 0;
                length =
                    calc_enc_length_stream(session, compressed->size,
-                                          tag_size, auth_cipher, exp_iv_size);
+                                          tag_size, auth_cipher, exp_iv_size, send_nonce);
        }
 
        if (length < 0)
@@ -386,12 +387,14 @@ compressed_to_ciphertext(gnutls_session_t session,
                       UINT64DATA(params->write.sequence_number),
                       8);
 
-               /* copy the explicit part */
-               memcpy(data_ptr, &nonce[imp_iv_size],
-                      exp_iv_size);
+               if (send_nonce != 0) {
+                       /* copy the explicit part */
+                       memcpy(data_ptr, &nonce[imp_iv_size],
+                              exp_iv_size);
 
-               data_ptr += exp_iv_size;
-               cipher_data += exp_iv_size;
+                       data_ptr += exp_iv_size;
+                       cipher_data += exp_iv_size;
+               }
        }
 
        if (etm)
@@ -503,6 +506,7 @@ ciphertext_to_compressed(gnutls_session_t session,
        const version_entry_st *ver = get_version(session);
        unsigned int tag_size =
            _gnutls_auth_cipher_tag_len(&params->read.cipher_state);
+       unsigned send_nonce = params->send_nonce;
        unsigned int explicit_iv = _gnutls_version_has_explicit_iv(ver);
        unsigned imp_iv_size, exp_iv_size;
        unsigned cipher_type = _gnutls_cipher_type(params->cipher);
@@ -569,17 +573,22 @@ ciphertext_to_compressed(gnutls_session_t session,
                        return
                            gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
 
-               if (unlikely(ciphertext->size < tag_size + exp_iv_size))
+               if (unlikely(ciphertext->size < tag_size + (send_nonce!=0)?exp_iv_size:0))
                        return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
 
                memcpy(nonce, params->read.IV.data,
                       imp_iv_size);
-               memcpy(&nonce[imp_iv_size],
-                      ciphertext->data, exp_iv_size);
 
+               if (send_nonce != 0) {
+                       memcpy(&nonce[imp_iv_size],
+                              ciphertext->data, exp_iv_size);
 
-               ciphertext->data += exp_iv_size;
-               ciphertext->size -= exp_iv_size;
+                       ciphertext->data += exp_iv_size;
+                       ciphertext->size -= exp_iv_size;
+               } else {
+                       memcpy(&nonce[imp_iv_size],
+                              UINT64DATA(params->read.sequence_number), 8);
+               }
 
                length =
                    ciphertext->size - tag_size;
index 5701a8fb0fec0d431e32c3cda6fd12f3b3452e38..544134026b4a634548827f55345788658c951c2a 100644 (file)
@@ -221,6 +221,7 @@ _gnutls_epoch_set_cipher_suite(gnutls_session_t session,
        const cipher_entry_st *cipher_algo;
        const mac_entry_st *mac_algo;
        record_parameters_st *params;
+       const gnutls_cipher_suite_entry_st *cs;
        int ret;
 
        ret = _gnutls_epoch_get(session, epoch_rel, &params);
@@ -231,8 +232,12 @@ _gnutls_epoch_set_cipher_suite(gnutls_session_t session,
            || params->cipher != NULL || params->mac != NULL)
                return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
 
-       cipher_algo = _gnutls_cipher_suite_get_cipher_algo(suite);
-       mac_algo = _gnutls_cipher_suite_get_mac_algo(suite);
+       cs = ciphersuite_to_entry(suite);
+       if (cs == NULL)
+               return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
+
+       cipher_algo = cipher_to_entry(cs->block_algorithm);
+       mac_algo = mac_to_entry(cs->mac_algorithm);
 
        if (_gnutls_cipher_is_ok(cipher_algo) == 0
            || _gnutls_mac_is_ok(mac_algo) == 0)
@@ -246,6 +251,10 @@ _gnutls_epoch_set_cipher_suite(gnutls_session_t session,
 
        params->cipher = cipher_algo;
        params->mac = mac_algo;
+       if (cs->nonce_type == NONCE_IS_SENT)
+               params->send_nonce = 1;
+       else
+               params->send_nonce = 0;
 
        return 0;
 }
index a61b563daa0dacf2fd8d77bcf2aaeb3501056b1b..dd1155a6d35882f8714a817e587c4dcdd19193b6 100644 (file)
@@ -445,6 +445,25 @@ typedef struct cipher_entry_st {
        uint16_t tagsize;
 } cipher_entry_st;
 
+typedef enum nonce_type_t {
+       NONCE_IS_SENT,
+       NONCE_IS_COUNTER,
+} nonce_type_t;
+
+typedef struct gnutls_cipher_suite_entry_st {
+       const char *name;
+       const uint8_t id[2];
+       gnutls_cipher_algorithm_t block_algorithm;
+       gnutls_kx_algorithm_t kx_algorithm;
+       gnutls_mac_algorithm_t mac_algorithm;
+       gnutls_protocol_t min_version;  /* this cipher suite is supported
+                                        * from 'version' and above;
+                                        */
+       gnutls_protocol_t min_dtls_version;     /* DTLS min version */
+       gnutls_mac_algorithm_t prf;
+       nonce_type_t nonce_type;
+} gnutls_cipher_suite_entry_st;
+
 /* This structure is used both for MACs and digests
  */
 typedef struct mac_entry_st {
@@ -604,6 +623,7 @@ struct record_parameters_st {
 
        record_state_st read;
        record_state_st write;
+       unsigned send_nonce; /* whether explicit nonce is sent (in AEAD ciphers) */
 
        /* Whether this state is in use, i.e., if there is
           a pending handshake message waiting to be encrypted