From: Nikos Mavrogiannopoulos Date: Sat, 28 Mar 2015 09:40:47 +0000 (+0100) Subject: Added the CHACHA20-POLY1305 ciphersuites (with random IDs) X-Git-Tag: gnutls_3_4_0~94 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=4c768e833705a8af43440fc71475d096d55ca3cd;p=thirdparty%2Fgnutls.git Added the CHACHA20-POLY1305 ciphersuites (with random IDs) --- diff --git a/lib/algorithms.h b/lib/algorithms.h index 97e6935de2..1ac4001255 100644 --- a/lib/algorithms.h +++ b/lib/algorithms.h @@ -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); diff --git a/lib/algorithms/ciphersuites.c b/lib/algorithms/ciphersuites.c index bfd93e5f80..d0f3c77f3c 100644 --- a/lib/algorithms/ciphersuites.c +++ b/lib/algorithms/ciphersuites.c @@ -32,22 +32,11 @@ /* 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); diff --git a/lib/gnutls_cipher.c b/lib/gnutls_cipher.c index c345ce2392..b98db6cae6 100644 --- a/lib/gnutls_cipher.c +++ b/lib/gnutls_cipher.c @@ -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(¶ms->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(¶ms->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; diff --git a/lib/gnutls_constate.c b/lib/gnutls_constate.c index 5701a8fb0f..544134026b 100644 --- a/lib/gnutls_constate.c +++ b/lib/gnutls_constate.c @@ -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, ¶ms); @@ -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; } diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h index a61b563daa..dd1155a6d3 100644 --- a/lib/gnutls_int.h +++ b/lib/gnutls_int.h @@ -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