diff options
author | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2018-03-24 14:46:00 +0000 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2018-03-24 14:46:00 +0000 |
commit | 3016f24d31ba03514c0383962350d675ecb7af06 (patch) | |
tree | 6a1b48d76452f4d4e68c0c995f68ce1e0adfd341 | |
parent | 47c1f6bd32eccf8a752ba8bc6949f5db38d7dd2a (diff) | |
parent | c21c85550f6beb00d11ebd59cbcf3bcd2ccf926d (diff) | |
download | gnutls-3016f24d31ba03514c0383962350d675ecb7af06.tar.gz |
Merge branch 'tmp-draft-ietf-tls13-26' into 'master'
Move to draft-ietf-tls-tls13-26
Closes #409, #378, and #410
See merge request gnutls/gnutls!611
-rw-r--r-- | NEWS | 6 | ||||
-rw-r--r-- | lib/algorithms/ciphersuites.c | 2 | ||||
-rw-r--r-- | lib/algorithms/protocols.c | 2 | ||||
-rw-r--r-- | lib/cipher.c | 90 | ||||
-rw-r--r-- | lib/ext/ecc.c | 78 | ||||
-rw-r--r-- | lib/ext/key_share.c | 67 | ||||
-rw-r--r-- | lib/ext/supported_versions.c | 3 | ||||
-rw-r--r-- | lib/gnutls_int.h | 5 | ||||
-rw-r--r-- | lib/priority.c | 49 | ||||
-rw-r--r-- | tests/Makefile.am | 2 | ||||
-rw-r--r-- | tests/cipher-neg-common.c | 20 | ||||
-rw-r--r-- | tests/tls13-cipher-neg.c | 143 | ||||
-rw-r--r-- | tests/tls13/prf.c | 8 | ||||
-rw-r--r-- | tests/tls13/supported_versions.c | 2 |
14 files changed, 362 insertions, 115 deletions
@@ -11,7 +11,7 @@ See the end for copying conditions. mode, i.e., strict vs a more lax mode which will allow certain non FIPS140-2 operations. -** libgnutls: Introduced support for draft-ietf-tls-tls13-23. It includes version +** libgnutls: Introduced support for draft-ietf-tls-tls13-26. It includes version negotiation, post handshake authentication, length hiding, multiple OCSP support, consistent ciphersuite support across protocols, hello retry requests, ability to adjust key shares via gnutls_init() flags, certificate authorities extension, @@ -29,6 +29,10 @@ See the end for copying conditions. ** libgnutls: gnutls_privkey_import_ext4() was enhanced with the GNUTLS_PRIVKEY_INFO_PK_ALGO_BITS flag. +** libgnutls: on group exchange honor the %SERVER_PRECEDENCE and select the groups + which are preferred by the server. That unfortunately has complicated semantics + as TLS1.2 requires specific ordering of the groups based on the ciphersuite ordering, + making group order unpredictable under TLS1.3. ** API and ABI modifications: gnutls_fips140_set_mode: Added diff --git a/lib/algorithms/ciphersuites.c b/lib/algorithms/ciphersuites.c index a541925029..063363b5bf 100644 --- a/lib/algorithms/ciphersuites.c +++ b/lib/algorithms/ciphersuites.c @@ -1458,7 +1458,7 @@ _gnutls_figure_common_ciphersuite(gnutls_session_t session, * we should assume that SECP256R1 is supported; that is required * by RFC4492, probably to allow SSLv2 hellos negotiate elliptic curve * ciphersuites */ - if (session->internals.cand_ec_group == NULL && + if (!version->tls13_sem && session->internals.cand_ec_group == NULL && !_gnutls_hello_ext_is_present(session, GNUTLS_EXTENSION_SUPPORTED_ECC)) { session->internals.cand_ec_group = _gnutls_id_to_group(DEFAULT_EC_GROUP); } diff --git a/lib/algorithms/protocols.c b/lib/algorithms/protocols.c index 12ac1acf12..bfefdec808 100644 --- a/lib/algorithms/protocols.c +++ b/lib/algorithms/protocols.c @@ -116,7 +116,7 @@ static const version_entry_st sup_versions[] = { .id = GNUTLS_TLS1_3, .age = 5, .major = 0x7f, - .minor = 23, + .minor = 26, .transport = GNUTLS_STREAM, .supported = 1, .explicit_iv = 0, diff --git a/lib/cipher.c b/lib/cipher.c index 0025dd5de9..8203ec8fc3 100644 --- a/lib/cipher.c +++ b/lib/cipher.c @@ -1,7 +1,7 @@ /* * Copyright (C) 2000-2013 Free Software Foundation, Inc. * Copyright (C) 2013 Nikos Mavrogiannopoulos - * Copyright (C) 2017 Red Hat, Inc. + * Copyright (C) 2017-2018 Red Hat, Inc. * * Author: Nikos Mavrogiannopoulos * @@ -65,12 +65,11 @@ decrypt_packet_tls13(gnutls_session_t session, static int encrypt_packet_tls13(gnutls_session_t session, - uint8_t * cipher_data, size_t cipher_size, - gnutls_datum_t * plain, + mbuffer_st *bufel, + gnutls_datum_t *plain, size_t min_pad, content_type_t type, - record_parameters_st * params); - + record_parameters_st *params); /* returns ciphertext which contains the headers too. This also @@ -79,10 +78,10 @@ encrypt_packet_tls13(gnutls_session_t session, */ int _gnutls_encrypt(gnutls_session_t session, - const uint8_t * data, size_t data_size, + const uint8_t *data, size_t data_size, size_t min_pad, - mbuffer_st * bufel, - content_type_t type, record_parameters_st * params) + mbuffer_st *bufel, + content_type_t type, record_parameters_st *params) { gnutls_datum_t plaintext; const version_entry_st *vers = get_version(session); @@ -91,31 +90,34 @@ _gnutls_encrypt(gnutls_session_t session, plaintext.data = (uint8_t *) data; plaintext.size = data_size; - if (vers && vers->tls13_sem) + if (vers && vers->tls13_sem) { + /* it fills the header, as it is included in the authenticated + * data of the AEAD cipher. */ ret = - encrypt_packet_tls13(session, - _mbuffer_get_udata_ptr(bufel), - _mbuffer_get_udata_size - (bufel), &plaintext, min_pad, type, + encrypt_packet_tls13(session, bufel, + &plaintext, min_pad, type, params); - else + if (ret < 0) + return gnutls_assert_val(ret); + } else { ret = encrypt_packet(session, _mbuffer_get_udata_ptr(bufel), _mbuffer_get_udata_size (bufel), &plaintext, min_pad, type, params); - if (ret < 0) - return gnutls_assert_val(ret); + if (ret < 0) + return gnutls_assert_val(ret); - if (IS_DTLS(session)) - _gnutls_write_uint16(ret, - ((uint8_t *) - _mbuffer_get_uhead_ptr(bufel)) + 11); - else - _gnutls_write_uint16(ret, - ((uint8_t *) - _mbuffer_get_uhead_ptr(bufel)) + 3); + if (IS_DTLS(session)) + _gnutls_write_uint16(ret, + ((uint8_t *) + _mbuffer_get_uhead_ptr(bufel)) + 11); + else + _gnutls_write_uint16(ret, + ((uint8_t *) + _mbuffer_get_uhead_ptr(bufel)) + 3); + } _mbuffer_set_udata_size(bufel, ret); _mbuffer_set_uhead_size(bufel, 0); @@ -130,10 +132,11 @@ _gnutls_encrypt(gnutls_session_t session, */ int _gnutls_decrypt(gnutls_session_t session, - gnutls_datum_t * ciphertext, - gnutls_datum_t * output, + gnutls_datum_t *ciphertext, + gnutls_datum_t *output, content_type_t *type, - record_parameters_st * params, gnutls_uint64 * sequence) + record_parameters_st *params, + gnutls_uint64 *sequence) { int ret; const version_entry_st *vers = get_version(session); @@ -414,11 +417,11 @@ encrypt_packet(gnutls_session_t session, static int encrypt_packet_tls13(gnutls_session_t session, - uint8_t * cipher_data, size_t cipher_size, - gnutls_datum_t * plain, + mbuffer_st *bciphertext, + gnutls_datum_t *plain, size_t min_pad, content_type_t type, - record_parameters_st * params) + record_parameters_st *params) { int ret; unsigned int tag_size = params->write.aead_tag_size; @@ -427,6 +430,10 @@ encrypt_packet_tls13(gnutls_session_t session, unsigned iv_size = 0; uint8_t *fdata; ssize_t fdata_size, max; + uint8_t *cipher_data = _mbuffer_get_udata_ptr(bciphertext); + size_t cipher_size = _mbuffer_get_udata_size(bciphertext); + uint8_t *header = _mbuffer_get_uhead_ptr(bciphertext); + size_t header_size = _mbuffer_get_uhead_size(bciphertext); if (unlikely(ver == NULL)) return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); @@ -442,6 +449,7 @@ encrypt_packet_tls13(gnutls_session_t session, if (cipher_size < plain->size+1) return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); memcpy(cipher_data, plain->data, plain->size); + _gnutls_write_uint16(plain->size, header+3); return plain->size; } @@ -471,9 +479,13 @@ encrypt_packet_tls13(gnutls_session_t session, if (min_pad) memset(&fdata[plain->size+1], 0, min_pad); + /* we need to write size to header prior to encryption, as + * size is in authenticated data of AEAD cipher. */ + _gnutls_write_uint16(fdata_size+tag_size, header+3); + ret = gnutls_aead_cipher_encrypt(¶ms->write.ctx.aead, nonce, iv_size, - NULL, 0, + header, header_size, tag_size, fdata, fdata_size, cipher_data, &cipher_size); @@ -865,10 +877,10 @@ decrypt_packet(gnutls_session_t session, static int decrypt_packet_tls13(gnutls_session_t session, - gnutls_datum_t * ciphertext, - gnutls_datum_t * plain, - content_type_t *type, record_parameters_st * params, - gnutls_uint64 * sequence) + gnutls_datum_t *ciphertext, + gnutls_datum_t *plain, + content_type_t *type, record_parameters_st *params, + gnutls_uint64 *sequence) { uint8_t nonce[MAX_CIPHER_IV_SIZE]; size_t length, length_to_decrypt; @@ -878,6 +890,7 @@ decrypt_packet_tls13(gnutls_session_t session, unsigned iv_size; unsigned j; volatile unsigned length_set; + uint8_t aad[5]; if (unlikely(ver == NULL)) return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); @@ -921,9 +934,14 @@ decrypt_packet_tls13(gnutls_session_t session, gnutls_assert_val(GNUTLS_E_DECRYPTION_FAILED); } + aad[0] = *type; + aad[1] = 0x03; + aad[2] = 0x03; + _gnutls_write_uint16(ciphertext->size, &aad[3]); + ret = gnutls_aead_cipher_decrypt(¶ms->read.ctx.aead, nonce, iv_size, - NULL, 0, + aad, 5, tag_size, ciphertext->data, length_to_decrypt, plain->data, &length); diff --git a/lib/ext/ecc.c b/lib/ext/ecc.c index 58cf3d86b2..50cd862211 100644 --- a/lib/ext/ecc.c +++ b/lib/ext/ecc.c @@ -115,7 +115,7 @@ static int _gnutls_supported_ecc_recv_params(gnutls_session_t session, const uint8_t * data, size_t _data_size) { - int ret, i; + int i; ssize_t data_size = _data_size; uint16_t len; const uint8_t *p = data; @@ -123,6 +123,9 @@ _gnutls_supported_ecc_recv_params(gnutls_session_t session, unsigned have_ffdhe = 0; unsigned tls_id; unsigned min_dh; + unsigned j; + int serv_ec_idx, serv_dh_idx; /* index in server's priority listing */ + int cli_ec_pos, cli_dh_pos; /* position in listing sent by client */ if (session->security_parameters.entity == GNUTLS_CLIENT) { /* A client shouldn't receive this extension in TLS1.2. It is @@ -148,11 +151,15 @@ _gnutls_supported_ecc_recv_params(gnutls_session_t session, /* we figure what is the minimum DH allowed for this session, if any */ min_dh = get_min_dh(session); - /* This is being processed prior to a ciphersuite being selected */ + serv_ec_idx = serv_dh_idx = -1; + cli_ec_pos = cli_dh_pos = -1; + + /* This extension is being processed prior to a ciphersuite being selected, + * so we cannot rely on ciphersuite information. */ for (i = 0; i < len; i += 2) { - if (have_ffdhe == 0 && p[i] == 0x01) { + if (have_ffdhe == 0 && p[i] == 0x01) have_ffdhe = 1; - } + tls_id = _gnutls_read_uint16(&p[i]); group = _gnutls_tls_id_to_group(tls_id); @@ -160,25 +167,62 @@ _gnutls_supported_ecc_recv_params(gnutls_session_t session, if (group == NULL) continue; - /* if a DH group and less than expected ignore */ if (min_dh > 0 && group->prime && group->prime->size*8 < min_dh) continue; - /* Check if we support this group */ - if ((ret = - _gnutls_session_supports_group(session, - group->id)) - < 0) { - group = NULL; - continue; - } else { - if (group->pk == GNUTLS_PK_DH && session->internals.cand_dh_group == NULL) - session->internals.cand_dh_group = group; - else if (group->pk != GNUTLS_PK_DH && session->internals.cand_ec_group == NULL) - session->internals.cand_ec_group = group; + /* we simulate _gnutls_session_supports_group, but we prioritize if + * %SERVER_PRECEDENCE is given */ + for (j = 0; j < session->internals.priorities->groups.size; j++) { + if (session->internals.priorities->groups.entry[j]->id == group->id) { + if (session->internals.priorities->server_precedence) { + if (group->pk == GNUTLS_PK_DH) { + if (serv_dh_idx != -1 && (int)j > serv_dh_idx) + break; + serv_dh_idx = j; + cli_dh_pos = i; + } else { + if (serv_ec_idx != -1 && (int)j > serv_ec_idx) + break; + serv_ec_idx = j; + cli_ec_pos = i; + } + } else { + if (group->pk == GNUTLS_PK_DH) { + if (cli_dh_pos != -1) + break; + cli_dh_pos = i; + serv_dh_idx = j; + } else { + if (cli_ec_pos != -1) + break; + cli_ec_pos = i; + serv_ec_idx = j; + } + } + break; + } } } + /* serv_dh/ec_pos contain the index of the groups we want to use. + */ + if (serv_dh_idx != -1) { + session->internals.cand_dh_group = session->internals.priorities->groups.entry[serv_dh_idx]; + session->internals.cand_group = session->internals.cand_dh_group; + } + + if (serv_ec_idx != -1) { + session->internals.cand_ec_group = session->internals.priorities->groups.entry[serv_ec_idx]; + if (session->internals.cand_group == NULL || + (session->internals.priorities->server_precedence && serv_ec_idx < serv_dh_idx) || + (!session->internals.priorities->server_precedence && cli_ec_pos < cli_dh_pos)) { + session->internals.cand_group = session->internals.cand_ec_group; + } + } + + if (session->internals.cand_group) + _gnutls_handshake_log("EXT[%p]: Selected group %s\n", session, session->internals.cand_group->name); + if (have_ffdhe) session->internals.hsk_flags |= HSK_HAVE_FFDHE; } diff --git a/lib/ext/key_share.c b/lib/ext/key_share.c index f110e10268..f9403df838 100644 --- a/lib/ext/key_share.c +++ b/lib/ext/key_share.c @@ -489,9 +489,10 @@ key_share_recv_params(gnutls_session_t session, int ret; ssize_t data_size = _data_size; ssize_t size; - unsigned gid, used_share = 0; + unsigned gid; const version_entry_st *ver; - const gnutls_group_entry_st *group, *sgroup = NULL; + const gnutls_group_entry_st *group; + unsigned used_share = 0; if (session->security_parameters.entity == GNUTLS_SERVER) { ver = get_version(session); @@ -523,46 +524,38 @@ key_share_recv_params(gnutls_session_t session, if (group != NULL) _gnutls_handshake_log("EXT[%p]: Received key share for %s\n", session, group->name); - if (group != NULL) { - if (group == session->internals.cand_ec_group) - sgroup = group; - else if (group == session->internals.cand_dh_group) - sgroup = group; - } + if (group != NULL && group == session->internals.cand_group) { + _gnutls_session_group_set(session, group); - if (sgroup == NULL) { - data += size; - continue; - } + ret = server_use_key_share(session, group, data, size); + if (ret < 0) + return gnutls_assert_val(ret); - _gnutls_session_group_set(session, sgroup); + used_share = 1; + break; - ret = server_use_key_share(session, sgroup, data, size); - if (ret < 0) { - return gnutls_assert_val(ret); } - used_share = 1; - break; + data += size; + continue; } - if (used_share == 0) { - /* we utilize GNUTLS_E_NO_COMMON_KEY_SHARE for: - * 1. signal for hello-retry-request in the handshake - * layer during first client hello parsing (server side - here). - * This does not result to error code being - * propagated to app layer. - * 2. Propagate to application error code that no - * common key share was found after an HRR was - * received (client side) - * 3. Propagate to application error code that no - * common key share was found after an HRR was - * sent (server side). - * In cases (2,3) the error is translated to illegal - * parameter alert. - */ + /* we utilize GNUTLS_E_NO_COMMON_KEY_SHARE for: + * 1. signal for hello-retry-request in the handshake + * layer during first client hello parsing (server side - here). + * This does not result to error code being + * propagated to app layer. + * 2. Propagate to application error code that no + * common key share was found after an HRR was + * received (client side) + * 3. Propagate to application error code that no + * common key share was found after an HRR was + * sent (server side). + * In cases (2,3) the error is translated to illegal + * parameter alert. + */ + if (used_share == 0) return gnutls_assert_val(GNUTLS_E_NO_COMMON_KEY_SHARE); - } } else { /* Client */ ver = get_version(session); @@ -712,10 +705,8 @@ key_share_send_params(gnutls_session_t session, return gnutls_assert_val(0); if (_gnutls_ext_get_msg(session) == GNUTLS_EXT_FLAG_HRR) { - if (session->internals.cand_ec_group != NULL) - group = session->internals.cand_ec_group; - else - group = session->internals.cand_dh_group; + group = session->internals.cand_group; + if (group == NULL) return gnutls_assert_val(GNUTLS_E_NO_COMMON_KEY_SHARE); diff --git a/lib/ext/supported_versions.c b/lib/ext/supported_versions.c index b2eff6be80..e9e0b88337 100644 --- a/lib/ext/supported_versions.c +++ b/lib/ext/supported_versions.c @@ -122,6 +122,9 @@ supported_versions_recv_params(gnutls_session_t session, _gnutls_handshake_log("EXT[%p]: Negotiated version: %d.%d\n", session, (int)major, (int)minor); + if (!vers->tls13_sem) + return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER); + ret = _gnutls_negotiate_version(session, proto, major, minor); if (ret < 0) { gnutls_assert(); diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h index 1d75c4a09f..e926b3d0fe 100644 --- a/lib/gnutls_int.h +++ b/lib/gnutls_int.h @@ -1272,9 +1272,12 @@ typedef struct { * receive size */ unsigned max_recv_size; - /* candidate groups to be selected for security params groups */ + /* candidate groups to be selected for security params groups, they are + * prioritized in isolation under TLS1.2 */ const gnutls_group_entry_st *cand_ec_group; const gnutls_group_entry_st *cand_dh_group; + /* used under TLS1.3+ */ + const gnutls_group_entry_st *cand_group; /* the ciphersuite received in HRR */ uint8_t hrr_cs[2]; diff --git a/lib/priority.c b/lib/priority.c index 8e2132ffea..65b3dd3d93 100644 --- a/lib/priority.c +++ b/lib/priority.c @@ -1172,8 +1172,10 @@ static int set_ciphersuite_list(gnutls_priority_t priority_cache) unsigned have_ec = 0; unsigned have_dh = 0; unsigned tls_sig_sem = 0; - const version_entry_st *tlsmax = NULL; + const version_entry_st *tlsmax = NULL, *vers; const version_entry_st *dtlsmax = NULL; + const version_entry_st *tlsmin = NULL; + const version_entry_st *dtlsmin = NULL; unsigned have_tls13 = 0; priority_cache->cs.size = 0; @@ -1182,23 +1184,42 @@ static int set_ciphersuite_list(gnutls_priority_t priority_cache) priority_cache->groups.have_ffdhe = 0; for (i = 0; i < priority_cache->protocol.algorithms; i++) { - if (priority_cache->protocol.priority[i] < GNUTLS_DTLS_VERSION_MIN) { - tlsmax = version_to_entry(priority_cache->protocol.priority[i]); - if (tlsmax) { - tls_sig_sem |= tlsmax->tls_sig_sem; - if (tlsmax->tls13_sem) - have_tls13 = 1; - } + vers = version_to_entry(priority_cache->protocol.priority[i]); + if (!vers) + continue; + + if (vers->transport == GNUTLS_STREAM) { /* TLS */ + tls_sig_sem |= vers->tls_sig_sem; + if (vers->tls13_sem) + have_tls13 = 1; + + if (tlsmax == NULL || vers->age > tlsmax->age) + tlsmax = vers; + if (tlsmin == NULL || vers->age < tlsmin->age) + tlsmin = vers; } else { /* dtls */ - dtlsmax = version_to_entry(priority_cache->protocol.priority[i]); - if (dtlsmax) { - tls_sig_sem |= dtlsmax->tls_sig_sem; - if (dtlsmax->tls13_sem) - have_tls13 = 1; - } + tls_sig_sem |= vers->tls_sig_sem; + if (vers->tls13_sem) + have_tls13 = 1; + + if (dtlsmax == NULL || vers->age > dtlsmax->age) + dtlsmax = vers; + if (dtlsmin == NULL || vers->age < dtlsmin->age) + dtlsmin = vers; } } + /* DTLS or TLS protocols must be present */ + if ((!tlsmax || !tlsmin) && (!dtlsmax || !dtlsmin)) + return gnutls_assert_val(GNUTLS_E_NO_PRIORITIES_WERE_SET); + + /* if we are have TLS1.3+ do not enable any key exchange algorithms, + * the protocol doesn't require any. */ + if (tlsmin && tlsmin->tls13_sem) { + if (!dtlsmin || (dtlsmin && dtlsmin->tls13_sem)) + priority_cache->_kx.algorithms = 0; + } + /* Add TLS 1.3 ciphersuites (no KX) */ for (j=0;j<priority_cache->_cipher.algorithms;j++) { for (z=0;z<priority_cache->_mac.algorithms;z++) { diff --git a/tests/Makefile.am b/tests/Makefile.am index 18814bf3f5..5abd976ff8 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -118,6 +118,8 @@ ctests += tls13/ocsp-client ctests += tls13/change_cipher_spec +ctests += tls13-cipher-neg + ctests += mini-record-2 simple gnutls_hmac_fast set_pkcs12_cred cert certuniqueid tls-neg-ext-key \ mpi certificate_set_x509_crl dn parse_ca x509-dn x509-dn-decode record-sizes \ hostname-check cve-2008-4989 pkcs12_s2k chainverify record-sizes-range \ diff --git a/tests/cipher-neg-common.c b/tests/cipher-neg-common.c index 1ddbad612d..a855147359 100644 --- a/tests/cipher-neg-common.c +++ b/tests/cipher-neg-common.c @@ -23,6 +23,7 @@ typedef struct test_case_st { const char *name; int cipher; + int group; const char *client_prio; const char *server_prio; unsigned not_on_fips; @@ -79,11 +80,28 @@ static void try(test_case_st *test) } if (cret != test->cipher) { - fail("%s: negotiated cipher diffs the expected (%s, %s)!\n", + fail("%s: negotiated cipher differs with the expected (%s, %s)!\n", test->name, gnutls_cipher_get_name(cret), gnutls_cipher_get_name(test->cipher)); } + if (test->group) { + sret = gnutls_group_get(client); + cret = gnutls_group_get(server); + + if (sret != cret) { + fail("%s: client negotiated different group than server (%s, %s)!\n", + test->name, gnutls_group_get_name(cret), + gnutls_group_get_name(sret)); + } + + if (cret != test->group) { + fail("%s: negotiated group differs with the expected (%s, %s)!\n", + test->name, gnutls_group_get_name(cret), + gnutls_group_get_name(test->group)); + } + } + gnutls_deinit(server); gnutls_deinit(client); gnutls_certificate_free_credentials(s_cert_cred); diff --git a/tests/tls13-cipher-neg.c b/tests/tls13-cipher-neg.c new file mode 100644 index 0000000000..b2d402cb85 --- /dev/null +++ b/tests/tls13-cipher-neg.c @@ -0,0 +1,143 @@ +/* + * Copyright (C) 2017-2018 Red Hat, Inc. + * + * Author: Nikos Mavrogiannopoulos + * + * This file is part of GnuTLS. + * + * GnuTLS is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * GnuTLS is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/> + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +/* This program tests the ciphersuite negotiation for various key exchange + * methods and options under TLS1.3. */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <gnutls/gnutls.h> +#include "utils.h" +#include "cert-common.h" +#include "eagain-common.h" + +#include "cipher-neg-common.c" + +/* We remove the ECDHE and DHE key exchanges as they impose additional + * rules in the sorting of groups. + */ +#define SPRIO "NORMAL:-VERS-ALL:+VERS-TLS1.3" +#define CPRIO "NORMAL:-VERS-ALL:+VERS-TLS1.3" + +test_case_st tests[] = { + { + .name = "server TLS 1.3: AES-128-GCM with SECP256R1 (server)", + .cipher = GNUTLS_CIPHER_AES_128_GCM, + .group = GNUTLS_GROUP_SECP256R1, + .server_prio = SPRIO":-CIPHER-ALL:+AES-128-GCM:+CIPHER-ALL:%SERVER_PRECEDENCE:-GROUP-ALL:+GROUP-SECP256R1:+GROUP-ALL", + .client_prio = CPRIO":+AES-128-GCM:-GROUP-ALL:+GROUP-FFDHE2048:+GROUP-SECP384R1:+GROUP-SECP521R1:+GROUP-SECP256R1" + }, + { + .name = "both TLS 1.3: AES-128-GCM with X25519 (server)", + .cipher = GNUTLS_CIPHER_AES_128_GCM, + .group = GNUTLS_GROUP_X25519, + .server_prio = SPRIO":-CIPHER-ALL:+AES-128-GCM:+CIPHER-ALL:%SERVER_PRECEDENCE:-GROUP-ALL:+GROUP-X25519:+GROUP-ALL", + .client_prio = CPRIO":+AES-128-GCM:-GROUP-ALL:+GROUP-FFDHE2048:+GROUP-SECP384R1:+GROUP-SECP521R1:+GROUP-SECP256R1:+GROUP-ALL" + }, + { + .name = "client TLS 1.3: AES-128-GCM with SECP256R1 (client)", + .cipher = GNUTLS_CIPHER_AES_128_GCM, + .group = GNUTLS_GROUP_SECP256R1, + .server_prio = SPRIO":+AES-128-GCM:-GROUP-ALL:+GROUP-FFDHE2048:+GROUP-SECP384R1:+GROUP-SECP521R1:+GROUP-SECP256R1", + .client_prio = CPRIO":-CIPHER-ALL:+AES-128-GCM:+CIPHER-ALL:-VERS-ALL:+VERS-TLS1.3:-GROUP-ALL:+GROUP-SECP256R1:+GROUP-ALL" + }, + { + .name = "both TLS 1.3: AES-128-GCM with X25519 (client)", + .cipher = GNUTLS_CIPHER_AES_128_GCM, + .group = GNUTLS_GROUP_X25519, + .server_prio = SPRIO":+AES-128-GCM:-GROUP-ALL:+GROUP-FFDHE2048:+GROUP-SECP384R1:+GROUP-SECP521R1:+GROUP-SECP256R1:+GROUP-ALL", + .client_prio = CPRIO":-CIPHER-ALL:+AES-128-GCM:+CIPHER-ALL:-VERS-ALL:+VERS-TLS1.3:-GROUP-ALL:+GROUP-X25519:+GROUP-ALL" + }, + { + .name = "server TLS 1.3: AES-128-CCM and FFDHE2048 (server)", + .cipher = GNUTLS_CIPHER_AES_128_CCM, + .group = GNUTLS_GROUP_FFDHE2048, + .server_prio = SPRIO":-CIPHER-ALL:+AES-128-CCM:+CIPHER-ALL:%SERVER_PRECEDENCE:-GROUP-ALL:+GROUP-FFDHE2048:+GROUP-ALL", + .client_prio = CPRIO":+AES-128-CCM" + }, + { + .name = "both TLS 1.3: AES-128-CCM and FFDHE 2048 (server)", + .cipher = GNUTLS_CIPHER_AES_128_CCM, + .group = GNUTLS_GROUP_FFDHE2048, + .server_prio = SPRIO":-CIPHER-ALL:+AES-128-CCM:+CIPHER-ALL:%SERVER_PRECEDENCE:-GROUP-ALL:+GROUP-FFDHE2048:+GROUP-ALL", + .client_prio = CPRIO":+AES-128-CCM:+VERS-TLS1.3" + }, + { + .name = "client TLS 1.3: AES-128-CCM and FFDHE 2048 (client)", + .cipher = GNUTLS_CIPHER_AES_128_CCM, + .group = GNUTLS_GROUP_FFDHE2048, + .server_prio = SPRIO":+AES-128-CCM", + .client_prio = CPRIO":-CIPHER-ALL:+AES-128-CCM:+CIPHER-ALL:-VERS-ALL:+VERS-TLS1.3:-GROUP-ALL:+GROUP-FFDHE2048:+GROUP-ALL" + }, + { + .name = "both TLS 1.3: AES-128-CCM and FFDHE 2048 (client)", + .cipher = GNUTLS_CIPHER_AES_128_CCM, + .group = GNUTLS_GROUP_FFDHE2048, + .server_prio = SPRIO":+AES-128-CCM:+VERS-TLS1.3", + .client_prio = CPRIO":-CIPHER-ALL:+AES-128-CCM:+CIPHER-ALL:-VERS-ALL:+VERS-TLS1.3:-GROUP-ALL:+GROUP-FFDHE2048:+GROUP-ALL" + }, + { + .name = "server TLS 1.3: CHACHA20-POLY (server)", + .cipher = GNUTLS_CIPHER_CHACHA20_POLY1305, + .not_on_fips = 1, + .server_prio = SPRIO":-CIPHER-ALL:+CHACHA20-POLY1305:+CIPHER-ALL:%SERVER_PRECEDENCE", + .client_prio = CPRIO":+CHACHA20-POLY1305" + }, + { + .name = "both TLS 1.3: CHACHA20-POLY (server)", + .cipher = GNUTLS_CIPHER_CHACHA20_POLY1305, + .not_on_fips = 1, + .server_prio = SPRIO":-CIPHER-ALL:+CHACHA20-POLY1305:+CIPHER-ALL:%SERVER_PRECEDENCE", + .client_prio = CPRIO":+CHACHA20-POLY1305:+VERS-TLS1.3" + }, + { + .name = "client TLS 1.3: CHACHA20-POLY (client)", + .cipher = GNUTLS_CIPHER_CHACHA20_POLY1305, + .not_on_fips = 1, + .server_prio = SPRIO":+CHACHA20-POLY1305", + .client_prio = CPRIO":-CIPHER-ALL:+CHACHA20-POLY1305:+CIPHER-ALL" + }, + { + .name = "both TLS 1.3: CHACHA20-POLY (client)", + .cipher = GNUTLS_CIPHER_CHACHA20_POLY1305, + .not_on_fips = 1, + .server_prio = SPRIO":+CHACHA20-POLY1305", + .client_prio = CPRIO":-CIPHER-ALL:+CHACHA20-POLY1305:+CIPHER-ALL" + } +}; + +void doit(void) +{ + unsigned i; + global_init(); + + for (i=0;i<sizeof(tests)/sizeof(tests[0]);i++) { + try(&tests[i]); + } + + gnutls_global_deinit(); +} diff --git a/tests/tls13/prf.c b/tests/tls13/prf.c index 355bf37c63..f221896124 100644 --- a/tests/tls13/prf.c +++ b/tests/tls13/prf.c @@ -126,8 +126,8 @@ static void dump(const char *name, const uint8_t *data, unsigned data_size) } \ } -#define KEY_EXP_VALUE "\x2a\xba\xd1\x0d\x79\x1d\x63\xaa\x68\xb5\x42\xa7\xbf\xee\x7c\x15\x68\x72\xc4\x94\x92\xfc\x38\x2d\x29\xc4\x2a\x21\xd6\xce\x1a\x30\x9f\x2e" -#define HELLO_VALUE "\x5b\x1e\x8a\xd6\xf4\x41\xca\xed\x60\xff\xd7\xd8\xe3\xcf\x89\xf1\x11\xfb\xc3\x08\x64\x05\xd4\x18\x2c\xf0\x8a\x75\x05\x7d\x65" +#define KEY_EXP_VALUE "\x1f\x17\xb5\xe2\xef\xfc\x1c\x27\x1e\x1a\x2c\x9b\x36\xc7\x43\x70\x5c\x80\x93\x7a\xce\x7b\x52\x18\xe0\x22\xca\x0d\xf8\x01\xa5\x7f\xef\x8b" +#define HELLO_VALUE "\x5c\x6d\x0a\xa0\xc7\x1e\x52\xb5\xb4\x2c\x4b\xfa\x24\xc8\x3f\x3f\xba\xfc\x43\xc2\x05\xe5\x04\xd9\xfd\x86\x84\x00\x1c\xfb\xf3" static void check_prfs(gnutls_session_t session) { unsigned char key_material[512]; @@ -138,8 +138,8 @@ static void check_prfs(gnutls_session_t session) TRY(13, "key expansion", 0, NULL, 34, (uint8_t*)KEY_EXP_VALUE); TRY(6, "hello", 0, NULL, 31, (uint8_t*)HELLO_VALUE); - TRY(7, "context", 5, "abcd\xfa", 31, (uint8_t*)"\x27\x0f\xd4\xa5\x34\xa3\x50\x60\xeb\xa7\x36\x39\x10\xbf\x54\xfb\x5f\x31\x50\xc9\x20\x4c\xe4\x1c\xa0\x6e\x63\xd6\x37\x71\x06"); - TRY(12, "null-context", 0, "", 31, (uint8_t*)"\x11\xf8\x0b\xae\x44\xe4\xed\x79\x39\x80\x8a\x6c\xff\xaa\xec\x77\x01\x9a\x1c\x9e\x14\xe8\x7a\x88\x7a\xb4\x1e\xd3\x2b\xf7\x41"); + TRY(7, "context", 5, "abcd\xfa", 31, (uint8_t*)"\xa5\xc0\x3e\x31\x5b\x70\x57\x48\x1e\xfe\x11\x2b\x13\x13\x8f\x97\x14\x2d\x4d\x35\xac\x0a\x20\x4e\x9c\x84\xcf\x48\x8c\xa2\x0b"); + TRY(12, "null-context", 0, "", 31, (uint8_t*)"\x7b\xb9\x00\x8a\x2c\x97\xa0\x73\x28\x91\xbf\x73\xda\xa5\x78\x08\x45\xac\xa7\x29\xa8\xc4\x30\x30\xc2\x76\x94\x1a\xaf\x74\x4b"); /* Try whether calling gnutls_prf() with non-null context or server-first * param, will fail */ diff --git a/tests/tls13/supported_versions.c b/tests/tls13/supported_versions.c index be0e6f3f2e..bb9c7b6b92 100644 --- a/tests/tls13/supported_versions.c +++ b/tests/tls13/supported_versions.c @@ -224,7 +224,7 @@ static int client_hello_callback(gnutls_session_t session, unsigned int htype, #ifdef TLS13_FINAL_VERSION if (msg->data[pos] != 0x03 || msg->data[pos+1] != 0x04) { #else - if (msg->data[pos] != 0x7f || msg->data[pos+1] != 23) { + if (msg->data[pos] != 0x7f || msg->data[pos+1] != 26) { #endif fail("fail expected TLS 1.3, got %d.%d\n", (int)msg->data[pos], (int)msg->data[pos+1]); } |