summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@gnutls.org>2018-03-24 14:46:00 +0000
committerNikos Mavrogiannopoulos <nmav@gnutls.org>2018-03-24 14:46:00 +0000
commit3016f24d31ba03514c0383962350d675ecb7af06 (patch)
tree6a1b48d76452f4d4e68c0c995f68ce1e0adfd341
parent47c1f6bd32eccf8a752ba8bc6949f5db38d7dd2a (diff)
parentc21c85550f6beb00d11ebd59cbcf3bcd2ccf926d (diff)
downloadgnutls-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--NEWS6
-rw-r--r--lib/algorithms/ciphersuites.c2
-rw-r--r--lib/algorithms/protocols.c2
-rw-r--r--lib/cipher.c90
-rw-r--r--lib/ext/ecc.c78
-rw-r--r--lib/ext/key_share.c67
-rw-r--r--lib/ext/supported_versions.c3
-rw-r--r--lib/gnutls_int.h5
-rw-r--r--lib/priority.c49
-rw-r--r--tests/Makefile.am2
-rw-r--r--tests/cipher-neg-common.c20
-rw-r--r--tests/tls13-cipher-neg.c143
-rw-r--r--tests/tls13/prf.c8
-rw-r--r--tests/tls13/supported_versions.c2
14 files changed, 362 insertions, 115 deletions
diff --git a/NEWS b/NEWS
index 6c2c7f7acb..064f8590ea 100644
--- a/NEWS
+++ b/NEWS
@@ -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(&params->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(&params->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]);
}