summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@gnutls.org>2018-03-10 11:57:18 +0000
committerNikos Mavrogiannopoulos <nmav@gnutls.org>2018-03-10 11:57:18 +0000
commit2d18661f21ab564e4d870ac320e15be9e2fcfebb (patch)
tree762e26344d99a905ca3f5ffd8766de1b90e68735
parent659adce03edaf71538e9d61fb5092e393f8867f4 (diff)
parentf14942024a6032e884fc8be4ff641149bc145ffc (diff)
downloadgnutls-2d18661f21ab564e4d870ac320e15be9e2fcfebb.tar.gz
Merge branch 'tmp-nmav-draft-ietf-tls-tls13-22' into 'master'
Move to draft-ietf-tls-tls-23 Closes #391, #400, #393, #389, #397, #398, #395, and #396 See merge request gnutls/gnutls!610
-rw-r--r--lib/alert.c1
-rw-r--r--lib/algorithms.h34
-rw-r--r--lib/algorithms/protocols.c2
-rw-r--r--lib/algorithms/sign.c60
-rw-r--r--lib/buffers.c15
-rw-r--r--lib/ext/dumbfw.c2
-rw-r--r--lib/ext/key_share.c2
-rw-r--r--lib/ext/signature.c23
-rw-r--r--lib/ext/supported_versions.c64
-rw-r--r--lib/gnutls_int.h17
-rw-r--r--lib/handshake-tls13.c112
-rw-r--r--lib/handshake.c434
-rw-r--r--lib/handshake.h4
-rw-r--r--lib/includes/gnutls/gnutls.h.in49
-rw-r--r--lib/priority.c8
-rw-r--r--lib/privkey.c17
-rw-r--r--lib/pubkey.c8
-rw-r--r--lib/record.c40
-rw-r--r--lib/sslv2_compat.c2
-rw-r--r--lib/tls-sig.c9
-rw-r--r--lib/tls13-sig.c17
-rw-r--r--lib/tls13/hello_retry.c62
-rw-r--r--tests/Makefile.am2
-rw-r--r--tests/common-cert-key-exchange.c88
-rw-r--r--tests/common-cert-key-exchange.h9
-rw-r--r--tests/dtls12-cert-key-exchange.c6
-rw-r--r--tests/pkcs11/tls-neg-pkcs11-key.c2
-rw-r--r--tests/privkey-verify-broken.c2
-rw-r--r--tests/rsa-rsa-pss.c75
-rw-r--r--tests/suite/tls-fuzzer/gnutls-cert.json4
-rw-r--r--tests/suite/tls-fuzzer/gnutls-nocert.json11
m---------tests/suite/tls-fuzzer/tlsfuzzer0
m---------tests/suite/tls-fuzzer/tlslite-ng0
-rw-r--r--tests/tls-neg-ext-key.c6
-rw-r--r--tests/tls11-cert-key-exchange.c9
-rw-r--r--tests/tls12-cert-key-exchange.c26
-rw-r--r--tests/tls13-cert-key-exchange.c36
-rw-r--r--tests/tls13/change_cipher_spec.c344
-rw-r--r--tests/tls13/ext-parse.h20
-rw-r--r--tests/tls13/key_share.c6
-rw-r--r--tests/tls13/prf.c20
-rw-r--r--tests/tls13/supported_versions.c12
42 files changed, 1260 insertions, 400 deletions
diff --git a/lib/alert.c b/lib/alert.c
index aec54615cf..182e97f21b 100644
--- a/lib/alert.c
+++ b/lib/alert.c
@@ -192,6 +192,7 @@ int gnutls_error_to_alert(int err, int *level)
switch (err) { /* send appropriate alert */
case GNUTLS_E_PK_SIG_VERIFY_FAILED:
+ case GNUTLS_E_ERROR_IN_FINISHED_PACKET:
ret = GNUTLS_A_DECRYPT_ERROR;
_level = GNUTLS_AL_FATAL;
break;
diff --git a/lib/algorithms.h b/lib/algorithms.h
index 556bc33901..495b20d439 100644
--- a/lib/algorithms.h
+++ b/lib/algorithms.h
@@ -327,6 +327,18 @@ struct gnutls_sign_entry_st {
gnutls_pk_algorithm_t pk;
gnutls_digest_algorithm_t hash;
+ /* if non-zero it must be the algorithm of the
+ * private key used or certificate. This is for algorithms
+ * which can have a different public key type than the
+ * private key (e.g., RSA PKCS#1 1.5 certificate, but
+ * an RSA-PSS private key, or an RSA private key and
+ * an RSA-PSS certificate). */
+ gnutls_pk_algorithm_t priv_pk;
+ gnutls_pk_algorithm_t cert_pk;
+
+ /* non-zero if it is ok to use under TLS1.3 */
+ unsigned tls13_ok;
+
/* if this signature algorithm is restricted to a curve
* under TLS 1.3. */
gnutls_ecc_curve_t curve;
@@ -342,6 +354,28 @@ const gnutls_sign_entry_st *_gnutls_sign_to_entry(gnutls_sign_algorithm_t sign);
const gnutls_sign_entry_st *_gnutls_pk_to_sign_entry(gnutls_pk_algorithm_t pk, gnutls_digest_algorithm_t hash);
const gnutls_sign_entry_st *_gnutls_oid_to_sign_entry(const char *oid);
+/* returns true if that signature can be generated
+ * from the given private key algorithm. */
+inline static unsigned
+sign_supports_priv_pk_algorithm(const gnutls_sign_entry_st *se, gnutls_pk_algorithm_t pk)
+{
+ if (pk == se->pk || (se->priv_pk && se->priv_pk == pk))
+ return 1;
+
+ return 0;
+}
+
+/* returns true if that signature can be verified with
+ * the given public key algorithm. */
+inline static unsigned
+sign_supports_cert_pk_algorithm(const gnutls_sign_entry_st *se, gnutls_pk_algorithm_t pk)
+{
+ if (pk == se->pk || (se->cert_pk && se->cert_pk == pk))
+ return 1;
+
+ return 0;
+}
+
bool _gnutls_sign_is_secure2(const gnutls_sign_entry_st *se, unsigned int flags);
gnutls_pk_algorithm_t _gnutls_x509_sign_to_pk(gnutls_sign_algorithm_t
diff --git a/lib/algorithms/protocols.c b/lib/algorithms/protocols.c
index a7af6b834d..12ac1acf12 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 = 21,
+ .minor = 23,
.transport = GNUTLS_STREAM,
.supported = 1,
.explicit_iv = 0,
diff --git a/lib/algorithms/sign.c b/lib/algorithms/sign.c
index 33fd881892..5a45e9fa10 100644
--- a/lib/algorithms/sign.c
+++ b/lib/algorithms/sign.c
@@ -36,9 +36,6 @@
# define SHA1_SECURE_VAL _INSECURE_FOR_CERTS
#endif
-/* Signature algorithms may be listed twice with a different PK algorithm,
- * e.g., RSA-PSS-SHA256 can be generated by GNUTLS_PK_RSA or GNUTLS_PK_RSA_PSS.
- */
static const gnutls_sign_entry_st sign_algorithms[] = {
/* RSA-PKCS#1 1.5: must be before PSS,
* so that gnutls_pk_to_sign() will return
@@ -67,37 +64,52 @@ static const gnutls_sign_entry_st sign_algorithms[] = {
.oid = PK_PKIX1_RSA_PSS_OID,
.id = GNUTLS_SIGN_RSA_PSS_SHA256,
.pk = GNUTLS_PK_RSA_PSS,
+ .priv_pk = GNUTLS_PK_RSA, /* PKCS#11 doesn't separate RSA from RSA-PSS privkeys */
.hash = GNUTLS_DIG_SHA256,
- .aid = {{8, 4}, SIG_SEM_DEFAULT}},
- {.name = "RSA-PSS-SHA256",
+ .tls13_ok = 1,
+ .aid = {{8, 9}, SIG_SEM_DEFAULT}},
+ {.name = "RSA-PSS-RSAE-SHA256",
.oid = PK_PKIX1_RSA_PSS_OID,
- .id = GNUTLS_SIGN_RSA_PSS_SHA256,
- .pk = GNUTLS_PK_RSA,
+ .id = GNUTLS_SIGN_RSA_PSS_RSAE_SHA256,
+ .pk = GNUTLS_PK_RSA_PSS,
+ .cert_pk = GNUTLS_PK_RSA,
+ .priv_pk = GNUTLS_PK_RSA,
.hash = GNUTLS_DIG_SHA256,
+ .tls13_ok = 1,
.aid = {{8, 4}, SIG_SEM_DEFAULT}},
{.name = "RSA-PSS-SHA384",
.oid = PK_PKIX1_RSA_PSS_OID,
.id = GNUTLS_SIGN_RSA_PSS_SHA384,
.pk = GNUTLS_PK_RSA_PSS,
+ .priv_pk = GNUTLS_PK_RSA,
.hash = GNUTLS_DIG_SHA384,
- .aid = {{8, 5}, SIG_SEM_DEFAULT}},
- {.name = "RSA-PSS-SHA384",
+ .tls13_ok = 1,
+ .aid = {{8, 0x0A}, SIG_SEM_DEFAULT}},
+ {.name = "RSA-PSS-RSAE-SHA384",
.oid = PK_PKIX1_RSA_PSS_OID,
- .id = GNUTLS_SIGN_RSA_PSS_SHA384,
- .pk = GNUTLS_PK_RSA,
+ .id = GNUTLS_SIGN_RSA_PSS_RSAE_SHA384,
+ .pk = GNUTLS_PK_RSA_PSS,
+ .cert_pk = GNUTLS_PK_RSA,
+ .priv_pk = GNUTLS_PK_RSA,
.hash = GNUTLS_DIG_SHA384,
+ .tls13_ok = 1,
.aid = {{8, 5}, SIG_SEM_DEFAULT}},
{.name = "RSA-PSS-SHA512",
.oid = PK_PKIX1_RSA_PSS_OID,
.id = GNUTLS_SIGN_RSA_PSS_SHA512,
.pk = GNUTLS_PK_RSA_PSS,
+ .priv_pk = GNUTLS_PK_RSA,
.hash = GNUTLS_DIG_SHA512,
- .aid = {{8, 6}, SIG_SEM_DEFAULT}},
- {.name = "RSA-PSS-SHA512",
+ .tls13_ok = 1,
+ .aid = {{8, 0x0B}, SIG_SEM_DEFAULT}},
+ {.name = "RSA-PSS-RSAE-SHA512",
.oid = PK_PKIX1_RSA_PSS_OID,
- .id = GNUTLS_SIGN_RSA_PSS_SHA512,
- .pk = GNUTLS_PK_RSA,
+ .id = GNUTLS_SIGN_RSA_PSS_RSAE_SHA512,
+ .pk = GNUTLS_PK_RSA_PSS,
+ .cert_pk = GNUTLS_PK_RSA,
+ .priv_pk = GNUTLS_PK_RSA,
.hash = GNUTLS_DIG_SHA512,
+ .tls13_ok = 1,
.aid = {{8, 6}, SIG_SEM_DEFAULT}},
/* Ed25519: The hash algorithm here is set to be SHA512, although that is
@@ -108,6 +120,7 @@ static const gnutls_sign_entry_st sign_algorithms[] = {
.id = GNUTLS_SIGN_EDDSA_ED25519,
.pk = GNUTLS_PK_EDDSA_ED25519,
.hash = GNUTLS_DIG_SHA512,
+ .tls13_ok = 1,
.aid = {{8, 7}, SIG_SEM_DEFAULT}},
/* ECDSA */
@@ -144,18 +157,21 @@ static const gnutls_sign_entry_st sign_algorithms[] = {
.pk = GNUTLS_PK_ECDSA,
.curve = GNUTLS_ECC_CURVE_SECP256R1,
.hash = GNUTLS_DIG_SHA256,
+ .tls13_ok = 1,
.aid = {{4, 3}, SIG_SEM_TLS13}},
{.name = "ECDSA-SECP384R1-SHA384",
.id = GNUTLS_SIGN_ECDSA_SECP384R1_SHA384,
.pk = GNUTLS_PK_ECDSA,
.curve = GNUTLS_ECC_CURVE_SECP384R1,
.hash = GNUTLS_DIG_SHA384,
+ .tls13_ok = 1,
.aid = {{5, 3}, SIG_SEM_TLS13}},
{.name = "ECDSA-SECP521R1-SHA512",
.id = GNUTLS_SIGN_ECDSA_SECP521R1_SHA512,
.pk = GNUTLS_PK_ECDSA,
.curve = GNUTLS_ECC_CURVE_SECP521R1,
.hash = GNUTLS_DIG_SHA512,
+ .tls13_ok = 1,
.aid = {{6, 3}, SIG_SEM_TLS13}},
/* ECDSA-SHA3 */
@@ -616,7 +632,8 @@ gnutls_sign_get_pk_algorithm(gnutls_sign_algorithm_t sign)
* @pk: is a public key algorithm
*
* This function returns non-zero if the public key algorithm corresponds to
- * the given signature algorithm.
+ * the given signature algorithm. That is, if that signature can be generated
+ * from the given private key algorithm.
*
* Since: 3.6.0
*
@@ -625,7 +642,16 @@ gnutls_sign_get_pk_algorithm(gnutls_sign_algorithm_t sign)
unsigned
gnutls_sign_supports_pk_algorithm(gnutls_sign_algorithm_t sign, gnutls_pk_algorithm_t pk)
{
- GNUTLS_SIGN_LOOP( if(p->id && p->id == sign && pk == p->pk) { return 1; } );
+ const gnutls_sign_entry_st *p;
+ unsigned r;
+
+ for(p = sign_algorithms; p->name != NULL; p++) {
+ if (p->id && p->id == sign) {
+ r = sign_supports_priv_pk_algorithm(p, pk);
+ if (r != 0)
+ return r;
+ }
+ }
return 0;
}
diff --git a/lib/buffers.c b/lib/buffers.c
index 414ea50307..52729f3723 100644
--- a/lib/buffers.c
+++ b/lib/buffers.c
@@ -900,17 +900,17 @@ parse_handshake_header(gnutls_session_t session, mbuffer_st * bufel,
return
gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET);
- hsk->htype = GNUTLS_HANDSHAKE_CLIENT_HELLO_V2;
+ hsk->rtype = hsk->htype = GNUTLS_HANDSHAKE_CLIENT_HELLO_V2;
hsk->sequence = 0;
hsk->start_offset = 0;
hsk->end_offset = hsk->length;
} else
#endif
- { /* TLS or DTLS handshake headers */
+ { /* TLS or DTLS handshake headers */
- hsk->htype = dataptr[0];
+ hsk->rtype = hsk->htype = dataptr[0];
/* we do not use DECR_LEN because we know
* that the packet has enough data.
@@ -932,6 +932,15 @@ parse_handshake_header(gnutls_session_t session, mbuffer_st * bufel,
MIN((_mbuffer_get_udata_size(bufel) -
handshake_header_size), hsk->length);
}
+
+ /* TLS1.3: distinguish server hello versus hello retry request.
+ * The epitome of slick protocol design. */
+ if (hsk->htype == GNUTLS_HANDSHAKE_SERVER_HELLO && hsk->start_offset == 0 && !IS_DTLS(session)) {
+ if (_mbuffer_get_udata_size(bufel) > handshake_header_size+2+GNUTLS_RANDOM_SIZE &&
+ memcmp(dataptr+handshake_header_size+2, HRR_RANDOM, GNUTLS_RANDOM_SIZE) == 0) {
+ hsk->htype = GNUTLS_HANDSHAKE_HELLO_RETRY_REQUEST;
+ }
+ }
}
data_size = _mbuffer_get_udata_size(bufel) - handshake_header_size;
diff --git a/lib/ext/dumbfw.c b/lib/ext/dumbfw.c
index 3ffeeca560..7faff65693 100644
--- a/lib/ext/dumbfw.c
+++ b/lib/ext/dumbfw.c
@@ -40,7 +40,7 @@ const hello_ext_entry_st ext_mod_dumbfw = {
.tls_id = 21,
.gid = GNUTLS_EXTENSION_DUMBFW,
.parse_type = GNUTLS_EXT_APPLICATION,
- .validity = GNUTLS_EXT_FLAG_CLIENT_HELLO|GNUTLS_EXT_FLAG_HRR,
+ .validity = GNUTLS_EXT_FLAG_CLIENT_HELLO,
.recv_func = NULL,
.send_func = _gnutls_dumbfw_send_params,
diff --git a/lib/ext/key_share.c b/lib/ext/key_share.c
index d4cf9b78c8..f110e10268 100644
--- a/lib/ext/key_share.c
+++ b/lib/ext/key_share.c
@@ -45,7 +45,7 @@ static int key_share_send_params(gnutls_session_t session,
const hello_ext_entry_st ext_mod_key_share = {
.name = "Key Share",
- .tls_id = 40,
+ .tls_id = 51,
.gid = GNUTLS_EXTENSION_KEY_SHARE,
.parse_type = _GNUTLS_EXT_TLS_POST_CS,
.validity = GNUTLS_EXT_FLAG_CLIENT_HELLO|GNUTLS_EXT_FLAG_TLS13_SERVER_HELLO|GNUTLS_EXT_FLAG_HRR,
diff --git a/lib/ext/signature.c b/lib/ext/signature.c
index 8b4bb1ac65..7bf2761fdf 100644
--- a/lib/ext/signature.c
+++ b/lib/ext/signature.c
@@ -283,6 +283,7 @@ _gnutls_session_get_sign_algo(gnutls_session_t session,
sig_ext_st *priv;
gnutls_ext_priv_data_t epriv;
unsigned int cert_algo;
+ const gnutls_sign_entry_st *se;
if (unlikely(ver == NULL))
return gnutls_assert_val(GNUTLS_SIGN_UNKNOWN);
@@ -304,23 +305,28 @@ _gnutls_session_get_sign_algo(gnutls_session_t session,
return ret;
}
+
+
for (i = 0; i < priv->sign_algorithms_size; i++) {
- _gnutls_handshake_log("checking cert compat with %s\n", gnutls_sign_algorithm_get_name(priv->sign_algorithms[i]));
+ se = _gnutls_sign_to_entry(priv->sign_algorithms[i]);
+ if (se == NULL)
+ continue;
+
+ _gnutls_handshake_log("checking cert compat with %s\n", se->name);
if (_gnutls_privkey_compatible_with_sig(privkey, priv->sign_algorithms[i]) == 0)
continue;
- if (gnutls_sign_supports_pk_algorithm(priv->sign_algorithms[i], cert_algo) != 0) {
+ if (sign_supports_cert_pk_algorithm(se, cert_algo) != 0) {
if (_gnutls_pubkey_compatible_with_sig
- (session, cert->pubkey, ver,
- priv->sign_algorithms[i]) < 0)
+ (session, cert->pubkey, ver, se->id) < 0)
continue;
if (_gnutls_session_sign_algo_enabled
- (session, priv->sign_algorithms[i]) < 0)
+ (session, se->id) < 0)
continue;
- return priv->sign_algorithms[i];
+ return se->id;
}
}
@@ -328,7 +334,7 @@ _gnutls_session_get_sign_algo(gnutls_session_t session,
* using algorithms we don't always enable by default (e.g., DSA-SHA1),
* continue and sign with it. */
if (client_cert) {
- _gnutls_audit_log(session, "No shared signature schemes with peer for client certificate (%s). Is the certificate a legacy one?",
+ _gnutls_audit_log(session, "No shared signature schemes with peer for client certificate (%s). Is the certificate a legacy one?\n",
gnutls_pk_get_name(cert_algo));
}
@@ -357,8 +363,9 @@ _gnutls_session_sign_algo_enabled(gnutls_session_t session,
if (ver->tls13_sem) {
/* disallow RSA, DSA, and SHA1 */
const gnutls_sign_entry_st *se;
+
se = _gnutls_sign_to_entry(sig);
- if (se == NULL || se->pk == GNUTLS_PK_RSA || se->pk == GNUTLS_PK_DSA || se->hash == GNUTLS_DIG_SHA1) {
+ if (se == NULL || (se->tls13_ok == 0)) {
gnutls_assert();
goto disallowed;
}
diff --git a/lib/ext/supported_versions.c b/lib/ext/supported_versions.c
index deca74039d..b2eff6be80 100644
--- a/lib/ext/supported_versions.c
+++ b/lib/ext/supported_versions.c
@@ -29,6 +29,7 @@
#include "num.h"
#include <hello_ext.h>
#include <ext/supported_versions.h>
+#include "handshake.h"
static int supported_versions_recv_params(gnutls_session_t session,
const uint8_t * data,
@@ -40,8 +41,9 @@ const hello_ext_entry_st ext_mod_supported_versions = {
.name = "Supported Versions",
.tls_id = 43,
.gid = GNUTLS_EXTENSION_SUPPORTED_VERSIONS,
- .validity = GNUTLS_EXT_FLAG_CLIENT_HELLO,
- .parse_type = GNUTLS_EXT_MANDATORY, /* force parsing prior to EXT_TLS extensions */
+ .validity = GNUTLS_EXT_FLAG_CLIENT_HELLO|GNUTLS_EXT_FLAG_TLS12_SERVER_HELLO|
+ GNUTLS_EXT_FLAG_TLS13_SERVER_HELLO|GNUTLS_EXT_FLAG_HRR,
+ .parse_type = GNUTLS_EXT_VERSION_NEG, /* force parsing prior to EXT_TLS extensions */
.recv_func = supported_versions_recv_params,
.send_func = supported_versions_send_params,
@@ -99,10 +101,32 @@ supported_versions_recv_params(gnutls_session_t session,
/* if we are here, none of the versions were acceptable */
return gnutls_assert_val(GNUTLS_E_UNSUPPORTED_VERSION_PACKET);
- } else {
- /* a server should never send this message */
- gnutls_assert();
- return GNUTLS_E_RECEIVED_ILLEGAL_EXTENSION;
+ } else { /* client */
+ const version_entry_st *vers;
+
+ DECR_LEN(data_size, 2);
+
+ if (data_size != 0)
+ return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
+
+ major = data[0];
+ minor = data[1];
+
+ vers = nversion_to_entry(major, minor);
+ if (!vers)
+ return gnutls_assert_val(GNUTLS_E_UNSUPPORTED_VERSION_PACKET);
+
+ set_adv_version(session, major, minor);
+ proto = _gnutls_version_get(major, minor);
+
+ _gnutls_handshake_log("EXT[%p]: Negotiated version: %d.%d\n",
+ session, (int)major, (int)minor);
+
+ ret = _gnutls_negotiate_version(session, proto, major, minor);
+ if (ret < 0) {
+ gnutls_assert();
+ return ret;
+ }
}
return 0;
@@ -116,10 +140,18 @@ supported_versions_send_params(gnutls_session_t session,
{
uint8_t versions[32];
size_t versions_size;
+ const version_entry_st *vers;
int ret;
/* this function sends the client extension data (dnsname) */
if (session->security_parameters.entity == GNUTLS_CLIENT) {
+ vers = _gnutls_version_max(session);
+
+ /* do not advertise this extension when we haven't TLS1.3
+ * enabled. */
+ if (vers && !vers->tls13_sem)
+ return 0;
+
ret = _gnutls_write_supported_versions(session, versions, sizeof(versions));
if (ret <= 0) /* if this function doesn't succeed do not send anything */
return 0;
@@ -131,6 +163,26 @@ supported_versions_send_params(gnutls_session_t session,
return gnutls_assert_val(ret);
return versions_size+2;
+ } else {
+ vers = get_version(session);
+ if (unlikely(vers == NULL))
+ return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
+
+ /* don't use this extension to negotiate versions <= 1.2,
+ * pretend we don't support it, so that we use a single
+ * code path to negotiate these protocols. */
+ if (!vers->tls13_sem)
+ return 0;
+
+ ret = _gnutls_buffer_append_data(extdata, &vers->major, 1);
+ if (ret < 0)
+ return gnutls_assert_val(ret);
+
+ ret = _gnutls_buffer_append_data(extdata, &vers->minor, 1);
+ if (ret < 0)
+ return gnutls_assert_val(ret);
+
+ return 2;
}
return 0;
diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h
index baa9c14589..1d75c4a09f 100644
--- a/lib/gnutls_int.h
+++ b/lib/gnutls_int.h
@@ -134,6 +134,16 @@ typedef struct {
#define GNUTLS_MASTER_SIZE 48
#define GNUTLS_RANDOM_SIZE 32
+#define HRR_RANDOM \
+ "\xCF\x21\xAD\x74\xE5\x9A\x61\x11\xBE\x1D\x8C\x02\x1E\x65\xB8\x91" \
+ "\xC2\xA2\x11\x16\x7A\xBB\x8C\x5E\x07\x9E\x09\xE2\xC8\xA8\x33\x9C"
+
+/* Under TLS1.3 a hello retry request is sent as server hello */
+#define REAL_HSK_TYPE(t) ((t)==GNUTLS_HANDSHAKE_HELLO_RETRY_REQUEST?GNUTLS_HANDSHAKE_SERVER_HELLO:t)
+
+/* Enable: Appendix D4. Middlebox Compatibility Mode */
+#define TLS13_APPENDIX_D4 1
+
/* DTLS */
#define DTLS_RETRANS_TIMEOUT 1000
@@ -254,9 +264,10 @@ typedef enum handshake_state_t { STATE0 = 0, STATE1, STATE2,
STATE15, STATE16, STATE17, STATE18, STATE19,
STATE20 = 20, STATE21, STATE22,
STATE30 = 30, STATE31, STATE40 = 40, STATE41, STATE50 = 50,
- STATE90=90, STATE91, STATE92, STATE93,
+ STATE90=90, STATE91, STATE92, STATE93, STATE99=99,
STATE100=100, STATE101, STATE102, STATE103, STATE104,
STATE105, STATE106, STATE107, STATE108, STATE109, STATE110,
+ STATE111,
STATE150 /* key update */
} handshake_state_t;
@@ -362,6 +373,10 @@ typedef enum content_type_t {
typedef struct {
/* Handshake layer type and sequence of message */
gnutls_handshake_description_t htype;
+
+ /* The "real" type received; that is, it does not distinguish
+ * HRR from server hello, while htype does */
+ gnutls_handshake_description_t rtype;
uint32_t length;
/* valid in DTLS */
diff --git a/lib/handshake-tls13.c b/lib/handshake-tls13.c
index 721f334eca..edb6e80574 100644
--- a/lib/handshake-tls13.c
+++ b/lib/handshake-tls13.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2017 Red Hat, Inc.
+ * Copyright (C) 2017-2018 Red Hat, Inc.
*
* Author: Nikos Mavrogiannopoulos
*
@@ -78,62 +78,72 @@ int _gnutls13_handshake_client(gnutls_session_t session)
int ret = 0;
switch (STATE) {
+ case STATE99:
case STATE100:
+#ifdef TLS13_APPENDIX_D4
+ /* We send it before keys are generated. That works because CCS
+ * is always being cached and queued and not being sent directly */
+ ret = _gnutls_send_change_cipher_spec(session, AGAIN(STATE100));
+ STATE = STATE100;
+ IMED_RET("send change cipher spec", ret, 0);
+#endif
+ /* fall through */
+ case STATE101:
ret =
generate_hs_traffic_keys(session);
- STATE = STATE100;
+ STATE = STATE101;
IMED_RET("generate session keys", ret, 0);
/* fall through */
- case STATE101:
+ case STATE102:
ret = _gnutls13_recv_encrypted_extensions(session);
- STATE = STATE101;
+ STATE = STATE102;
IMED_RET("recv encrypted extensions", ret, 0);
/* fall through */
- case STATE102:
+ case STATE103:
ret = _gnutls13_recv_certificate_request(session);
- STATE = STATE102;
+ STATE = STATE103;
IMED_RET("recv certificate request", ret, 0);
/* fall through */
- case STATE103:
+ case STATE104:
ret = _gnutls13_recv_certificate(session);
- STATE = STATE103;
+ STATE = STATE104;
IMED_RET("recv certificate", ret, 0);
/* fall through */
- case STATE104:
+ case STATE105:
ret = _gnutls13_recv_certificate_verify(session);
- STATE = STATE104;
+ STATE = STATE105;
IMED_RET("recv server certificate verify", ret, 0);
/* fall through */
- case STATE105:
+ case STATE106:
ret = _gnutls_run_verify_callback(session, GNUTLS_CLIENT);
- STATE = STATE105;
+ STATE = STATE106;
if (ret < 0)
return gnutls_assert_val(ret);
FALLTHROUGH;
- case STATE106:
- ret = _gnutls13_recv_finished(session);
- STATE = STATE106;
- IMED_RET("recv finished", ret, 0);
- /* fall through */
case STATE107:
- ret = _gnutls13_send_certificate(session, AGAIN(STATE107));
+ ret = _gnutls13_recv_finished(session);
STATE = STATE107;
- IMED_RET("send certificate", ret, 0);
+ IMED_RET("recv finished", ret, 0);
/* fall through */
case STATE108:
- ret = _gnutls13_send_certificate_verify(session, AGAIN(STATE108));
+ ret = _gnutls13_send_certificate(session, AGAIN(STATE108));
STATE = STATE108;
- IMED_RET("send certificate verify", ret, 0);
+ IMED_RET("send certificate", ret, 0);
/* fall through */
case STATE109:
- ret = _gnutls13_send_finished(session, AGAIN(STATE109));
+ ret = _gnutls13_send_certificate_verify(session, AGAIN(STATE109));
STATE = STATE109;
- IMED_RET("send finished", ret, 0);
+ IMED_RET("send certificate verify", ret, 0);
/* fall through */
case STATE110:
+ ret = _gnutls13_send_finished(session, AGAIN(STATE110));
+ STATE = STATE110;
+ IMED_RET("send finished", ret, 0);
+ /* fall through */
+ case STATE111:
ret =
generate_ap_traffic_keys(session);
- STATE = STATE110;
+ STATE = STATE111;
IMED_RET("generate app keys", ret, 0);
STATE = STATE0;
@@ -243,7 +253,7 @@ int _gnutls13_handshake_server(gnutls_session_t session)
/* this is triggered by post_client_hello, and instructs the
* handshake to proceed but be put on hold */
ret = GNUTLS_E_INTERRUPTED;
- STATE = STATE100; /* hello already parsed -> move on */
+ STATE = STATE99; /* hello already parsed -> move on */
} else {
STATE = STATE92;
}
@@ -255,62 +265,70 @@ int _gnutls13_handshake_server(gnutls_session_t session)
STATE = STATE93;
IMED_RET("send hello", ret, 0);
/* fall through */
+ case STATE99:
case STATE100:
- ret =
- generate_hs_traffic_keys(session);
+#ifdef TLS13_APPENDIX_D4
+ ret = _gnutls_send_change_cipher_spec(session, AGAIN(STATE100));
STATE = STATE100;
- IMED_RET("generate session keys", ret, 0);
+ IMED_RET("send change cipher spec", ret, 0);
+#endif
/* fall through */
case STATE101:
- ret = _gnutls13_send_encrypted_extensions(session, AGAIN(STATE101));
+ ret =
+ generate_hs_traffic_keys(session);
STATE = STATE101;
- IMED_RET("send encrypted extensions", ret, 0);
+ IMED_RET("generate session keys", ret, 0);
/* fall through */
case STATE102:
- ret = _gnutls13_send_certificate_request(session, AGAIN(STATE102));
+ ret = _gnutls13_send_encrypted_extensions(session, AGAIN(STATE102));
STATE = STATE102;
- IMED_RET("send certificate request", ret, 0);
+ IMED_RET("send encrypted extensions", ret, 0);
/* fall through */
case STATE103:
- ret = _gnutls13_send_certificate(session, AGAIN(STATE103));
+ ret = _gnutls13_send_certificate_request(session, AGAIN(STATE103));
STATE = STATE103;
- IMED_RET("send certificate", ret, 0);
+ IMED_RET("send certificate request", ret, 0);
/* fall through */
case STATE104:
- ret = _gnutls13_send_certificate_verify(session, AGAIN(STATE104));
+ ret = _gnutls13_send_certificate(session, AGAIN(STATE104));
STATE = STATE104;
- IMED_RET("send certificate verify", ret, 0);
+ IMED_RET("send certificate", ret, 0);
/* fall through */
case STATE105:
- ret = _gnutls13_send_finished(session, AGAIN(STATE105));
+ ret = _gnutls13_send_certificate_verify(session, AGAIN(STATE105));
STATE = STATE105;
- IMED_RET("send finished", ret, 0);
+ IMED_RET("send certificate verify", ret, 0);
/* fall through */
case STATE106:
- ret = _gnutls13_recv_certificate(session);
+ ret = _gnutls13_send_finished(session, AGAIN(STATE106));
STATE = STATE106;
- IMED_RET("recv certificate", ret, 0);
+ IMED_RET("send finished", ret, 0);
/* fall through */
case STATE107:
- ret = _gnutls13_recv_certificate_verify(session);
+ ret = _gnutls13_recv_certificate(session);
STATE = STATE107;
- IMED_RET("recv certificate verify", ret, 0);
+ IMED_RET("recv certificate", ret, 0);
/* fall through */
case STATE108:
- ret = _gnutls_run_verify_callback(session, GNUTLS_CLIENT);
+ ret = _gnutls13_recv_certificate_verify(session);
STATE = STATE108;
+ IMED_RET("recv certificate verify", ret, 0);
+ /* fall through */
+ case STATE109:
+ ret = _gnutls_run_verify_callback(session, GNUTLS_CLIENT);
+ STATE = STATE109;
if (ret < 0)
return gnutls_assert_val(ret);
/* fall through */
- case STATE109:
+ case STATE110:
ret = _gnutls13_recv_finished(session);
- STATE = STATE109;
+ STATE = STATE110;
IMED_RET("recv finished", ret, 0);
/* fall through */
- case STATE110:
+ case STATE111:
ret =
generate_ap_traffic_keys(session);
- STATE = STATE110;
+ STATE = STATE111;
IMED_RET("generate app keys", ret, 0);
STATE = STATE0;
diff --git a/lib/handshake.c b/lib/handshake.c
index 179fcb8009..955fd5dd08 100644
--- a/lib/handshake.c
+++ b/lib/handshake.c
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2000-2016 Free Software Foundation, Inc.
- * Copyright (C) 2015-2017 Red Hat, Inc.
+ * Copyright (C) 2015-2018 Red Hat, Inc.
*
* Author: Nikos Mavrogiannopoulos
*
@@ -422,14 +422,15 @@ _gnutls_finished(gnutls_session_t session, int type, void *ret,
/* returns the 0 on success or a negative error code.
*/
int
-_gnutls_negotiate_legacy_version(gnutls_session_t session,
+_gnutls_negotiate_version(gnutls_session_t session,
gnutls_protocol_t adv_version, uint8_t major, uint8_t minor)
{
const version_entry_st *vers;
/* if we do not support that version, unless that version is TLS 1.2;
* TLS 1.2 is handled separately because it is always advertized under TLS 1.3 or later */
- if (adv_version == GNUTLS_VERSION_UNKNOWN || _gnutls_version_is_supported(session, adv_version) == 0) {
+ if (adv_version == GNUTLS_VERSION_UNKNOWN ||
+ _gnutls_version_is_supported(session, adv_version) == 0) {
if (adv_version == GNUTLS_TLS1_2) {
vers = _gnutls_version_max(session);
@@ -477,6 +478,7 @@ _gnutls_user_hello_func(gnutls_session_t session,
gnutls_protocol_t adv_version, uint8_t major, uint8_t minor)
{
int ret, sret = 0;
+ const version_entry_st *vers;
if (session->internals.user_hello_func != NULL) {
ret = session->internals.user_hello_func(session);
@@ -489,13 +491,18 @@ _gnutls_user_hello_func(gnutls_session_t session,
return ret;
}
- /* Here we need to renegotiate the version since the callee might
- * have disabled some TLS versions.
- */
- ret = _gnutls_negotiate_legacy_version(session, adv_version, major, minor);
- if (ret < 0) {
- gnutls_assert();
- return ret;
+ vers = get_version(session);
+ if (!vers->tls13_sem) {
+ /* Here we need to renegotiate the version since the callee might
+ * have disabled some TLS versions. We only do it for TLS1.2 or
+ * earlier, as TLS1.3 uses a different set of ciphersuites, and
+ * thus we cannot fallback.
+ */
+ ret = _gnutls_negotiate_version(session, adv_version, major, minor);
+ if (ret < 0) {
+ gnutls_assert();
+ return ret;
+ }
}
}
return sret;
@@ -519,6 +526,7 @@ read_client_hello(gnutls_session_t session, uint8_t * data,
int len = datalen;
uint8_t major, minor;
uint8_t *suite_ptr, *comp_ptr, *session_id, *ext_ptr;
+ const version_entry_st *vers;
DECR_LEN(len, 2);
_gnutls_handshake_log("HSK[%p]: Client's version: %d.%d\n",
@@ -530,7 +538,7 @@ read_client_hello(gnutls_session_t session, uint8_t * data,
minor = data[pos+1];
set_adv_version(session, major, minor);
- neg_version = _gnutls_negotiate_legacy_version(session, adv_version, major, minor);
+ neg_version = _gnutls_negotiate_version(session, adv_version, major, minor);
if (neg_version < 0) {
gnutls_assert();
return neg_version;
@@ -598,46 +606,64 @@ read_client_hello(gnutls_session_t session, uint8_t * data,
ext_ptr = &data[pos];
ext_size = len;
- /* Parse only the mandatory to read extensions for resumption.
- * We don't want to parse any other extensions since
- * we don't want new extension values to override the
- * resumed ones.
- */
+ /* Parse only the mandatory to read extensions for resumption
+ * and version negotiation. We don't want to parse any other
+ * extensions since we don't want new extension values to override
+ * the resumed ones. */
ret =
_gnutls_parse_hello_extensions(session, GNUTLS_EXT_FLAG_CLIENT_HELLO,
- GNUTLS_EXT_MANDATORY,
- ext_ptr, ext_size);
- if (ret < 0) {
- gnutls_assert();
- return ret;
- }
+ GNUTLS_EXT_VERSION_NEG,
+ ext_ptr, ext_size);
+ if (ret < 0)
+ return gnutls_assert_val(ret);
ret =
- _gnutls_server_restore_session(session, session_id,
- session_id_len);
+ _gnutls_parse_hello_extensions(session, GNUTLS_EXT_FLAG_CLIENT_HELLO,
+ GNUTLS_EXT_MANDATORY,
+ ext_ptr, ext_size);
+ if (ret < 0)
+ return gnutls_assert_val(ret);
- if (session_id_len > 0)
- session->internals.resumption_requested = 1;
+ vers = get_version(session);
+ if (unlikely(vers == NULL))
+ return gnutls_assert_val(GNUTLS_E_UNSUPPORTED_VERSION_PACKET);
- if (ret == 0) { /* resumed using default TLS resumption! */
- ret = _gnutls_server_select_suite(session, suite_ptr, suite_size, 1);
- if (ret < 0)
- return gnutls_assert_val(ret);
+ if (!vers->tls13_sem) {
+ ret =
+ _gnutls_server_restore_session(session, session_id,
+ session_id_len);
- ret = resume_copy_required_values(session);
- if (ret < 0)
- return gnutls_assert_val(ret);
+ if (session_id_len > 0)
+ session->internals.resumption_requested = 1;
- session->internals.resumed = RESUME_TRUE;
+ if (ret == 0) { /* resumed using default TLS resumption! */
+ ret = _gnutls_server_select_suite(session, suite_ptr, suite_size, 1);
+ if (ret < 0)
+ return gnutls_assert_val(ret);
- return _gnutls_user_hello_func(session, adv_version, major, minor);
- } else {
- _gnutls_generate_session_id(session->security_parameters.
- session_id,
- &session->security_parameters.
- session_id_size);
+ ret = resume_copy_required_values(session);
+ if (ret < 0)
+ return gnutls_assert_val(ret);
+
+ session->internals.resumed = RESUME_TRUE;
+
+ return _gnutls_user_hello_func(session, adv_version, major, minor);
+ } else {
+ ret = _gnutls_generate_session_id(session->security_parameters.
+ session_id,
+ &session->security_parameters.
+ session_id_size);
+ if (ret < 0)
+ return gnutls_assert_val(ret);
- session->internals.resumed = RESUME_FALSE;
+ session->internals.resumed = RESUME_FALSE;
+ }
+ } else { /* TLS1.3 */
+ /* we echo client's session ID - length was checked previously */
+ assert(session_id_len <= GNUTLS_MAX_SESSION_ID_SIZE);
+ if (session_id_len > 0)
+ memcpy(session->security_parameters.session_id, session_id, session_id_len);
+ session->security_parameters.session_id_size = session_id_len;
}
/* Parse the extensions (if any)
@@ -646,8 +672,8 @@ read_client_hello(gnutls_session_t session, uint8_t * data,
* sslv3 and higher, even though sslv3 doesn't officially support them.
*/
ret = _gnutls_parse_hello_extensions(session, GNUTLS_EXT_FLAG_CLIENT_HELLO,
- GNUTLS_EXT_APPLICATION,
- ext_ptr, ext_size);
+ GNUTLS_EXT_APPLICATION,
+ ext_ptr, ext_size);
/* len is the rest of the parsed length */
if (ret < 0) {
gnutls_assert();
@@ -664,7 +690,7 @@ read_client_hello(gnutls_session_t session, uint8_t * data,
/* Session tickets are parsed in this point */
ret =
_gnutls_parse_hello_extensions(session, GNUTLS_EXT_FLAG_CLIENT_HELLO,
- GNUTLS_EXT_TLS, ext_ptr, ext_size);
+ GNUTLS_EXT_TLS, ext_ptr, ext_size);
if (ret < 0) {
gnutls_assert();
return ret;
@@ -1068,9 +1094,22 @@ inline
if ((session->internals.h_type == type
|| session->internals.h_type == GNUTLS_HANDSHAKE_ANY)
&& (session->internals.h_post == post
- || session->internals.h_post == GNUTLS_HOOK_BOTH))
+ || session->internals.h_post == GNUTLS_HOOK_BOTH)) {
+
+ /* internal API for testing: when we are expected to
+ * wait for GNUTLS_HANDSHAKE_CHANGE_CIPHER_SPEC, we
+ * do so, but not when doing for all messages. The
+ * reason is that change cipher specs are not handshake
+ * messages, and we don't support waiting for them
+ * consistently (only sending is tracked, not receiving).
+ */
+ if (type == GNUTLS_HANDSHAKE_CHANGE_CIPHER_SPEC &&
+ session->internals.h_type != GNUTLS_HANDSHAKE_CHANGE_CIPHER_SPEC)
+ return 0;
+
return session->internals.h_hook(session, type,
post, incoming, &msg);
+ }
}
return 0;
}
@@ -1104,7 +1143,7 @@ _gnutls_send_handshake(gnutls_session_t session, mbuffer_st * bufel,
i_datasize = _mbuffer_get_udata_size(bufel);
datasize = i_datasize + _mbuffer_get_uhead_size(bufel);
- data[pos++] = (uint8_t) type;
+ data[pos++] = (uint8_t) REAL_HSK_TYPE(type);
_gnutls_write_uint24(_mbuffer_get_udata_size(bufel), &data[pos]);
pos += 3;
@@ -1350,7 +1389,7 @@ _gnutls_recv_handshake(gnutls_session_t session,
goto cleanup;
}
- ret = handshake_hash_add_recvd(session, hsk.htype,
+ ret = handshake_hash_add_recvd(session, hsk.rtype,
hsk.header, hsk.header_size,
hsk.data.data,
hsk.data.length);
@@ -1549,11 +1588,11 @@ set_client_ciphersuite(gnutls_session_t session, uint8_t suite[2])
/* This function returns 0 if we are resuming a session or -1 otherwise.
* This also sets the variables in the session. Used only while reading a server
- * hello.
+ * hello. Only applicable to TLS1.2 or earlier.
*/
static int
client_check_if_resuming(gnutls_session_t session,
- uint8_t * session_id, int session_id_len)
+ uint8_t * session_id, int session_id_len)
{
char buf[2 * GNUTLS_MAX_SESSION_ID_SIZE + 1];
int ret;
@@ -1598,13 +1637,6 @@ client_check_if_resuming(gnutls_session_t session,
no_resume:
/* keep the new session id */
session->internals.resumed = RESUME_FALSE; /* we are not resuming */
- session->security_parameters.session_id_size =
- session_id_len;
- if (session_id_len > 0) {
- memcpy(session->security_parameters.session_id, session_id,
- session_id_len);
- }
-
return -1;
}
}
@@ -1619,11 +1651,14 @@ read_server_hello(gnutls_session_t session,
uint8_t * data, int datalen)
{
uint8_t session_id_len = 0;
+ uint8_t *session_id;
+ uint8_t *cs_pos, *comp_pos, *srandom_pos;
+ uint8_t major, minor;
int pos = 0;
int ret = 0;
int len = datalen;
- const version_entry_st *vers;
- gnutls_ext_flags_t ext_parse_flag;
+ unsigned ext_parse_flag = 0;
+ const version_entry_st *vers, *saved_vers;
if (datalen < GNUTLS_RANDOM_SIZE+2) {
gnutls_assert();
@@ -1634,14 +1669,17 @@ read_server_hello(gnutls_session_t session,
session, data[pos], data[pos + 1]);
DECR_LEN(len, 2);
- vers = nversion_to_entry(data[pos], data[pos + 1]);
+ major = data[pos];
+ minor = data[pos+1];
+
+ saved_vers = get_version(session); /* will be non-null if HRR has been received */
+
+ vers = nversion_to_entry(major, minor);
if (unlikely(vers == NULL))
return gnutls_assert_val(GNUTLS_E_UNSUPPORTED_VERSION_PACKET);
- if (_gnutls_version_is_supported(session, vers->id) == 0) {
- gnutls_assert();
- return GNUTLS_E_UNSUPPORTED_VERSION_PACKET;
- }
+ if (vers->tls13_sem) /* that shouldn't have been negotiated here */
+ return gnutls_assert_val(GNUTLS_E_UNSUPPORTED_VERSION_PACKET);
if (_gnutls_set_current_version(session, vers->id) < 0)
return gnutls_assert_val(GNUTLS_E_UNSUPPORTED_VERSION_PACKET);
@@ -1649,64 +1687,100 @@ read_server_hello(gnutls_session_t session,
pos += 2;
DECR_LEN(len, GNUTLS_RANDOM_SIZE);
- ret = _gnutls_set_server_random(session, vers, &data[pos]);
+ srandom_pos = &data[pos];
+ pos += GNUTLS_RANDOM_SIZE;
+
+ /* Read session ID
+ */
+ DECR_LEN(len, 1);
+ session_id_len = data[pos++];
+
+ if (len < session_id_len || session_id_len > GNUTLS_MAX_SESSION_ID_SIZE) {
+ gnutls_assert();
+ return GNUTLS_E_ILLEGAL_PARAMETER;
+ }
+ DECR_LEN(len, session_id_len);
+ session_id = &data[pos];
+ pos += session_id_len;
+
+ DECR_LEN(len, 2);
+ cs_pos = &data[pos];
+ pos += 2;
+
+ /* move to compression
+ */
+ DECR_LEN(len, 1);
+ comp_pos = &data[pos];
+ pos++;
+
+ /* parse extensions to figure version */
+ ret =
+ _gnutls_parse_hello_extensions(session, GNUTLS_EXT_FLAG_TLS12_SERVER_HELLO|
+ GNUTLS_EXT_FLAG_TLS13_SERVER_HELLO,
+ GNUTLS_EXT_VERSION_NEG,
+ &data[pos], len);
if (ret < 0)
return gnutls_assert_val(ret);
- pos += GNUTLS_RANDOM_SIZE;
+ vers = get_version(session);
+ if (unlikely(vers == NULL))
+ return gnutls_assert_val(GNUTLS_E_UNSUPPORTED_VERSION_PACKET);
+ if (vers->tls13_sem) {
+ if (major != 0x03 || minor != 0x03)
+ return gnutls_assert_val(GNUTLS_E_UNSUPPORTED_VERSION_PACKET);
+ }
- if (!vers->tls13_sem) {
- /* Read session ID
- */
- DECR_LEN(len, 1);
- session_id_len = data[pos++];
+ if (_gnutls_version_is_supported(session, vers->id) == 0)
+ return gnutls_assert_val(GNUTLS_E_UNSUPPORTED_VERSION_PACKET);
- if (len < session_id_len || session_id_len > GNUTLS_MAX_SESSION_ID_SIZE) {
- gnutls_assert();
- return GNUTLS_E_ILLEGAL_PARAMETER;
- }
- DECR_LEN(len, session_id_len);
+ /* set server random - done after final version is selected */
+ ret = _gnutls_set_server_random(session, vers, srandom_pos);
+ if (ret < 0)
+ return gnutls_assert_val(ret);
- /* check if we are resuming and set the appropriate
- * values;
- */
- if (client_check_if_resuming
- (session, &data[pos], session_id_len) == 0) {
- pos += session_id_len + 2 + 1;
- DECR_LEN(len, 2 + 1);
+ /* check if we are resuming and set the appropriate
+ * values;
+ */
+ if (!vers->tls13_sem &&
+ client_check_if_resuming(session, session_id, session_id_len) == 0) {
- ret =
- _gnutls_parse_hello_extensions(session, GNUTLS_EXT_FLAG_TLS12_SERVER_HELLO,
- GNUTLS_EXT_MANDATORY,
- &data[pos], len);
- if (ret < 0) {
- gnutls_assert();
- return ret;
- }
- return 0;
- }
+ ret =
+ _gnutls_parse_hello_extensions(session, GNUTLS_EXT_FLAG_TLS12_SERVER_HELLO,
+ GNUTLS_EXT_MANDATORY,
+ &data[pos], len);
+ if (ret < 0)
+ return gnutls_assert_val(ret);
- pos += session_id_len;
+ return 0;
+ } else {
+ session->security_parameters.session_id_size = session_id_len;
+ if (session_id_len > 0)
+ memcpy(session->security_parameters.session_id, session_id,
+ session_id_len);
}
/* Check if the given cipher suite is supported and copy
* it to the session.
*/
-
- DECR_LEN(len, 2);
- ret = set_client_ciphersuite(session, &data[pos]);
+ ret = set_client_ciphersuite(session, cs_pos);
if (ret < 0) {
gnutls_assert();
return ret;
}
- pos += 2;
if (session->internals.hsk_flags & HSK_HRR_RECEIVED) {
/* check if ciphersuite matches */
- if (memcmp(session->security_parameters.cs->id, session->internals.hrr_cs, 2) != 0)
+ if (memcmp(cs_pos, session->internals.hrr_cs, 2) != 0)
+ return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
+
+ /* check if HRR version matches this version */
+ if (vers != saved_vers)
return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
}
+ if (*comp_pos != 0)
+ return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
+
if (vers->tls13_sem) {
/* TLS 1.3 Early Secret */
ret = _tls13_init_secret(session, NULL, 0);
@@ -1719,46 +1793,42 @@ read_server_hello(gnutls_session_t session,
if (ret < 0)
return gnutls_assert_val(ret);
- ext_parse_flag = GNUTLS_EXT_FLAG_TLS13_SERVER_HELLO;
+ ext_parse_flag |= GNUTLS_EXT_FLAG_TLS13_SERVER_HELLO;
} else {
- /* move to compression
- */
- DECR_LEN(len, 1);
- pos++;
- ext_parse_flag = GNUTLS_EXT_FLAG_TLS12_SERVER_HELLO;
+ ext_parse_flag |= GNUTLS_EXT_FLAG_TLS12_SERVER_HELLO;
}
/* Parse extensions in order.
*/
ret =
_gnutls_parse_hello_extensions(session,
- ext_parse_flag,
- GNUTLS_EXT_MANDATORY,
- &data[pos], len);
+ ext_parse_flag,
+ GNUTLS_EXT_MANDATORY,
+ &data[pos], len);
if (ret < 0)
return gnutls_assert_val(ret);
ret =
_gnutls_parse_hello_extensions(session,
- ext_parse_flag,
- GNUTLS_EXT_APPLICATION,
- &data[pos], len);
+ ext_parse_flag,
+ GNUTLS_EXT_APPLICATION,
+ &data[pos], len);
if (ret < 0)
return gnutls_assert_val(ret);
ret =
_gnutls_parse_hello_extensions(session,
- ext_parse_flag,
- GNUTLS_EXT_TLS,
- &data[pos], len);
+ ext_parse_flag,
+ GNUTLS_EXT_TLS,
+ &data[pos], len);
if (ret < 0)
return gnutls_assert_val(ret);
ret =
_gnutls_parse_hello_extensions(session,
- ext_parse_flag,
- _GNUTLS_EXT_TLS_POST_CS,
- &data[pos], len);
+ ext_parse_flag,
+ _GNUTLS_EXT_TLS_POST_CS,
+ &data[pos], len);
if (ret < 0)
return gnutls_assert_val(ret);
@@ -1793,7 +1863,7 @@ static int send_client_hello(gnutls_session_t session, int again)
mbuffer_st *bufel = NULL;
int type;
int ret = 0;
- const version_entry_st *hver, *min_ver;
+ const version_entry_st *hver, *min_ver, *max_ver;
uint8_t tver[2];
gnutls_buffer_st extdata;
int rehandshake = 0;
@@ -1829,7 +1899,8 @@ static int send_client_hello(gnutls_session_t session, int again)
if (hver == NULL) {
gnutls_assert();
- return GNUTLS_E_NO_PRIORITIES_WERE_SET;
+ ret = GNUTLS_E_NO_PRIORITIES_WERE_SET;
+ goto cleanup;
}
if (unlikely(session->internals.default_hello_version[0] != 0)) {
@@ -1848,7 +1919,8 @@ static int send_client_hello(gnutls_session_t session, int again)
(unsigned)tver[0], (unsigned)tver[1]);
min_ver = _gnutls_version_lowest(session);
- if (min_ver == NULL) {
+ max_ver = _gnutls_version_max(session);
+ if (min_ver == NULL || max_ver == NULL) {
gnutls_assert();
ret = GNUTLS_E_NO_PRIORITIES_WERE_SET;
goto cleanup;
@@ -1858,8 +1930,10 @@ static int send_client_hello(gnutls_session_t session, int again)
* (RSA uses it).
*/
set_adv_version(session, hver->major, hver->minor);
- if (_gnutls_set_current_version(session, hver->id) < 0)
- return gnutls_assert_val(GNUTLS_E_UNSUPPORTED_VERSION_PACKET);
+ if (_gnutls_set_current_version(session, hver->id) < 0) {
+ ret = gnutls_assert_val(GNUTLS_E_UNSUPPORTED_VERSION_PACKET);
+ goto cleanup;
+ }
if (session->internals.priorities->min_record_version != 0) {
/* Advertize the lowest supported (SSL 3.0) record packet
@@ -1882,24 +1956,43 @@ static int send_client_hello(gnutls_session_t session, int again)
if (!(session->internals.hsk_flags & HSK_HRR_RECEIVED) &&
!(IS_DTLS(session) && session->internals.dtls.hsk_hello_verify_requests == 0)) {
ret = _gnutls_gen_client_random(session);
- if (ret < 0)
- return gnutls_assert_val(ret);
+ if (ret < 0) {
+ gnutls_assert();
+ goto cleanup;
+ }
}
ret = _gnutls_buffer_append_data(&extdata,
- session->security_parameters.client_random,
- GNUTLS_RANDOM_SIZE);
+ session->security_parameters.client_random,
+ GNUTLS_RANDOM_SIZE);
if (ret < 0) {
gnutls_assert();
goto cleanup;
}
- /* Copy the Session ID
+#ifdef TLS13_APPENDIX_D4
+ if (max_ver->tls13_sem &&
+ session->security_parameters.session_id_size == 0) {
+
+ /* Under TLS1.3 we generate a random session ID to make
+ * the TLS1.3 session look like a resumed TLS1.2 session */
+ ret = _gnutls_generate_session_id(session->security_parameters.
+ session_id,
+ &session->security_parameters.
+ session_id_size);
+ if (ret < 0) {
+ gnutls_assert();
+ goto cleanup;
+ }
+ }
+#endif
+
+ /* Copy the Session ID - if any
*/
ret = _gnutls_buffer_append_data_prefix(&extdata, 8,
- session->internals.resumed_security_parameters.session_id,
- session_id_len);
+ session->internals.resumed_security_parameters.session_id,
+ session_id_len);
if (ret < 0) {
gnutls_assert();
goto cleanup;
@@ -1957,8 +2050,8 @@ static int send_client_hello(gnutls_session_t session, int again)
ret =
_gnutls_gen_hello_extensions(session, &extdata,
- GNUTLS_EXT_FLAG_CLIENT_HELLO,
- type);
+ GNUTLS_EXT_FLAG_CLIENT_HELLO,
+ type);
if (ret < 0) {
gnutls_assert();
goto cleanup;
@@ -1986,7 +2079,8 @@ int _gnutls_send_server_hello(gnutls_session_t session, int again)
session->security_parameters.session_id_size;
char tmpbuf[2 * GNUTLS_MAX_SESSION_ID_SIZE + 1];
const version_entry_st *vers;
- gnutls_ext_flags_t ext_parse_flag;
+ uint8_t vbytes[2];
+ unsigned extflag = 0;
_gnutls_buffer_init(&buf);
@@ -2001,50 +2095,46 @@ int _gnutls_send_server_hello(gnutls_session_t session, int again)
if (ret < 0)
return gnutls_assert_val(ret);
- ext_parse_flag = GNUTLS_EXT_FLAG_TLS13_SERVER_HELLO;
+ vbytes[0] = 0x03; /* TLS1.2 */
+ vbytes[1] = 0x03;
+ extflag |= GNUTLS_EXT_FLAG_TLS13_SERVER_HELLO;
} else {
- ext_parse_flag = GNUTLS_EXT_FLAG_TLS12_SERVER_HELLO;
+ vbytes[0] = vers->major;
+ vbytes[1] = vers->minor;
+ extflag |= GNUTLS_EXT_FLAG_TLS12_SERVER_HELLO;
}
ret = _gnutls_buffer_init_handshake_mbuffer(&buf);
if (ret < 0)
return gnutls_assert_val(ret);
- ret = _gnutls_buffer_append_data(&buf, &vers->major, 1);
+ ret = _gnutls_buffer_append_data(&buf, vbytes, 2);
if (ret < 0) {
gnutls_assert();
goto fail;
}
- ret = _gnutls_buffer_append_data(&buf, &vers->minor, 1);
+ ret = _gnutls_buffer_append_data(&buf,
+ session->security_parameters.server_random,
+ GNUTLS_RANDOM_SIZE);
if (ret < 0) {
gnutls_assert();
goto fail;
}
- ret = _gnutls_buffer_append_data(&buf,
- session->security_parameters.server_random,
- GNUTLS_RANDOM_SIZE);
+ ret = _gnutls_buffer_append_data_prefix(&buf, 8,
+ session->security_parameters.session_id,
+ session_id_len);
if (ret < 0) {
gnutls_assert();
goto fail;
}
- if (!vers->tls13_sem) {
- ret = _gnutls_buffer_append_data_prefix(&buf, 8,
- session->security_parameters.session_id,
- session_id_len);
- if (ret < 0) {
- gnutls_assert();
- goto fail;
- }
-
- _gnutls_handshake_log("HSK[%p]: SessionID: %s\n", session,
- _gnutls_bin2hex(session->
- security_parameters.session_id,
- session_id_len, tmpbuf,
- sizeof(tmpbuf), NULL));
- }
+ _gnutls_handshake_log("HSK[%p]: SessionID: %s\n", session,
+ _gnutls_bin2hex(session->
+ security_parameters.session_id,
+ session_id_len, tmpbuf,
+ sizeof(tmpbuf), NULL));
ret = _gnutls_buffer_append_data(&buf,
session->security_parameters.cs->id,
@@ -2054,17 +2144,16 @@ int _gnutls_send_server_hello(gnutls_session_t session, int again)
goto fail;
}
- if (!vers->tls13_sem) {
- ret = _gnutls_buffer_append_prefix(&buf, 8, 0);
- if (ret < 0) {
- gnutls_assert();
- goto fail;
- }
+ /* compression */
+ ret = _gnutls_buffer_append_prefix(&buf, 8, 0);
+ if (ret < 0) {
+ gnutls_assert();
+ goto fail;
}
ret =
_gnutls_gen_hello_extensions(session, &buf,
- ext_parse_flag,
+ extflag,
(session->internals.resumed ==
RESUME_TRUE) ?
GNUTLS_EXT_MANDATORY :
@@ -2556,7 +2645,7 @@ static int handshake_client(gnutls_session_t session)
const version_entry_st *ver;
reset:
- if (STATE >= STATE100)
+ if (STATE >= STATE99)
return _gnutls13_handshake_client(session);
switch (STATE) {
@@ -2605,7 +2694,7 @@ static int handshake_client(gnutls_session_t session)
case STATE4:
ver = get_version(session);
if (ver->tls13_sem) { /* TLS 1.3 state machine */
- STATE = STATE100;
+ STATE = STATE99;
goto reset;
}
@@ -2778,7 +2867,7 @@ static int handshake_client(gnutls_session_t session)
/* This function is to be called if the handshake was successfully
* completed. This sends a Change Cipher Spec packet to the peer.
*/
-static ssize_t send_change_cipher_spec(gnutls_session_t session, int again)
+ssize_t _gnutls_send_change_cipher_spec(gnutls_session_t session, int again)
{
uint8_t *data;
mbuffer_st *bufel;
@@ -2786,7 +2875,7 @@ static ssize_t send_change_cipher_spec(gnutls_session_t session, int again)
const version_entry_st *vers;
if (again == 0) {
- bufel = _gnutls_handshake_alloc(session, 1);
+ bufel = _gnutls_handshake_alloc(session, 3); /* max for DTLS0.9 */
if (bufel == NULL)
return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
@@ -2809,6 +2898,13 @@ static ssize_t send_change_cipher_spec(gnutls_session_t session, int again)
session->internals.dtls.hsk_write_seq++;
}
+ ret = call_hook_func(session, GNUTLS_HANDSHAKE_CHANGE_CIPHER_SPEC, GNUTLS_HOOK_PRE, 0,
+ data, 1);
+ if (ret < 0) {
+ _mbuffer_xfree(&bufel);
+ return gnutls_assert_val(ret);
+ }
+
ret =
_gnutls_handshake_io_cache_int(session,
GNUTLS_HANDSHAKE_CHANGE_CIPHER_SPEC,
@@ -2818,6 +2914,12 @@ static ssize_t send_change_cipher_spec(gnutls_session_t session, int again)
return gnutls_assert_val(ret);
}
+ ret = call_hook_func(session, GNUTLS_HANDSHAKE_CHANGE_CIPHER_SPEC, GNUTLS_HOOK_POST, 0,
+ data, 1);
+ if (ret < 0) {
+ return gnutls_assert_val(ret);
+ }
+
_gnutls_handshake_log("REC[%p]: Sent ChangeCipherSpec\n",
session);
}
@@ -2836,7 +2938,7 @@ static int send_handshake_final(gnutls_session_t session, int init)
switch (FINAL_STATE) {
case STATE0:
case STATE1:
- ret = send_change_cipher_spec(session, FAGAIN(STATE1));
+ ret = _gnutls_send_change_cipher_spec(session, FAGAIN(STATE1));
FINAL_STATE = STATE0;
if (ret < 0) {
@@ -3021,7 +3123,7 @@ static int handshake_server(gnutls_session_t session)
ver = get_version(session);
if (ver->tls13_sem) { /* TLS 1.3 state machine */
- STATE = STATE100;
+ STATE = STATE99;
goto reset;
}
diff --git a/lib/handshake.h b/lib/handshake.h
index 109f1247c8..1096226410 100644
--- a/lib/handshake.h
+++ b/lib/handshake.h
@@ -64,13 +64,15 @@ int _gnutls_generate_session_id(uint8_t * session_id, uint8_t * len);
int _gnutls_gen_server_random(gnutls_session_t session, int version);
void _gnutls_set_client_random(gnutls_session_t session, uint8_t * rnd);
+ssize_t _gnutls_send_change_cipher_spec(gnutls_session_t session, int again);
+
int _gnutls_send_server_hello(gnutls_session_t session, int again);
int _gnutls_find_pk_algos_in_ciphersuites(uint8_t * data, int datalen);
int _gnutls_server_select_suite(gnutls_session_t session, uint8_t * data,
unsigned int datalen, unsigned int scsv_only);
-int _gnutls_negotiate_legacy_version(gnutls_session_t session,
+int _gnutls_negotiate_version(gnutls_session_t session,
gnutls_protocol_t adv_version, uint8_t major, uint8_t minor);
int _gnutls_user_hello_func(gnutls_session_t session,
gnutls_protocol_t adv_version, uint8_t major, uint8_t minor);
diff --git a/lib/includes/gnutls/gnutls.h.in b/lib/includes/gnutls/gnutls.h.in
index b9142519aa..5b449d148c 100644
--- a/lib/includes/gnutls/gnutls.h.in
+++ b/lib/includes/gnutls/gnutls.h.in
@@ -534,7 +534,6 @@ typedef enum {
GNUTLS_HANDSHAKE_HELLO_VERIFY_REQUEST = 3,
GNUTLS_HANDSHAKE_NEW_SESSION_TICKET = 4,
GNUTLS_HANDSHAKE_END_OF_EARLY_DATA = 5,
- GNUTLS_HANDSHAKE_HELLO_RETRY_REQUEST = 6,
GNUTLS_HANDSHAKE_ENCRYPTED_EXTENSIONS = 8,
GNUTLS_HANDSHAKE_CERTIFICATE_PKT = 11,
GNUTLS_HANDSHAKE_SERVER_KEY_EXCHANGE = 12,
@@ -547,7 +546,8 @@ typedef enum {
GNUTLS_HANDSHAKE_SUPPLEMENTAL = 23,
GNUTLS_HANDSHAKE_KEY_UPDATE = 24,
GNUTLS_HANDSHAKE_CHANGE_CIPHER_SPEC = 254,
- GNUTLS_HANDSHAKE_CLIENT_HELLO_V2 = 1024
+ GNUTLS_HANDSHAKE_CLIENT_HELLO_V2 = 1024,
+ GNUTLS_HANDSHAKE_HELLO_RETRY_REQUEST = 1025,
} gnutls_handshake_description_t;
#define GNUTLS_HANDSHAKE_ANY ((unsigned int)-1)
@@ -797,9 +797,21 @@ const char *gnutls_pk_algorithm_get_name(gnutls_pk_algorithm_t algorithm);
* @GNUTLS_SIGN_RSA_SHA3_256: Digital signature algorithm RSA with SHA3-256.
* @GNUTLS_SIGN_RSA_SHA3_384: Digital signature algorithm RSA with SHA3-384.
* @GNUTLS_SIGN_RSA_SHA3_512: Digital signature algorithm RSA with SHA3-512.
- * @GNUTLS_SIGN_RSA_PSS_SHA256: Digital signature algorithm RSA with SHA-256, with PSS padding.
- * @GNUTLS_SIGN_RSA_PSS_SHA384: Digital signature algorithm RSA with SHA-384, with PSS padding.
- * @GNUTLS_SIGN_RSA_PSS_SHA512: Digital signature algorithm RSA with SHA-512, with PSS padding.
+ * @GNUTLS_SIGN_RSA_PSS_RSAE_SHA256: Digital signature algorithm RSA with SHA-256,
+ * with PSS padding (RSA PKCS#1 1.5 certificate). This signature is identical
+ * to #GNUTLS_SIGN_RSA_PSS_SHA256, but they are distinct as the TLS1.3 protocol
+ * treats them differently.
+ * @GNUTLS_SIGN_RSA_PSS_RSAE_SHA384: Digital signature algorithm RSA with SHA-384,
+ * with PSS padding (RSA PKCS#1 1.5 certificate). This signature is identical
+ * to #GNUTLS_SIGN_RSA_PSS_SHA384, but they are distinct as the TLS1.3 protocol
+ * treats them differently.
+ * @GNUTLS_SIGN_RSA_PSS_RSAE_SHA512: Digital signature algorithm RSA with SHA-512,
+ * with PSS padding (RSA PKCS#1 1.5 certificate). This signature is identical
+ * to #GNUTLS_SIGN_RSA_PSS_SHA512, but they are distinct as the TLS1.3 protocol
+ * treats them differently.
+ * @GNUTLS_SIGN_RSA_PSS_SHA256: Digital signature algorithm RSA with SHA-256, with PSS padding (RSA-PSS certificate).
+ * @GNUTLS_SIGN_RSA_PSS_SHA384: Digital signature algorithm RSA with SHA-384, with PSS padding (RSA-PSS certificate).
+ * @GNUTLS_SIGN_RSA_PSS_SHA512: Digital signature algorithm RSA with SHA-512, with PSS padding (RSA-PSS certificate).
* @GNUTLS_SIGN_EDDSA_ED25519: Digital signature algorithm EdDSA with Ed25519 curve.
*
* Enumeration of different digital signature algorithms.
@@ -849,7 +861,11 @@ typedef enum {
GNUTLS_SIGN_ECDSA_SECP256R1_SHA256 = 37,
GNUTLS_SIGN_ECDSA_SECP384R1_SHA384 = 38,
GNUTLS_SIGN_ECDSA_SECP521R1_SHA512 = 39,
- GNUTLS_SIGN_MAX = GNUTLS_SIGN_ECDSA_SECP521R1_SHA512
+
+ GNUTLS_SIGN_RSA_PSS_RSAE_SHA256 = 40,
+ GNUTLS_SIGN_RSA_PSS_RSAE_SHA384 = 41,
+ GNUTLS_SIGN_RSA_PSS_RSAE_SHA512 = 42,
+ GNUTLS_SIGN_MAX = GNUTLS_SIGN_RSA_PSS_RSAE_SHA512
} gnutls_sign_algorithm_t;
/**
@@ -2715,25 +2731,24 @@ int gnutls_ext_raw_parse(void *ctx, gnutls_ext_raw_process_func cb,
/**
* gnutls_ext_parse_type_t:
- * @GNUTLS_EXT_NONE: Never parsed
- * @GNUTLS_EXT_ANY: Any extension type (internal use only).
- * @GNUTLS_EXT_APPLICATION: Application extension.
- * @GNUTLS_EXT_TLS: TLS-internal extension.
- * @GNUTLS_EXT_MANDATORY: Extension parsed even if resuming (or extensions are disabled).
+ * @GNUTLS_EXT_NONE: Never to be parsed
+ * @GNUTLS_EXT_ANY: Any extension type (should not be used as it is used only internally).
+ * @GNUTLS_EXT_VERSION_NEG: Extensions to be parsed first for TLS version negotiation.
+ * @GNUTLS_EXT_MANDATORY: Parsed after @GNUTLS_EXT_VERSION_NEG and even when resuming.
+ * @GNUTLS_EXT_APPLICATION: Parsed after @GNUTLS_EXT_MANDATORY
+ * @GNUTLS_EXT_TLS: TLS-internal extensions, parsed after @GNUTLS_EXT_APPLICATION.
*
- * Enumeration of different TLS extension parsing types. This type is
- * to indicate whether an extension is useful to application
- * level or TLS level only. This is used to decide the appropriate time
- * each extension is parsed at during the server or client hello parsing.
+ * Enumeration of different TLS extension parsing phases. The @gnutls_ext_parse_type_t
+ * indicates the time/phase an extension is parsed during Client or Server hello parsing.
*
- * This applies to TLS 1.2 and earlier versions.
*/
typedef enum {
GNUTLS_EXT_ANY = 0,
GNUTLS_EXT_APPLICATION = 1,
GNUTLS_EXT_TLS = 2,
GNUTLS_EXT_MANDATORY = 3,
- GNUTLS_EXT_NONE = 4
+ GNUTLS_EXT_NONE = 4,
+ GNUTLS_EXT_VERSION_NEG = 5
} gnutls_ext_parse_type_t;
/**
diff --git a/lib/priority.c b/lib/priority.c
index a83a1ffc78..8e2132ffea 100644
--- a/lib/priority.c
+++ b/lib/priority.c
@@ -349,6 +349,7 @@ static const int* cipher_priority_secure192 = _cipher_priority_secure192;
static const int _sign_priority_default[] = {
GNUTLS_SIGN_RSA_SHA256,
GNUTLS_SIGN_RSA_PSS_SHA256,
+ GNUTLS_SIGN_RSA_PSS_RSAE_SHA256,
GNUTLS_SIGN_ECDSA_SHA256,
GNUTLS_SIGN_ECDSA_SECP256R1_SHA256,
@@ -356,11 +357,13 @@ static const int _sign_priority_default[] = {
GNUTLS_SIGN_RSA_SHA384,
GNUTLS_SIGN_RSA_PSS_SHA384,
+ GNUTLS_SIGN_RSA_PSS_RSAE_SHA384,
GNUTLS_SIGN_ECDSA_SHA384,
GNUTLS_SIGN_ECDSA_SECP384R1_SHA384,
GNUTLS_SIGN_RSA_SHA512,
GNUTLS_SIGN_RSA_PSS_SHA512,
+ GNUTLS_SIGN_RSA_PSS_RSAE_SHA512,
GNUTLS_SIGN_ECDSA_SHA512,
GNUTLS_SIGN_ECDSA_SECP521R1_SHA512,
@@ -391,17 +394,20 @@ static const int* sign_priority_suiteb192 = _sign_priority_suiteb192;
static const int _sign_priority_secure128[] = {
GNUTLS_SIGN_RSA_SHA256,
GNUTLS_SIGN_RSA_PSS_SHA256,
+ GNUTLS_SIGN_RSA_PSS_RSAE_SHA256,
GNUTLS_SIGN_ECDSA_SHA256,
GNUTLS_SIGN_ECDSA_SECP256R1_SHA256,
GNUTLS_SIGN_EDDSA_ED25519,
GNUTLS_SIGN_RSA_SHA384,
GNUTLS_SIGN_RSA_PSS_SHA384,
+ GNUTLS_SIGN_RSA_PSS_RSAE_SHA384,
GNUTLS_SIGN_ECDSA_SHA384,
GNUTLS_SIGN_ECDSA_SECP384R1_SHA384,
GNUTLS_SIGN_RSA_SHA512,
GNUTLS_SIGN_RSA_PSS_SHA512,
+ GNUTLS_SIGN_RSA_PSS_RSAE_SHA512,
GNUTLS_SIGN_ECDSA_SHA512,
GNUTLS_SIGN_ECDSA_SECP521R1_SHA512,
@@ -412,10 +418,12 @@ static const int* sign_priority_secure128 = _sign_priority_secure128;
static const int _sign_priority_secure192[] = {
GNUTLS_SIGN_RSA_SHA384,
GNUTLS_SIGN_RSA_PSS_SHA384,
+ GNUTLS_SIGN_RSA_PSS_RSAE_SHA384,
GNUTLS_SIGN_ECDSA_SHA384,
GNUTLS_SIGN_ECDSA_SECP384R1_SHA384,
GNUTLS_SIGN_RSA_SHA512,
GNUTLS_SIGN_RSA_PSS_SHA512,
+ GNUTLS_SIGN_RSA_PSS_RSAE_SHA512,
GNUTLS_SIGN_ECDSA_SHA512,
GNUTLS_SIGN_ECDSA_SECP521R1_SHA512,
diff --git a/lib/privkey.c b/lib/privkey.c
index 10afdf90f1..e5b7e83965 100644
--- a/lib/privkey.c
+++ b/lib/privkey.c
@@ -1148,13 +1148,13 @@ gnutls_privkey_sign_data2(gnutls_privkey_t signer,
{
int ret;
gnutls_x509_spki_st params;
- const gnutls_sign_entry_st *e;
+ const gnutls_sign_entry_st *se;
if (flags & GNUTLS_PRIVKEY_SIGN_FLAG_TLS1_RSA)
return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
- e = _gnutls_sign_to_entry(algo);
- if (e == NULL)
+ se = _gnutls_sign_to_entry(algo);
+ if (se == NULL)
return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
ret = _gnutls_privkey_get_spki_params(signer, &params);
@@ -1163,14 +1163,14 @@ gnutls_privkey_sign_data2(gnutls_privkey_t signer,
return ret;
}
- ret = _gnutls_privkey_update_spki_params(signer, e->pk, e->hash,
+ ret = _gnutls_privkey_update_spki_params(signer, se->pk, se->hash,
flags, &params);
if (ret < 0) {
gnutls_assert();
return ret;
}
- return privkey_sign_and_hash_data(signer, _gnutls_sign_to_entry(algo), data, signature, &params);
+ return privkey_sign_and_hash_data(signer, se, data, signature, &params);
}
/**
@@ -1831,8 +1831,13 @@ unsigned _gnutls_privkey_compatible_with_sig(gnutls_privkey_t privkey,
* and RSA keys which cannot do RSA-PSS (e.g., smart card) from
* negotiating RSA-PSS sig.
*/
- if (privkey->pk_algorithm == GNUTLS_PK_RSA_PSS && se->pk != GNUTLS_PK_RSA_PSS) {
+
+ if (se->pk != privkey->pk_algorithm) { /* if the PK algorithm of the signature differs to the one on the pubkey */
+ if (!sign_supports_priv_pk_algorithm(se, privkey->pk_algorithm)) {
+ _gnutls_handshake_log("cannot use privkey of %s with %s\n",
+ gnutls_pk_get_name(privkey->pk_algorithm), se->name);
return 0;
+ }
}
if (privkey->type == GNUTLS_PRIVKEY_EXT) {
diff --git a/lib/pubkey.c b/lib/pubkey.c
index 466e2dee63..d6d374b786 100644
--- a/lib/pubkey.c
+++ b/lib/pubkey.c
@@ -1518,7 +1518,7 @@ int fixup_spki_params(const gnutls_pk_params_st *key_params, const gnutls_sign_e
unsigned bits;
if (se->pk != key_params->algo) {
- if (!gnutls_sign_supports_pk_algorithm(se->id, key_params->algo)) {
+ if (!sign_supports_priv_pk_algorithm(se, key_params->algo)) {
_gnutls_debug_log("have key: %s/%d, with sign %s/%d\n",
gnutls_pk_get_name(key_params->algo), key_params->algo,
se->name, se->id);
@@ -1729,7 +1729,7 @@ int pubkey_supports_sig(gnutls_pubkey_t pubkey,
gnutls_ecc_curve_t curve = pubkey->params.curve;
if (curve != se->curve) {
- _gnutls_debug_log("have key: ECDSA with %s/%d, with sign %s/%d\n",
+ _gnutls_handshake_log("have key: ECDSA with %s/%d, with sign %s/%d\n",
gnutls_ecc_curve_get_name(curve), (int)curve,
se->name, se->id);
return gnutls_assert_val(GNUTLS_E_INCOMPATIBLE_SIG_WITH_KEY);
@@ -1737,8 +1737,8 @@ int pubkey_supports_sig(gnutls_pubkey_t pubkey,
}
if (se->pk != pubkey->params.algo) { /* if the PK algorithm of the signature differs to the one on the pubkey */
- if (!gnutls_sign_supports_pk_algorithm(se->id, pubkey->params.algo)) {
- _gnutls_debug_log("have key: %s/%d, with sign %s/%d\n",
+ if (!sign_supports_priv_pk_algorithm(se, pubkey->params.algo)) {
+ _gnutls_handshake_log("have key: %s/%d, with sign %s/%d\n",
gnutls_pk_get_name(pubkey->params.algo), pubkey->params.algo,
se->name, se->id);
return gnutls_assert_val(GNUTLS_E_INCOMPATIBLE_SIG_WITH_KEY);
diff --git a/lib/record.c b/lib/record.c
index 577a15aef8..a8ba45032d 100644
--- a/lib/record.c
+++ b/lib/record.c
@@ -1,6 +1,7 @@
/*
- * Copyright (C) 2000-2016 Free Software Foundation, Inc.
- * Copyright (C) 2012-2016 Nikos Mavrogiannopoulos
+ * Copyright (C) 2000-2018 Free Software Foundation, Inc.
+ * Copyright (C) 2012-2018 Nikos Mavrogiannopoulos
+ * Copyright (C) 2018 Red Hat, Inc.
*
* Author: Nikos Mavrogiannopoulos
*
@@ -372,7 +373,7 @@ copy_record_version(gnutls_session_t session,
if (lver->tls13_sem) {
version[0] = 0x03;
- version[1] = 0x01;
+ version[1] = 0x03;
} else {
version[0] = lver->major;
version[1] = lver->minor;
@@ -687,8 +688,8 @@ record_check_version(gnutls_session_t session,
int diff = 0;
if (vers->tls13_sem) {
- /* TLS 1.3 requires version to be 0x0301 */
- if (version[0] != 0x03 || version[1] != 0x01)
+ /* TLS 1.3 requires version to be 0x0303 */
+ if (version[0] != 0x03 || version[1] != 0x03)
diff = 1;
} else {
if (vers->major != version[0] || vers->minor != version[1])
@@ -1195,14 +1196,15 @@ _gnutls_recv_in_buffers(gnutls_session_t session, content_type_t type,
mbuffer_st *bufel = NULL, *decrypted = NULL;
gnutls_datum_t t;
int ret;
- unsigned int empty_fragments = 0;
+ unsigned int n_retries = 0;
record_parameters_st *record_params;
record_state_st *record_state;
struct tls_record_st record;
+ const version_entry_st *vers = get_version(session);
- begin:
+ begin:
- if (empty_fragments > DEFAULT_MAX_EMPTY_RECORDS) {
+ if (n_retries > DEFAULT_MAX_EMPTY_RECORDS) {
gnutls_assert();
return GNUTLS_E_TOO_MANY_EMPTY_PACKETS;
}
@@ -1263,6 +1265,18 @@ _gnutls_recv_in_buffers(gnutls_session_t session, content_type_t type,
if (bufel == NULL)
return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
+ if (vers && vers->tls13_sem && record.type == GNUTLS_CHANGE_CIPHER_SPEC &&
+ record.length == 1 && session->internals.handshake_in_progress) {
+ _gnutls_read_log("discarding change cipher spec in TLS1.3\n");
+ /* we use the same mechanism to retry as when
+ * receiving multiple empty TLS packets */
+ bufel =
+ _mbuffer_head_pop_first(&session->internals.
+ record_recv_buffer);
+ _mbuffer_xfree(&bufel);
+ n_retries++;
+ goto begin;
+ }
/* We allocate the maximum possible to allow few compressed bytes to expand to a
* full record. Moreover we add space for any pad and the MAC (in case
@@ -1362,7 +1376,7 @@ _gnutls_recv_in_buffers(gnutls_session_t session, content_type_t type,
*/
if (_mbuffer_get_udata_size(decrypted) == 0) {
_mbuffer_xfree(&decrypted);
- empty_fragments++;
+ n_retries++;
goto begin;
}
@@ -1387,7 +1401,7 @@ _gnutls_recv_in_buffers(gnutls_session_t session, content_type_t type,
return ret;
- discard:
+ discard:
session->internals.dtls.packets_dropped++;
/* discard the whole received fragment. */
@@ -1397,7 +1411,7 @@ _gnutls_recv_in_buffers(gnutls_session_t session, content_type_t type,
_mbuffer_xfree(&bufel);
return gnutls_assert_val(GNUTLS_E_AGAIN);
- sanity_check_error:
+ sanity_check_error:
if (IS_DTLS(session)) {
session->internals.dtls.packets_dropped++;
ret = gnutls_assert_val(GNUTLS_E_AGAIN);
@@ -1407,11 +1421,11 @@ _gnutls_recv_in_buffers(gnutls_session_t session, content_type_t type,
session_unresumable(session);
session_invalidate(session);
- cleanup:
+ cleanup:
_mbuffer_xfree(&decrypted);
return ret;
- recv_error:
+ recv_error:
if (ret < 0
&& (gnutls_error_is_fatal(ret) == 0
|| ret == GNUTLS_E_TIMEDOUT))
diff --git a/lib/sslv2_compat.c b/lib/sslv2_compat.c
index 882cbd628d..d466cc30f1 100644
--- a/lib/sslv2_compat.c
+++ b/lib/sslv2_compat.c
@@ -112,7 +112,7 @@ _gnutls_read_client_hello_v2(gnutls_session_t session, uint8_t * data,
adv_version = _gnutls_version_get(major, minor);
- ret = _gnutls_negotiate_legacy_version(session, adv_version, major, minor);
+ ret = _gnutls_negotiate_version(session, adv_version, major, minor);
if (ret < 0) {
gnutls_assert();
return ret;
diff --git a/lib/tls-sig.c b/lib/tls-sig.c
index 26b36e6115..87016172e2 100644
--- a/lib/tls-sig.c
+++ b/lib/tls-sig.c
@@ -87,6 +87,9 @@ _gnutls_handshake_sign_data12(gnutls_session_t session,
("HSK[%p]: signing TLS 1.2 handshake data: using %s\n", session,
gnutls_sign_algorithm_get_name(sign_algo));
+ if (unlikely(gnutls_sign_supports_pk_algorithm(sign_algo, pkey->pk_algorithm) == 0))
+ return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
+
dconcat.size = GNUTLS_RANDOM_SIZE*2 + params->size;
dconcat.data = gnutls_malloc(dconcat.size);
if (dconcat.data == NULL)
@@ -121,7 +124,8 @@ _gnutls_handshake_sign_data10(gnutls_session_t session,
const mac_entry_st *me;
gnutls_pk_algorithm_t pk_algo;
- if (gnutls_privkey_get_pk_algorithm(pkey, NULL) == GNUTLS_PK_RSA)
+ pk_algo = gnutls_privkey_get_pk_algorithm(pkey, NULL);
+ if (pk_algo == GNUTLS_PK_RSA)
me = hash_to_entry(GNUTLS_DIG_MD5_SHA1);
else
me = hash_to_entry(
@@ -129,6 +133,9 @@ _gnutls_handshake_sign_data10(gnutls_session_t session,
if (me == NULL)
return gnutls_assert_val(GNUTLS_E_UNKNOWN_HASH_ALGORITHM);
+ if (unlikely(gnutls_sign_supports_pk_algorithm(sign_algo, pk_algo) == 0))
+ return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
+
pk_algo = gnutls_sign_get_pk_algorithm(sign_algo);
if (pk_algo == GNUTLS_PK_UNKNOWN)
return gnutls_assert_val(GNUTLS_E_UNKNOWN_PK_ALGORITHM);
diff --git a/lib/tls13-sig.c b/lib/tls13-sig.c
index 8995fa456c..334052df2c 100644
--- a/lib/tls13-sig.c
+++ b/lib/tls13-sig.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2017 Red Hat, Inc.
+ * Copyright (C) 2017-2018 Red Hat, Inc.
*
* Author: Nikos Mavrogiannopoulos
*
@@ -61,14 +61,18 @@ _gnutls13_handshake_verify_data(gnutls_session_t session,
if (ret < 0)
return gnutls_assert_val(ret);
+ if (unlikely(sign_supports_cert_pk_algorithm(se, cert->pubkey->params.algo) == 0)) {
+ _gnutls_handshake_log("HSK[%p]: certificate of %s cannot be combined with %s sig\n",
+ session, gnutls_pk_get_name(cert->pubkey->params.algo), se->name);
+ return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
+ }
+
ret =
_gnutls_session_sign_algo_enabled(session, se->id);
if (ret < 0)
return gnutls_assert_val(ret);
- if (se->hash == GNUTLS_DIG_SHA1) /* explicitly prohibited */
- return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
- if (se->pk == GNUTLS_PK_RSA) /* explicitly prohibited */
+ if (se->tls13_ok == 0) /* explicitly prohibited */
return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
_gnutls_buffer_init(&buf);
@@ -140,7 +144,10 @@ _gnutls13_handshake_sign_data(gnutls_session_t session,
gnutls_buffer_st buf;
uint8_t prefix[PREFIX_SIZE];
- if (unlikely(se == NULL || se->hash == GNUTLS_DIG_SHA1 || se->pk == GNUTLS_PK_RSA))
+ if (unlikely(se == NULL || se->tls13_ok == 0))
+ return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
+
+ if (unlikely(sign_supports_priv_pk_algorithm(se, pkey->pk_algorithm) == 0))
return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
_gnutls_handshake_log
diff --git a/lib/tls13/hello_retry.c b/lib/tls13/hello_retry.c
index 59f965cd57..51f545ec00 100644
--- a/lib/tls13/hello_retry.c
+++ b/lib/tls13/hello_retry.c
@@ -34,6 +34,7 @@ int _gnutls13_send_hello_retry_request(gnutls_session_t session, unsigned again)
mbuffer_st *bufel = NULL;
gnutls_buffer_st buf;
const version_entry_st *ver;
+ const uint8_t vbuf[2] = {0x03, 0x03};
if (again == 0) {
ver = get_version(session);
@@ -44,11 +45,21 @@ int _gnutls13_send_hello_retry_request(gnutls_session_t session, unsigned again)
if (ret < 0)
return gnutls_assert_val(ret);
- ret = _gnutls_buffer_append_data(&buf, &ver->major, 1);
+ ret = _gnutls_buffer_append_data(&buf, vbuf, 2);
if (ret < 0)
return gnutls_assert_val(ret);
- ret = _gnutls_buffer_append_data(&buf, &ver->minor, 1);
+ ret = _gnutls_buffer_append_data(&buf,
+ HRR_RANDOM,
+ GNUTLS_RANDOM_SIZE);
+ if (ret < 0) {
+ gnutls_assert();
+ goto cleanup;
+ }
+
+ ret = _gnutls_buffer_append_data_prefix(&buf, 8,
+ session->security_parameters.session_id,
+ session->security_parameters.session_id_size);
if (ret < 0) {
gnutls_assert();
goto cleanup;
@@ -60,6 +71,13 @@ int _gnutls13_send_hello_retry_request(gnutls_session_t session, unsigned again)
goto cleanup;
}
+ /* compression */
+ ret = _gnutls_buffer_append_prefix(&buf, 8, 0);
+ if (ret < 0) {
+ gnutls_assert();
+ goto cleanup;
+ }
+
ret = _gnutls_gen_hello_extensions(session, &buf,
GNUTLS_EXT_FLAG_HRR,
GNUTLS_EXT_ANY);
@@ -85,11 +103,12 @@ int
_gnutls13_recv_hello_retry_request(gnutls_session_t session,
gnutls_buffer_st *buf)
{
- const version_entry_st *vers;
int ret;
uint8_t tmp[2];
const gnutls_cipher_suite_entry_st *cs;
const mac_entry_st *prf;
+ gnutls_datum_t session_id;
+ uint8_t random[GNUTLS_RANDOM_SIZE];
/* only under TLS 1.3 */
if (IS_DTLS(session))
@@ -100,20 +119,27 @@ _gnutls13_recv_hello_retry_request(gnutls_session_t session,
session->internals.hsk_flags |= HSK_HRR_RECEIVED;
+ /* version */
ret = _gnutls_buffer_pop_data(buf, tmp, 2);
if (ret < 0)
return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
- vers = nversion_to_entry(tmp[0], tmp[1]);
- if (unlikely(vers == NULL))
+ if (unlikely(tmp[0] != 0x03 || tmp[1] != 0x03))
return gnutls_assert_val(GNUTLS_E_UNSUPPORTED_VERSION_PACKET);
- if (_gnutls_version_is_supported(session, vers->id) == 0)
- return gnutls_assert_val(GNUTLS_E_UNSUPPORTED_VERSION_PACKET);
+ ret = _gnutls_buffer_pop_data(buf, random, GNUTLS_RANDOM_SIZE);
+ if (ret < 0)
+ return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
- if (_gnutls_set_current_version(session, vers->id) < 0)
- return gnutls_assert_val(GNUTLS_E_UNSUPPORTED_VERSION_PACKET);
+ if (memcmp(random, HRR_RANDOM, GNUTLS_RANDOM_SIZE) != 0) {
+ return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
+ }
+ ret = _gnutls_buffer_pop_datum_prefix8(buf, &session_id);
+ if (ret < 0)
+ return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
+
+ /* read ciphersuites */
ret = _gnutls_buffer_pop_data(buf, tmp, 2);
if (ret < 0)
return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
@@ -123,13 +149,20 @@ _gnutls13_recv_hello_retry_request(gnutls_session_t session,
return gnutls_assert_val(GNUTLS_E_UNKNOWN_CIPHER_SUITE);
_gnutls_handshake_log("EXT[%p]: Hello Retry Request with %s\n", session, cs->name);
-
memcpy(session->internals.hrr_cs, cs->id, 2);
prf = mac_to_entry(cs->prf);
if (unlikely(prf == NULL))
return gnutls_assert_val(GNUTLS_E_UNKNOWN_CIPHER_SUITE);
+ /* compression */
+ ret = _gnutls_buffer_pop_data(buf, tmp, 1);
+ if (ret < 0)
+ return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
+
+ if (unlikely(tmp[0] != 0))
+ return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
+
ret = _gnutls13_handshake_hash_buffers_synth(session, prf, 1);
if (ret < 0)
return gnutls_assert_val(ret);
@@ -139,6 +172,15 @@ _gnutls13_recv_hello_retry_request(gnutls_session_t session,
return gnutls_assert_val(GNUTLS_E_UNEXPECTED_EXTENSIONS_LENGTH);
}
+ /* figure version first */
+ ret =
+ _gnutls_parse_hello_extensions(session, GNUTLS_EXT_FLAG_HRR,
+ GNUTLS_EXT_VERSION_NEG,
+ buf->data, buf->length);
+ if (ret < 0)
+ return gnutls_assert_val(ret);
+
+ /* parse the rest of extensions */
ret = _gnutls_parse_hello_extensions(session, GNUTLS_EXT_FLAG_HRR, GNUTLS_EXT_ANY,
buf->data, buf->length);
if (ret < 0)
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 66766b632c..36a493cdc7 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -112,6 +112,8 @@ ctests += tls13/multi-ocsp
ctests += tls13/ocsp-client
+ctests += tls13/change_cipher_spec
+
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/common-cert-key-exchange.c b/tests/common-cert-key-exchange.c
index ed79973bfe..3f3ce085f5 100644
--- a/tests/common-cert-key-exchange.c
+++ b/tests/common-cert-key-exchange.c
@@ -49,6 +49,94 @@ static void tls_log_func(int level, const char *str)
#define MSG "hello there ppl"
+void try_with_key_fail(const char *name, const char *client_prio,
+ int server_err, int client_err,
+ const gnutls_datum_t *serv_cert,
+ const gnutls_datum_t *serv_key,
+ const gnutls_datum_t *cli_cert,
+ const gnutls_datum_t *cli_key)
+{
+ int ret;
+ /* Server stuff. */
+ gnutls_certificate_credentials_t serverx509cred;
+ gnutls_session_t server;
+ int sret = GNUTLS_E_AGAIN;
+ /* Client stuff. */
+ gnutls_certificate_credentials_t clientx509cred;
+ gnutls_session_t client;
+ int cret = GNUTLS_E_AGAIN;
+ const char *err;
+
+ /* General init. */
+ gnutls_global_set_log_function(tls_log_func);
+ if (debug)
+ gnutls_global_set_log_level(6);
+
+ reset_buffers();
+ /* Init server */
+ gnutls_certificate_allocate_credentials(&serverx509cred);
+
+ ret = gnutls_certificate_set_x509_key_mem(serverx509cred,
+ serv_cert, serv_key,
+ GNUTLS_X509_FMT_PEM);
+ if (ret < 0)
+ fail("Could not set key/cert: %s\n", gnutls_strerror(ret));
+
+ gnutls_init(&server, GNUTLS_SERVER);
+ gnutls_credentials_set(server, GNUTLS_CRD_CERTIFICATE,
+ serverx509cred);
+
+
+ if (server_priority)
+ assert(gnutls_priority_set_direct(server, server_priority, NULL) >= 0);
+ else
+ assert(gnutls_priority_set_direct(server, client_prio, NULL) >= 0);
+
+ gnutls_transport_set_push_function(server, server_push);
+ gnutls_transport_set_pull_function(server, server_pull);
+ gnutls_transport_set_ptr(server, server);
+
+ /* Init client */
+ ret = gnutls_certificate_allocate_credentials(&clientx509cred);
+ if (ret < 0)
+ exit(1);
+
+ if (cli_cert) {
+ gnutls_certificate_set_x509_key_mem(clientx509cred,
+ cli_cert, cli_key,
+ GNUTLS_X509_FMT_PEM);
+ gnutls_certificate_server_set_request(server, GNUTLS_CERT_REQUIRE);
+ }
+
+ ret = gnutls_init(&client, GNUTLS_CLIENT);
+ if (ret < 0)
+ exit(1);
+
+ ret = gnutls_credentials_set(client, GNUTLS_CRD_CERTIFICATE,
+ clientx509cred);
+ if (ret < 0)
+ exit(1);
+
+ gnutls_transport_set_push_function(client, client_push);
+ gnutls_transport_set_pull_function(client, client_pull);
+ gnutls_transport_set_ptr(client, client);
+
+ ret = gnutls_priority_set_direct(client, client_prio, &err);
+ if (ret < 0) {
+ if (ret == GNUTLS_E_INVALID_REQUEST)
+ fprintf(stderr, "Error in %s\n", err);
+ exit(1);
+ }
+ success("negotiating %s\n", name);
+ HANDSHAKE_EXPECT(client, server, client_err, server_err);
+
+ gnutls_deinit(client);
+ gnutls_deinit(server);
+
+ gnutls_certificate_free_credentials(serverx509cred);
+ gnutls_certificate_free_credentials(clientx509cred);
+}
+
void try_with_key_ks(const char *name, const char *client_prio, gnutls_kx_algorithm_t client_kx,
gnutls_sign_algorithm_t server_sign_algo,
gnutls_sign_algorithm_t client_sign_algo,
diff --git a/tests/common-cert-key-exchange.h b/tests/common-cert-key-exchange.h
index 4c7d6c0ca9..b52c95ea72 100644
--- a/tests/common-cert-key-exchange.h
+++ b/tests/common-cert-key-exchange.h
@@ -36,7 +36,7 @@ extern const char *server_priority;
&server_ca3_localhost_cert, &server_ca3_key, NULL, NULL, 0)
#define try_ks(name, client_prio, client_kx, group) \
- try_with_key_ks(name, client_prio, client_kx, GNUTLS_SIGN_RSA_PSS_SHA256, GNUTLS_SIGN_UNKNOWN, \
+ try_with_key_ks(name, client_prio, client_kx, GNUTLS_SIGN_RSA_PSS_RSAE_SHA256, GNUTLS_SIGN_UNKNOWN, \
&server_ca3_localhost_cert, &server_ca3_key, NULL, NULL, 0, group)
#define try_cli(name, client_prio, client_kx, server_sign_algo, client_sign_algo, client_cert) \
@@ -67,6 +67,13 @@ void try_with_key(const char *name, const char *client_prio, gnutls_kx_algorithm
serv_cert, serv_key, cli_cert, cli_key, client_cert, 0);
}
+void try_with_key_fail(const char *name, const char *client_prio,
+ int server_err, int client_err,
+ const gnutls_datum_t *serv_cert,
+ const gnutls_datum_t *serv_key,
+ const gnutls_datum_t *cli_cert,
+ const gnutls_datum_t *cli_key);
+
#define dtls_try(name, client_prio, client_kx, server_sign_algo, client_sign_algo) \
dtls_try_with_key(name, client_prio, client_kx, server_sign_algo, client_sign_algo, \
&server_ca3_localhost_cert, &server_ca3_key, NULL, NULL, 0)
diff --git a/tests/dtls12-cert-key-exchange.c b/tests/dtls12-cert-key-exchange.c
index 0903cafe66..82028041d7 100644
--- a/tests/dtls12-cert-key-exchange.c
+++ b/tests/dtls12-cert-key-exchange.c
@@ -48,8 +48,8 @@ void doit(void)
dtls_try_with_key("DTLS 1.2 with ecdhe ecdsa no-cli-cert", "NORMAL:-VERS-ALL:+VERS-DTLS1.2:-KX-ALL:+ECDHE-ECDSA", GNUTLS_KX_ECDHE_ECDSA, GNUTLS_SIGN_ECDSA_SHA256, GNUTLS_SIGN_UNKNOWN,
&server_ca3_localhost_ecc_cert, &server_ca3_ecc_key, NULL, NULL, 0);
- dtls_try("DTLS 1.2 with ecdhe rsa-pss sig no-cli-cert", "NORMAL:-VERS-ALL:+VERS-DTLS1.2:-KX-ALL:+ECDHE-RSA:-SIGN-ALL:+SIGN-RSA-PSS-SHA256", GNUTLS_KX_ECDHE_RSA, GNUTLS_SIGN_RSA_PSS_SHA256, GNUTLS_SIGN_UNKNOWN);
- dtls_try("DTLS 1.2 with ecdhe rsa-pss no-cli-cert", "NORMAL:-VERS-ALL:+VERS-DTLS1.2:-KX-ALL:+ECDHE-RSA:-SIGN-ALL:+SIGN-RSA-PSS-SHA256", GNUTLS_KX_ECDHE_RSA, GNUTLS_SIGN_RSA_PSS_SHA256, GNUTLS_SIGN_UNKNOWN);
+ dtls_try("DTLS 1.2 with ecdhe rsa-pss sig no-cli-cert", "NORMAL:-VERS-ALL:+VERS-DTLS1.2:-KX-ALL:+ECDHE-RSA:-SIGN-ALL:+SIGN-RSA-PSS-RSAE-SHA256", GNUTLS_KX_ECDHE_RSA, GNUTLS_SIGN_RSA_PSS_RSAE_SHA256, GNUTLS_SIGN_UNKNOWN);
+ dtls_try("DTLS 1.2 with ecdhe rsa-pss no-cli-cert", "NORMAL:-VERS-ALL:+VERS-DTLS1.2:-KX-ALL:+ECDHE-RSA:-SIGN-ALL:+SIGN-RSA-PSS-RSAE-SHA256", GNUTLS_KX_ECDHE_RSA, GNUTLS_SIGN_RSA_PSS_RSAE_SHA256, GNUTLS_SIGN_UNKNOWN);
dtls_try_with_key("TLS 1.2 with ecdhe rsa-pss/rsa-pss no-cli-cert", "NORMAL:-VERS-ALL:+VERS-DTLS1.2:-KX-ALL:+ECDHE-RSA:-SIGN-ALL:+SIGN-RSA-PSS-SHA256", GNUTLS_KX_ECDHE_RSA, GNUTLS_SIGN_RSA_PSS_SHA256, GNUTLS_SIGN_UNKNOWN,
&server_ca3_rsa_pss_cert, &server_ca3_rsa_pss_key, NULL, NULL, 0);
dtls_try("DTLS 1.2 with rsa no-cli-cert", "NORMAL:-VERS-ALL:+VERS-DTLS1.2:-KX-ALL:+RSA", GNUTLS_KX_RSA, GNUTLS_SIGN_UNKNOWN, GNUTLS_SIGN_UNKNOWN);
@@ -63,7 +63,7 @@ void doit(void)
&server_ca3_localhost_ecc_cert, &server_ca3_ecc_key, &server_ca3_localhost_ecc_cert, &server_ca3_ecc_key, USE_CERT);
- dtls_try_cli("DTLS 1.2 with ecdhe-rsa-pss cli-cert", "NORMAL:-VERS-ALL:+VERS-DTLS1.2:-KX-ALL:+ECDHE-RSA:-SIGN-ALL:+SIGN-RSA-PSS-SHA256", GNUTLS_KX_ECDHE_RSA, GNUTLS_SIGN_RSA_PSS_SHA256, GNUTLS_SIGN_RSA_PSS_SHA256, USE_CERT);
+ dtls_try_cli("DTLS 1.2 with ecdhe-rsa-pss cli-cert", "NORMAL:-VERS-ALL:+VERS-DTLS1.2:-KX-ALL:+ECDHE-RSA:-SIGN-ALL:+SIGN-RSA-PSS-RSAE-SHA256", GNUTLS_KX_ECDHE_RSA, GNUTLS_SIGN_RSA_PSS_RSAE_SHA256, GNUTLS_SIGN_RSA_PSS_RSAE_SHA256, USE_CERT);
dtls_try_with_key("DTLS 1.2 with ecdhe-rsa-pss/rsa-pss cli-cert", "NORMAL:-VERS-ALL:+VERS-DTLS1.2:-KX-ALL:+ECDHE-RSA:-SIGN-ALL:+SIGN-RSA-PSS-SHA256", GNUTLS_KX_ECDHE_RSA, GNUTLS_SIGN_RSA_PSS_SHA256, GNUTLS_SIGN_RSA_PSS_SHA256,
&server_ca3_rsa_pss_cert, &server_ca3_rsa_pss_key, &cli_ca3_rsa_pss_cert, &cli_ca3_rsa_pss_key, USE_CERT);
dtls_try_cli("DTLS 1.2 with dhe-rsa ask cli-cert", "NORMAL:-VERS-ALL:+VERS-DTLS1.2:-KX-ALL:+DHE-RSA", GNUTLS_KX_DHE_RSA, GNUTLS_SIGN_RSA_SHA256, GNUTLS_SIGN_UNKNOWN, ASK_CERT);
diff --git a/tests/pkcs11/tls-neg-pkcs11-key.c b/tests/pkcs11/tls-neg-pkcs11-key.c
index c85d8789df..c32dee27a6 100644
--- a/tests/pkcs11/tls-neg-pkcs11-key.c
+++ b/tests/pkcs11/tls-neg-pkcs11-key.c
@@ -286,7 +286,7 @@ static const test_st tests[] = {
},
{.name = "tls1.2: rsa-pss cert, rsa-sign key no PSS signatures",
.pk = GNUTLS_PK_RSA,
- .prio = "NORMAL:+ECDHE-RSA:+ECDHE-ECDSA:-VERS-TLS-ALL:+VERS-TLS1.2:-SIGN-RSA-PSS-SHA256:-SIGN-RSA-PSS-SHA384:-SIGN-RSA-PSS-SHA512",
+ .prio = "NORMAL:+ECDHE-RSA:+ECDHE-ECDSA:-VERS-TLS-ALL:+VERS-TLS1.2:-SIGN-RSA-PSS-SHA256:-SIGN-RSA-PSS-SHA384:-SIGN-RSA-PSS-SHA512:-SIGN-RSA-PSS-RSAE-SHA256:-SIGN-RSA-PSS-RSAE-SHA384:-SIGN-RSA-PSS-RSAE-SHA512",
.cert = &server_ca3_rsa_pss_cert,
.key = &server_ca3_rsa_pss_key,
.exp_kx = GNUTLS_KX_ECDHE_RSA,
diff --git a/tests/privkey-verify-broken.c b/tests/privkey-verify-broken.c
index aaf640d030..276fcdaafe 100644
--- a/tests/privkey-verify-broken.c
+++ b/tests/privkey-verify-broken.c
@@ -145,7 +145,7 @@ void doit(void)
if (sign_verify_data(pkey, GNUTLS_SIGN_RSA_SHA3_256, 0) < 0)
fail("failed verification with SHA3-256!\n");
- if (sign_verify_data(pkey, GNUTLS_SIGN_RSA_PSS_SHA256, 0) < 0)
+ if (sign_verify_data(pkey, GNUTLS_SIGN_RSA_PSS_RSAE_SHA256, 0) < 0)
fail("failed verification with SHA256 with PSS!\n");
gnutls_x509_privkey_deinit(pkey);
diff --git a/tests/rsa-rsa-pss.c b/tests/rsa-rsa-pss.c
index 74ed99055a..2ba926e321 100644
--- a/tests/rsa-rsa-pss.c
+++ b/tests/rsa-rsa-pss.c
@@ -46,8 +46,8 @@ const gnutls_datum_t raw_data = {
11
};
-static void inv_sign_check(gnutls_pk_algorithm_t algorithm, unsigned sigalgo,
- gnutls_privkey_t privkey, int exp_error)
+static void inv_sign_check(unsigned sigalgo,
+ gnutls_privkey_t privkey, int exp_error)
{
int ret;
gnutls_datum_t signature;
@@ -55,9 +55,11 @@ static void inv_sign_check(gnutls_pk_algorithm_t algorithm, unsigned sigalgo,
ret = gnutls_privkey_sign_data2(privkey, sigalgo, 0,
&raw_data, &signature);
if (ret != exp_error)
- fail("gnutls_privkey_sign_data succeeded with %s and %s: %s\n", gnutls_pk_get_name(algorithm),
+ fail("gnutls_privkey_sign_data succeeded with %s and %s: %s\n", gnutls_pk_get_name(gnutls_privkey_get_pk_algorithm(privkey, NULL)),
gnutls_sign_get_name(sigalgo), gnutls_strerror(ret));
+ if (ret == 0)
+ gnutls_free(signature.data);
}
static void inv_encryption_check(gnutls_pk_algorithm_t algorithm,
@@ -82,8 +84,7 @@ static void inv_encryption_check(gnutls_pk_algorithm_t algorithm,
}
-static void sign_verify_data(gnutls_pk_algorithm_t algorithm, unsigned sigalgo,
- gnutls_privkey_t privkey)
+static void sign_verify_data(unsigned sigalgo, gnutls_privkey_t privkey)
{
int ret;
gnutls_pubkey_t pubkey;
@@ -112,7 +113,8 @@ static void sign_verify_data(gnutls_pk_algorithm_t algorithm, unsigned sigalgo,
void doit(void)
{
- gnutls_privkey_t pkey;
+ gnutls_privkey_t pkey_rsa_pss;
+ gnutls_privkey_t pkey_rsa;
gnutls_x509_privkey_t tkey;
int ret;
gnutls_x509_spki_t spki;
@@ -128,46 +130,67 @@ void doit(void)
assert(gnutls_x509_spki_init(&spki)>=0);
- assert(gnutls_privkey_init(&pkey) >=0);
+ assert(gnutls_privkey_init(&pkey_rsa) >=0);
gnutls_x509_spki_set_rsa_pss_params(spki, GNUTLS_DIG_SHA256, 32);
ret =
- gnutls_privkey_generate(pkey, GNUTLS_PK_RSA, 2048, 0);
+ gnutls_privkey_generate(pkey_rsa, GNUTLS_PK_RSA, 2048, 0);
if (ret < 0) {
fail("gnutls_privkey_generate: %s\n", gnutls_strerror(ret));
}
- assert(gnutls_privkey_set_spki(pkey, spki, 0)>=0);
- assert(gnutls_privkey_export_x509(pkey, &tkey) >=0);
+ assert(gnutls_privkey_set_spki(pkey_rsa, spki, 0)>=0);
+ assert(gnutls_privkey_export_x509(pkey_rsa, &tkey) >=0);
gnutls_x509_privkey_export2_pkcs8(tkey, GNUTLS_X509_FMT_PEM, NULL, 0, &tmp);
- gnutls_x509_privkey_deinit(tkey);
- gnutls_privkey_deinit(pkey);
+ /* import RSA-PSS version of key */
+ assert(gnutls_privkey_init(&pkey_rsa_pss) >=0);
+ assert(gnutls_privkey_import_x509_raw(pkey_rsa_pss, &tmp, GNUTLS_X509_FMT_PEM, NULL, 0) >= 0);
- assert(gnutls_privkey_init(&pkey) >=0);
+ gnutls_free(tmp.data);
- assert(gnutls_privkey_import_x509_raw(pkey, &tmp, GNUTLS_X509_FMT_PEM, NULL, 0) >= 0);
+ /* import RSA-PSS version of key */
+ gnutls_privkey_deinit(pkey_rsa);
+ gnutls_x509_privkey_export2(tkey, GNUTLS_X509_FMT_PEM, &tmp);
+ assert(gnutls_privkey_init(&pkey_rsa) >=0);
+ assert(gnutls_privkey_import_x509_raw(pkey_rsa, &tmp, GNUTLS_X509_FMT_PEM, NULL, 0) >= 0);
- if (debug)
- printf("%s", tmp.data);
+ gnutls_x509_privkey_deinit(tkey);
+ gnutls_free(tmp.data);
- sign_verify_data(GNUTLS_PK_RSA_PSS, GNUTLS_SIGN_RSA_PSS_SHA256, pkey);
+ sign_verify_data(GNUTLS_SIGN_RSA_PSS_SHA256, pkey_rsa_pss);
+ sign_verify_data(GNUTLS_SIGN_RSA_PSS_RSAE_SHA256, pkey_rsa);
+ sign_verify_data(GNUTLS_SIGN_RSA_PSS_SHA256, pkey_rsa);
if (debug)
success("success signing with RSA-PSS-SHA256\n");
- /* check whether the RSA-PSS restrictions are being followed */
- inv_encryption_check(GNUTLS_PK_RSA_PSS, pkey, GNUTLS_E_INVALID_REQUEST);
- inv_sign_check(GNUTLS_PK_RSA, GNUTLS_SIGN_RSA_SHA512, pkey, GNUTLS_E_CONSTRAINT_ERROR);
- inv_sign_check(GNUTLS_PK_RSA, GNUTLS_SIGN_RSA_SHA256, pkey, GNUTLS_E_CONSTRAINT_ERROR);
- inv_sign_check(GNUTLS_PK_RSA_PSS, GNUTLS_SIGN_RSA_PSS_SHA384, pkey, GNUTLS_E_CONSTRAINT_ERROR);
- inv_sign_check(GNUTLS_PK_RSA_PSS, GNUTLS_SIGN_RSA_PSS_SHA512, pkey, GNUTLS_E_CONSTRAINT_ERROR);
-
- gnutls_privkey_deinit(pkey);
+ /* check whether the RSA-PSS key restrictions are being followed */
+ inv_encryption_check(GNUTLS_PK_RSA_PSS, pkey_rsa_pss, GNUTLS_E_INVALID_REQUEST);
+ inv_sign_check(GNUTLS_SIGN_RSA_SHA512, pkey_rsa_pss, GNUTLS_E_CONSTRAINT_ERROR);
+ inv_sign_check(GNUTLS_SIGN_RSA_SHA256, pkey_rsa_pss, GNUTLS_E_CONSTRAINT_ERROR);
+ inv_sign_check(GNUTLS_SIGN_RSA_PSS_SHA384, pkey_rsa_pss, GNUTLS_E_CONSTRAINT_ERROR);
+ inv_sign_check(GNUTLS_SIGN_RSA_PSS_SHA512, pkey_rsa_pss, GNUTLS_E_CONSTRAINT_ERROR);
+ inv_sign_check(GNUTLS_SIGN_RSA_PSS_RSAE_SHA384, pkey_rsa_pss, GNUTLS_E_CONSTRAINT_ERROR);
+ inv_sign_check(GNUTLS_SIGN_RSA_PSS_RSAE_SHA512, pkey_rsa_pss, GNUTLS_E_CONSTRAINT_ERROR);
+
+ /* check whether the RSA key is not being restricted */
+ inv_sign_check(GNUTLS_SIGN_RSA_SHA512, pkey_rsa, 0);
+ inv_sign_check(GNUTLS_SIGN_RSA_SHA256, pkey_rsa, 0);
+ inv_sign_check(GNUTLS_SIGN_RSA_PSS_RSAE_SHA384, pkey_rsa, 0);
+ inv_sign_check(GNUTLS_SIGN_RSA_PSS_RSAE_SHA512, pkey_rsa, 0);
+ /* an RSA key can also generate "pure" for TLS RSA-PSS signatures
+ * as they are essentially the same thing, and we cannot always
+ * know whether a key is RSA-PSS only, or not (e.g., in PKCS#11
+ * keys). */
+ inv_sign_check(GNUTLS_SIGN_RSA_PSS_SHA384, pkey_rsa, 0);
+ inv_sign_check(GNUTLS_SIGN_RSA_PSS_SHA512, pkey_rsa, 0);
+
+ gnutls_privkey_deinit(pkey_rsa);
+ gnutls_privkey_deinit(pkey_rsa_pss);
gnutls_x509_spki_deinit(spki);
- gnutls_free(tmp.data);
gnutls_global_deinit();
}
diff --git a/tests/suite/tls-fuzzer/gnutls-cert.json b/tests/suite/tls-fuzzer/gnutls-cert.json
index 8da7a50a06..781ac2db54 100644
--- a/tests/suite/tls-fuzzer/gnutls-cert.json
+++ b/tests/suite/tls-fuzzer/gnutls-cert.json
@@ -30,10 +30,10 @@
"-e", "check sigalgs in cert request"]
},
{"name" : "test-rsa-pss-sigs-on-certificate-verify.py",
- "comment" : "tlsfuzzer doesn't like our set of algorithms",
"arguments" : ["-k", "tests/clientX509Key.pem",
"-c", "tests/clientX509Cert.pem",
- "-e", "check CertificateRequest sigalgs"]
+ "-e", "check CertificateRequest sigalgs",
+ "-n", "100"]
},
{"name": "test-certificate-malformed.py",
"comment" : "tlsfuzzer doesn't like the alerts we send",
diff --git a/tests/suite/tls-fuzzer/gnutls-nocert.json b/tests/suite/tls-fuzzer/gnutls-nocert.json
index db9ec67844..e5b7a80b4c 100644
--- a/tests/suite/tls-fuzzer/gnutls-nocert.json
+++ b/tests/suite/tls-fuzzer/gnutls-nocert.json
@@ -5,6 +5,7 @@
"--x509keyfile", "../../../certs/ecc256.pem",
"--x509certfile", "../../../certs/cert-ecc256.pem",
"--debug=3",
+ "--noticket",
"--priority=@PRIORITY@",
"--disable-client-cert", "--port=@PORT@"],
"tests" : [
@@ -60,7 +61,9 @@
{"name" : "test-chacha20.py"},
{"name" : "test-aes-gcm-nonces.py" },
{"name" : "test-atypical-padding.py" },
- {"name" : "test-bleichenbacher-workaround.py" },
+ {"name" : "test-bleichenbacher-workaround.py",
+ "arguments" : ["-n", "20"]
+ },
{"name" : "test-clienthello-md5.py"},
{"name" : "test-client-compatibility.py"},
{"name" : "test-conversation.py"},
@@ -133,10 +136,8 @@
"-e", "small, maximum fragmentation: 1 fragment - 20B extension",
"-e", "medium, maximum fragmentation: 1 fragment - 1024B extension"]},
{"name" : "test-sessionID-resumption.py"},
- {"name" : "test-sig-algs.py",
- "comment" : "FIXME: these fail, but most likely due to tls-fuzzer issue",
- "arguments" : ["-e", "RSA-PSS only - fails in verify if server selects PSS",
- "-e", "with RSA-PSS - fails in verify if server selects PSS"]},
+ {"name" : "test-sig-algs.py"
+ },
{"name" : "test-signature-algorithms.py",
"comment" : "gnutls doesn't tolerate that much",
"arguments" : ["-e", "tolerance max (32764) number of methods"]
diff --git a/tests/suite/tls-fuzzer/tlsfuzzer b/tests/suite/tls-fuzzer/tlsfuzzer
-Subproject d10aac68845a80e6bef97b9061aa53119baabcc
+Subproject ff3ab5e356e413bba5845deecdfe105dd207a9a
diff --git a/tests/suite/tls-fuzzer/tlslite-ng b/tests/suite/tls-fuzzer/tlslite-ng
-Subproject 79eee6139661bcd2f0c15d0bd7b10308f699e0b
+Subproject 57d97d290043c6e1ef730e89b57c11937898667
diff --git a/tests/tls-neg-ext-key.c b/tests/tls-neg-ext-key.c
index a02c6b0034..f8b4877a58 100644
--- a/tests/tls-neg-ext-key.c
+++ b/tests/tls-neg-ext-key.c
@@ -295,7 +295,7 @@ static const test_st tests[] = {
},
{.name = "rsa-sign key with rsa-pss sigs prioritized",
.pk = GNUTLS_PK_RSA,
- .prio = "NORMAL:+ECDHE-RSA:+ECDHE-ECDSA:-SIGN-ALL:+SIGN-RSA-PSS-SHA256:+SIGN-RSA-PSS-SHA384:+SIGN-RSA-PSS-SHA512:+SIGN-RSA-SHA256:+SIGN-RSA-SHA384:+SIGN-RSA-SHA512",
+ .prio = "NORMAL:+ECDHE-RSA:+ECDHE-ECDSA:-SIGN-ALL:+SIGN-RSA-PSS-RSAE-SHA256:+SIGN-RSA-PSS-RSAE-SHA384:+SIGN-RSA-PSS-RSAE-SHA512:+SIGN-RSA-SHA256:+SIGN-RSA-SHA384:+SIGN-RSA-SHA512",
.cert = &server_ca3_localhost_cert,
.key = &server_ca3_key,
.exp_kx = GNUTLS_KX_ECDHE_RSA
@@ -308,9 +308,9 @@ static const test_st tests[] = {
.exp_kx = GNUTLS_KX_ECDHE_RSA,
.exp_key_err = GNUTLS_E_INVALID_REQUEST
},
- {.name = "rsa-pss cert, rsa-sign key", /* we expect the server to refuse negotiating */
+ {.name = "rsa-pss cert, rsa-sign key, no rsa-pss-rsae sigs", /* we expect the server to refuse negotiating */
.pk = GNUTLS_PK_RSA,
- .prio = "NORMAL:+ECDHE-RSA:+ECDHE-ECDSA",
+ .prio = "NORMAL:+ECDHE-RSA:+ECDHE-ECDSA:-SIGN-ALL:+SIGN-RSA-PSS-SHA256:+SIGN-RSA-PSS-SHA384:+SIGN-RSA-PSS-SHA512:+SIGN-RSA-SHA256:+SIGN-RSA-SHA384:+SIGN-RSA-SHA512",
.cert = &server_ca3_rsa_pss_cert,
.key = &server_ca3_rsa_pss_key,
.exp_kx = GNUTLS_KX_ECDHE_RSA,
diff --git a/tests/tls11-cert-key-exchange.c b/tests/tls11-cert-key-exchange.c
index 410126fc74..860574afdc 100644
--- a/tests/tls11-cert-key-exchange.c
+++ b/tests/tls11-cert-key-exchange.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015-2017 Red Hat, Inc.
+ * Copyright (C) 2015-2018 Red Hat, Inc.
*
* Author: Nikos Mavrogiannopoulos
*
@@ -62,5 +62,12 @@ void doit(void)
try_with_key("TLS 1.1 with ecdhe ecdsa cert", "NORMAL:-VERS-ALL:+VERS-TLS1.1:-KX-ALL:+ECDHE-ECDSA", GNUTLS_KX_ECDHE_ECDSA, GNUTLS_SIGN_UNKNOWN, GNUTLS_SIGN_UNKNOWN,
&server_ca3_localhost_ecc_cert, &server_ca3_ecc_key, &cli_ca3_cert, &cli_ca3_key, ASK_CERT);
+ /* illegal setups */
+ server_priority = NULL;
+ try_with_key_fail("TLS 1.1 with rsa-pss cert and no cli cert",
+ "NORMAL:-VERS-ALL:+VERS-TLS1.1:-KX-ALL:+DHE-RSA:-SIGN-ALL:+SIGN-RSA-PSS-SHA256:+SIGN-RSA-PSS-SHA384:+SIGN-RSA-PSS-SHA512",
+ GNUTLS_E_UNWANTED_ALGORITHM, GNUTLS_E_AGAIN,
+ &server_ca3_rsa_pss_cert, &server_ca3_rsa_pss_key, NULL, NULL);
+
gnutls_global_deinit();
}
diff --git a/tests/tls12-cert-key-exchange.c b/tests/tls12-cert-key-exchange.c
index 497c8aee3c..bdfd91f72f 100644
--- a/tests/tls12-cert-key-exchange.c
+++ b/tests/tls12-cert-key-exchange.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015-2017 Red Hat, Inc.
+ * Copyright (C) 2015-2018 Red Hat, Inc.
*
* Author: Nikos Mavrogiannopoulos
*
@@ -47,7 +47,7 @@ void doit(void)
try("TLS 1.2 with ecdhe rsa no-cli-cert", "NORMAL:-VERS-ALL:+VERS-TLS1.2:-KX-ALL:+ECDHE-RSA", GNUTLS_KX_ECDHE_RSA, GNUTLS_SIGN_RSA_SHA256, GNUTLS_SIGN_UNKNOWN);
try_with_key("TLS 1.2 with ecdhe ecdsa no-cli-cert", "NORMAL:-VERS-ALL:+VERS-TLS1.2:-KX-ALL:+ECDHE-ECDSA", GNUTLS_KX_ECDHE_ECDSA, GNUTLS_SIGN_ECDSA_SHA256, GNUTLS_SIGN_UNKNOWN,
&server_ca3_localhost_ecc_cert, &server_ca3_ecc_key, NULL, NULL, 0);
- try("TLS 1.2 with ecdhe rsa-pss sig no-cli-cert", "NORMAL:-VERS-ALL:+VERS-TLS1.2:-KX-ALL:+ECDHE-RSA:-SIGN-ALL:+SIGN-RSA-PSS-SHA256", GNUTLS_KX_ECDHE_RSA, GNUTLS_SIGN_RSA_PSS_SHA256, GNUTLS_SIGN_UNKNOWN);
+ try("TLS 1.2 with ecdhe rsa-pss sig no-cli-cert", "NORMAL:-VERS-ALL:+VERS-TLS1.2:-KX-ALL:+ECDHE-RSA:-SIGN-ALL:+SIGN-RSA-PSS-RSAE-SHA256", GNUTLS_KX_ECDHE_RSA, GNUTLS_SIGN_RSA_PSS_RSAE_SHA256, GNUTLS_SIGN_UNKNOWN);
/* Test RSA-PSS cert/key combo issues */
try_with_key("TLS 1.2 with ecdhe with rsa-pss-sha256 key no-cli-cert", "NORMAL:-VERS-ALL:+VERS-TLS1.2:-KX-ALL:+ECDHE-RSA", GNUTLS_KX_ECDHE_RSA, GNUTLS_SIGN_RSA_PSS_SHA256, GNUTLS_SIGN_UNKNOWN,
@@ -59,7 +59,7 @@ void doit(void)
try_with_key("TLS 1.2 with ecdhe with rsa-pss-sha256 key and rsa-pss-sha512 first sig no-cli-cert", "NORMAL:-VERS-ALL:+VERS-TLS1.2:-KX-ALL:+ECDHE-RSA:-SIGN-ALL:+SIGN-RSA-PSS-SHA512:+SIGN-RSA-PSS-SHA384:+SIGN-RSA-PSS-SHA256", GNUTLS_KX_ECDHE_RSA, GNUTLS_SIGN_RSA_PSS_SHA256, GNUTLS_SIGN_UNKNOWN,
&server_ca3_rsa_pss2_cert, &server_ca3_rsa_pss2_key, NULL, NULL, 0);
- try("TLS 1.2 with ecdhe rsa-pss no-cli-cert", "NORMAL:-VERS-ALL:+VERS-TLS1.2:-KX-ALL:+ECDHE-RSA:-SIGN-ALL:+SIGN-RSA-PSS-SHA256", GNUTLS_KX_ECDHE_RSA, GNUTLS_SIGN_RSA_PSS_SHA256, GNUTLS_SIGN_UNKNOWN);
+ try("TLS 1.2 with ecdhe rsa-pss no-cli-cert", "NORMAL:-VERS-ALL:+VERS-TLS1.2:-KX-ALL:+ECDHE-RSA:-SIGN-ALL:+SIGN-RSA-PSS-RSAE-SHA256", GNUTLS_KX_ECDHE_RSA, GNUTLS_SIGN_RSA_PSS_RSAE_SHA256, GNUTLS_SIGN_UNKNOWN);
try_with_key("TLS 1.2 with ecdhe rsa-pss/rsa-pss no-cli-cert", "NORMAL:-VERS-ALL:+VERS-TLS1.2:-KX-ALL:+ECDHE-RSA:-SIGN-ALL:+SIGN-RSA-PSS-SHA256", GNUTLS_KX_ECDHE_RSA, GNUTLS_SIGN_RSA_PSS_SHA256, GNUTLS_SIGN_UNKNOWN,
&server_ca3_rsa_pss_cert, &server_ca3_rsa_pss_key, NULL, NULL, 0);
try("TLS 1.2 with rsa no-cli-cert", "NORMAL:-VERS-ALL:+VERS-TLS1.2:-KX-ALL:+RSA", GNUTLS_KX_RSA, GNUTLS_SIGN_UNKNOWN, GNUTLS_SIGN_UNKNOWN);
@@ -71,7 +71,7 @@ void doit(void)
try_cli("TLS 1.2 with rsa cli-cert", "NORMAL:-VERS-ALL:+VERS-TLS1.2:-KX-ALL:+RSA", GNUTLS_KX_RSA, GNUTLS_SIGN_UNKNOWN, GNUTLS_SIGN_RSA_SHA256, USE_CERT);
try_with_key("TLS 1.2 with ecdhe ecdsa cli-cert", "NORMAL:-VERS-ALL:+VERS-TLS1.2:-KX-ALL:+ECDHE-ECDSA", GNUTLS_KX_ECDHE_ECDSA, GNUTLS_SIGN_ECDSA_SHA256, GNUTLS_SIGN_RSA_SHA256,
&server_ca3_localhost_ecc_cert, &server_ca3_ecc_key, &cli_ca3_cert, &cli_ca3_key, USE_CERT);
- try_cli("TLS 1.2 with ecdhe-rsa-pss cli-cert", "NORMAL:-VERS-ALL:+VERS-TLS1.2:-KX-ALL:+ECDHE-RSA:-SIGN-ALL:+SIGN-RSA-PSS-SHA256", GNUTLS_KX_ECDHE_RSA, GNUTLS_SIGN_RSA_PSS_SHA256, GNUTLS_SIGN_RSA_PSS_SHA256, USE_CERT);
+ try_cli("TLS 1.2 with ecdhe-rsa-pss cli-cert", "NORMAL:-VERS-ALL:+VERS-TLS1.2:-KX-ALL:+ECDHE-RSA:-SIGN-ALL:+SIGN-RSA-PSS-RSAE-SHA256", GNUTLS_KX_ECDHE_RSA, GNUTLS_SIGN_RSA_PSS_RSAE_SHA256, GNUTLS_SIGN_RSA_PSS_RSAE_SHA256, USE_CERT);
try_with_key("TLS 1.2 with ecdhe-rsa-pss/rsa-pss cli-cert", "NORMAL:-VERS-ALL:+VERS-TLS1.2:-KX-ALL:+ECDHE-RSA:-SIGN-ALL:+SIGN-RSA-PSS-SHA256", GNUTLS_KX_ECDHE_RSA, GNUTLS_SIGN_RSA_PSS_SHA256, GNUTLS_SIGN_RSA_PSS_SHA256,
&server_ca3_rsa_pss_cert, &server_ca3_rsa_pss_key, &cli_ca3_rsa_pss_cert, &cli_ca3_rsa_pss_key, USE_CERT);
@@ -84,5 +84,23 @@ void doit(void)
try_with_key("TLS 1.2 with ecdhe ecdsa cli-cert", "NORMAL:-VERS-ALL:+VERS-TLS1.2:-KX-ALL:+ECDHE-ECDSA", GNUTLS_KX_ECDHE_ECDSA, GNUTLS_SIGN_ECDSA_SHA256, GNUTLS_SIGN_UNKNOWN,
&server_ca3_localhost_ecc_cert, &server_ca3_ecc_key, &cli_ca3_cert, &cli_ca3_key, ASK_CERT);
+ /* illegal setups */
+ server_priority = "NORMAL:-VERS-ALL:+VERS-TLS1.2:-KX-ALL:+ECDHE-RSA";
+ try_with_key_fail("TLS 1.2 with rsa cert and only RSA-PSS sig algos in client",
+ "NORMAL:-VERS-ALL:+VERS-TLS1.2:-SIGN-ALL:+SIGN-RSA-PSS-SHA256:+SIGN-RSA-PSS-SHA384:+SIGN-RSA-PSS-SHA512",
+ GNUTLS_E_NO_CIPHER_SUITES, GNUTLS_E_AGAIN,
+ &server_ca3_localhost_cert, &server_ca3_key, NULL, NULL);
+
+ server_priority = NULL;
+ try_with_key_fail("TLS 1.2 with rsa cert and only RSA-PSS sig algos",
+ "NORMAL:-VERS-ALL:+VERS-TLS1.2:-KX-ALL:+ECDHE-RSA:-SIGN-ALL:+SIGN-RSA-PSS-SHA256:+SIGN-RSA-PSS-SHA384:+SIGN-RSA-PSS-SHA512",
+ GNUTLS_E_NO_CIPHER_SUITES, GNUTLS_E_AGAIN,
+ &server_ca3_localhost_cert, &server_ca3_key, NULL, NULL);
+
+ try_with_key_fail("TLS 1.2 with rsa-pss cert and rsa cli cert with only RSA-PSS sig algos",
+ "NORMAL:-VERS-ALL:+VERS-TLS1.2:-SIGN-ALL:+SIGN-RSA-PSS-SHA256:+SIGN-RSA-PSS-SHA384:+SIGN-RSA-PSS-SHA512",
+ GNUTLS_E_AGAIN, GNUTLS_E_UNWANTED_ALGORITHM,
+ &server_ca3_rsa_pss_cert, &server_ca3_rsa_pss_key, &cli_ca3_cert, &cli_ca3_key);
+
gnutls_global_deinit();
}
diff --git a/tests/tls13-cert-key-exchange.c b/tests/tls13-cert-key-exchange.c
index ca1b205c50..5cf60a7189 100644
--- a/tests/tls13-cert-key-exchange.c
+++ b/tests/tls13-cert-key-exchange.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015-2017 Red Hat, Inc.
+ * Copyright (C) 2015-2018 Red Hat, Inc.
*
* Author: Nikos Mavrogiannopoulos
*
@@ -40,13 +40,13 @@ void doit(void)
global_init();
/* TLS 1.3 no clin cert */
- try("TLS 1.3 with ffdhe2048 rsa no-cli-cert", "NORMAL:-VERS-ALL:+VERS-TLS1.3:-GROUP-ALL:+GROUP-FFDHE2048", GNUTLS_KX_DHE_RSA, GNUTLS_SIGN_RSA_PSS_SHA256, GNUTLS_SIGN_UNKNOWN);
- try("TLS 1.3 with ffdhe3072 rsa no-cli-cert", "NORMAL:-VERS-ALL:+VERS-TLS1.3:-GROUP-ALL:+GROUP-FFDHE3072", GNUTLS_KX_DHE_RSA, GNUTLS_SIGN_RSA_PSS_SHA256, GNUTLS_SIGN_UNKNOWN);
- try("TLS 1.3 with ffdhe4096 rsa no-cli-cert", "NORMAL:-VERS-ALL:+VERS-TLS1.3:-GROUP-ALL:+GROUP-FFDHE4096", GNUTLS_KX_DHE_RSA, GNUTLS_SIGN_RSA_PSS_SHA256, GNUTLS_SIGN_UNKNOWN);
- try("TLS 1.3 with secp256r1 rsa no-cli-cert", "NORMAL:-VERS-ALL:+VERS-TLS1.3:-GROUP-ALL:+GROUP-SECP256R1", GNUTLS_KX_ECDHE_RSA, GNUTLS_SIGN_RSA_PSS_SHA256, GNUTLS_SIGN_UNKNOWN);
- try("TLS 1.3 with secp384r1 rsa no-cli-cert", "NORMAL:-VERS-ALL:+VERS-TLS1.3:-GROUP-ALL:+GROUP-SECP384R1", GNUTLS_KX_ECDHE_RSA, GNUTLS_SIGN_RSA_PSS_SHA256, GNUTLS_SIGN_UNKNOWN);
- try("TLS 1.3 with secp521r1 rsa no-cli-cert", "NORMAL:-VERS-ALL:+VERS-TLS1.3:-GROUP-ALL:+GROUP-SECP521R1", GNUTLS_KX_ECDHE_RSA, GNUTLS_SIGN_RSA_PSS_SHA256, GNUTLS_SIGN_UNKNOWN);
- try("TLS 1.3 with x25519 rsa no-cli-cert", "NORMAL:-VERS-ALL:+VERS-TLS1.3:-GROUP-ALL:+GROUP-X25519", GNUTLS_KX_ECDHE_RSA, GNUTLS_SIGN_RSA_PSS_SHA256, GNUTLS_SIGN_UNKNOWN);
+ try("TLS 1.3 with ffdhe2048 rsa no-cli-cert", "NORMAL:-VERS-ALL:+VERS-TLS1.3:-GROUP-ALL:+GROUP-FFDHE2048", GNUTLS_KX_DHE_RSA, GNUTLS_SIGN_RSA_PSS_RSAE_SHA256, GNUTLS_SIGN_UNKNOWN);
+ try("TLS 1.3 with ffdhe3072 rsa no-cli-cert", "NORMAL:-VERS-ALL:+VERS-TLS1.3:-GROUP-ALL:+GROUP-FFDHE3072", GNUTLS_KX_DHE_RSA, GNUTLS_SIGN_RSA_PSS_RSAE_SHA256, GNUTLS_SIGN_UNKNOWN);
+ try("TLS 1.3 with ffdhe4096 rsa no-cli-cert", "NORMAL:-VERS-ALL:+VERS-TLS1.3:-GROUP-ALL:+GROUP-FFDHE4096", GNUTLS_KX_DHE_RSA, GNUTLS_SIGN_RSA_PSS_RSAE_SHA256, GNUTLS_SIGN_UNKNOWN);
+ try("TLS 1.3 with secp256r1 rsa no-cli-cert", "NORMAL:-VERS-ALL:+VERS-TLS1.3:-GROUP-ALL:+GROUP-SECP256R1", GNUTLS_KX_ECDHE_RSA, GNUTLS_SIGN_RSA_PSS_RSAE_SHA256, GNUTLS_SIGN_UNKNOWN);
+ try("TLS 1.3 with secp384r1 rsa no-cli-cert", "NORMAL:-VERS-ALL:+VERS-TLS1.3:-GROUP-ALL:+GROUP-SECP384R1", GNUTLS_KX_ECDHE_RSA, GNUTLS_SIGN_RSA_PSS_RSAE_SHA256, GNUTLS_SIGN_UNKNOWN);
+ try("TLS 1.3 with secp521r1 rsa no-cli-cert", "NORMAL:-VERS-ALL:+VERS-TLS1.3:-GROUP-ALL:+GROUP-SECP521R1", GNUTLS_KX_ECDHE_RSA, GNUTLS_SIGN_RSA_PSS_RSAE_SHA256, GNUTLS_SIGN_UNKNOWN);
+ try("TLS 1.3 with x25519 rsa no-cli-cert", "NORMAL:-VERS-ALL:+VERS-TLS1.3:-GROUP-ALL:+GROUP-X25519", GNUTLS_KX_ECDHE_RSA, GNUTLS_SIGN_RSA_PSS_RSAE_SHA256, GNUTLS_SIGN_UNKNOWN);
try_with_key_ks("TLS 1.3 with secp256r1 ecdsa no-cli-cert", "NORMAL:-VERS-ALL:+VERS-TLS1.3:-GROUP-ALL:+GROUP-SECP256R1", GNUTLS_KX_ECDHE_RSA, GNUTLS_SIGN_ECDSA_SECP256R1_SHA256, GNUTLS_SIGN_UNKNOWN,
&server_ca3_localhost_ecc_cert, &server_ca3_ecc_key, NULL, NULL, 0, GNUTLS_GROUP_SECP256R1);
@@ -69,7 +69,7 @@ void doit(void)
/* client authentication */
try_with_key("TLS 1.3 with rsa-pss cli-cert", "NORMAL:-VERS-ALL:+VERS-TLS1.3:-KX-ALL:+ECDHE-RSA", GNUTLS_KX_ECDHE_RSA, GNUTLS_SIGN_ECDSA_SECP256R1_SHA256, GNUTLS_SIGN_RSA_PSS_SHA256,
&server_ca3_localhost_ecc_cert, &server_ca3_ecc_key, &cli_ca3_rsa_pss_cert, &cli_ca3_rsa_pss_key, USE_CERT);
- try_with_key("TLS 1.3 with rsa cli-cert", "NORMAL:-VERS-ALL:+VERS-TLS1.3:-KX-ALL:+ECDHE-RSA", GNUTLS_KX_ECDHE_RSA, GNUTLS_SIGN_ECDSA_SECP256R1_SHA256, GNUTLS_SIGN_RSA_PSS_SHA256,
+ try_with_key("TLS 1.3 with rsa cli-cert", "NORMAL:-VERS-ALL:+VERS-TLS1.3:-KX-ALL:+ECDHE-RSA", GNUTLS_KX_ECDHE_RSA, GNUTLS_SIGN_ECDSA_SECP256R1_SHA256, GNUTLS_SIGN_RSA_PSS_RSAE_SHA256,
&server_ca3_localhost_ecc_cert, &server_ca3_ecc_key, &cli_ca3_cert, &cli_ca3_key, USE_CERT);
try_with_key("TLS 1.3 with ecdsa cli-cert", "NORMAL:-VERS-ALL:+VERS-TLS1.3:-KX-ALL:+ECDHE-RSA", GNUTLS_KX_ECDHE_RSA, GNUTLS_SIGN_ECDSA_SECP256R1_SHA256, GNUTLS_SIGN_ECDSA_SECP256R1_SHA256,
&server_ca3_localhost_ecc_cert, &server_ca3_ecc_key, &server_ca3_localhost_ecc_cert, &server_ca3_ecc_key, USE_CERT);
@@ -97,5 +97,23 @@ void doit(void)
try("TLS 1.2 fallback with secp521r1 rsa no-cli-cert", "NORMAL:-VERS-ALL:+VERS-TLS1.3:+VERS-TLS1.2:-GROUP-ALL:+GROUP-SECP521R1", GNUTLS_KX_ECDHE_RSA, GNUTLS_SIGN_RSA_SHA256, GNUTLS_SIGN_UNKNOWN);
try("TLS 1.2 fallback with ffdhe2048 rsa no-cli-cert", "NORMAL:-VERS-ALL:+VERS-TLS1.3:+VERS-TLS1.2:-KX-ALL:+DHE-RSA:-GROUP-ALL:+GROUP-FFDHE2048", GNUTLS_KX_DHE_RSA, GNUTLS_SIGN_RSA_SHA256, GNUTLS_SIGN_UNKNOWN);
+ /* illegal setups */
+ server_priority = "NORMAL:-VERS-ALL:+VERS-TLS1.3";
+ try_with_key_fail("TLS 1.3 with rsa cert and only RSA-PSS sig algos in client",
+ "NORMAL:-VERS-ALL:+VERS-TLS1.3:-SIGN-ALL:+SIGN-RSA-PSS-SHA256:+SIGN-RSA-PSS-SHA384:+SIGN-RSA-PSS-SHA512",
+ GNUTLS_E_NO_CIPHER_SUITES, GNUTLS_E_AGAIN,
+ &server_ca3_localhost_cert, &server_ca3_key, NULL, NULL);
+
+ server_priority = NULL;
+ try_with_key_fail("TLS 1.3 with rsa cert and only RSA-PSS sig algos",
+ "NORMAL:-VERS-ALL:+VERS-TLS1.3:-SIGN-ALL:+SIGN-RSA-PSS-SHA256:+SIGN-RSA-PSS-SHA384:+SIGN-RSA-PSS-SHA512",
+ GNUTLS_E_NO_CIPHER_SUITES, GNUTLS_E_AGAIN,
+ &server_ca3_localhost_cert, &server_ca3_key, NULL, NULL);
+
+ try_with_key_fail("TLS 1.3 with rsa-pss cert and rsa cli cert with only RSA-PSS sig algos",
+ "NORMAL:-VERS-ALL:+VERS-TLS1.3:-SIGN-ALL:+SIGN-RSA-PSS-SHA256:+SIGN-RSA-PSS-SHA384:+SIGN-RSA-PSS-SHA512",
+ GNUTLS_E_AGAIN, GNUTLS_E_INCOMPATIBLE_SIG_WITH_KEY,
+ &server_ca3_rsa_pss_cert, &server_ca3_rsa_pss_key, &cli_ca3_cert, &cli_ca3_key);
+
gnutls_global_deinit();
}
diff --git a/tests/tls13/change_cipher_spec.c b/tests/tls13/change_cipher_spec.c
new file mode 100644
index 0000000000..23519d9fd4
--- /dev/null
+++ b/tests/tls13/change_cipher_spec.c
@@ -0,0 +1,344 @@
+/*
+ * Copyright (C) 2017 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
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#if defined(_WIN32)
+
+int main()
+{
+ exit(77);
+}
+
+#else
+
+#include <string.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <sys/wait.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+#include <gnutls/gnutls.h>
+#include <gnutls/dtls.h>
+#include <signal.h>
+#include <assert.h>
+#include <errno.h>
+
+#include "cert-common.h"
+#include "utils.h"
+
+/* This program tests whether the ChangeCipherSpec message
+ * is ignored during handshake.
+ */
+
+static void server_log_func(int level, const char *str)
+{
+ fprintf(stderr, "server|<%d>| %s", level, str);
+}
+
+static void client_log_func(int level, const char *str)
+{
+ fprintf(stderr, "client|<%d>| %s", level, str);
+}
+
+static unsigned client_sent_ccs = 0;
+static unsigned server_sent_ccs = 0;
+
+static int cli_hsk_callback(gnutls_session_t session, unsigned int htype,
+ unsigned post, unsigned int incoming, const gnutls_datum_t *msg);
+
+static void client(int fd, unsigned ccs_check)
+{
+ int ret;
+ gnutls_certificate_credentials_t x509_cred;
+ gnutls_session_t session;
+ char buf[64];
+
+ global_init();
+ client_sent_ccs = 0;
+ server_sent_ccs = 0;
+
+ if (debug) {
+ gnutls_global_set_log_function(client_log_func);
+ gnutls_global_set_log_level(7);
+ }
+
+ gnutls_certificate_allocate_credentials(&x509_cred);
+
+ /* Initialize TLS session
+ */
+ gnutls_init(&session, GNUTLS_CLIENT|GNUTLS_POST_HANDSHAKE_AUTH);
+
+ gnutls_session_set_ptr(session, &ccs_check);
+ gnutls_handshake_set_timeout(session, 20 * 1000);
+ if (ccs_check) {
+ gnutls_handshake_set_hook_function(session, GNUTLS_HANDSHAKE_ANY,
+ GNUTLS_HOOK_PRE,
+ cli_hsk_callback);
+ }
+
+ ret = gnutls_priority_set_direct(session, "NORMAL:-VERS-ALL:+VERS-TLS1.3:+VERS-TLS1.2:+VERS-TLS1.0", NULL);
+ if (ret < 0)
+ fail("cannot set TLS 1.3 priorities\n");
+
+
+ gnutls_certificate_set_x509_key_mem(x509_cred, &cli_ca3_cert,
+ &cli_ca3_key,
+ GNUTLS_X509_FMT_PEM);
+
+ /* put the anonymous credentials to the current session
+ */
+ gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, x509_cred);
+
+ gnutls_transport_set_int(session, fd);
+
+ /* Perform the TLS handshake
+ */
+ do {
+ ret = gnutls_handshake(session);
+ }
+ while (ret < 0 && gnutls_error_is_fatal(ret) == 0);
+
+ if (ret != 0)
+ fail("handshake failed: %s\n", gnutls_strerror(ret));
+ success("client handshake completed\n");
+
+ do {
+ ret = gnutls_record_recv(session, buf, sizeof(buf));
+ } while (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED);
+
+ if (ret < 0)
+ fail("client: recv did not succeed as expected: %s\n", gnutls_strerror(ret));
+
+ close(fd);
+
+ gnutls_deinit(session);
+
+ if (ccs_check) {
+ if (client_sent_ccs != 1) {
+ fail("client: did not sent CCS\n");
+ }
+ }
+
+ gnutls_certificate_free_credentials(x509_cred);
+
+ gnutls_global_deinit();
+}
+
+static int cli_hsk_callback(gnutls_session_t session, unsigned int htype,
+ unsigned post, unsigned int incoming, const gnutls_datum_t *msg)
+{
+ unsigned *p;
+ unsigned ccs_check;
+ static unsigned hello_received = 0;
+
+ p = gnutls_session_get_ptr(session);
+ ccs_check = *p;
+
+ assert(ccs_check != 0);
+ assert(post == GNUTLS_HOOK_PRE);
+
+ if (htype == GNUTLS_HANDSHAKE_CLIENT_HELLO && !incoming) {
+ hello_received = 1;
+
+ gnutls_handshake_set_hook_function(session, GNUTLS_HANDSHAKE_CHANGE_CIPHER_SPEC,
+ GNUTLS_HOOK_PRE,
+ cli_hsk_callback);
+ }
+
+ if (htype == GNUTLS_HANDSHAKE_CHANGE_CIPHER_SPEC && !incoming && hello_received) {
+ client_sent_ccs++;
+ assert(msg->size == 1 && msg->data[0] == 0x01);
+ }
+
+
+ return 0;
+}
+
+static int hsk_callback(gnutls_session_t session, unsigned int htype,
+ unsigned post, unsigned int incoming, const gnutls_datum_t *msg)
+{
+ int ret;
+ int fd;
+ unsigned *p;
+ unsigned ccs_check;
+
+ p = gnutls_session_get_ptr(session);
+ ccs_check = *p;
+
+ assert(post == GNUTLS_HOOK_PRE);
+
+ if (!ccs_check) {
+ if (!incoming || htype == GNUTLS_HANDSHAKE_CLIENT_HELLO ||
+ htype == GNUTLS_HANDSHAKE_FINISHED)
+ return 0;
+
+ fd = gnutls_transport_get_int(session);
+
+ /* send change cipher spec */
+ do {
+ ret = send(fd, "\x14\x03\x03\x00\x01\x01", 6, 0);
+ } while(ret == -1 && (errno == EINTR || errno == EAGAIN));
+ } else { /* checking whether server received it */
+ if (htype == GNUTLS_HANDSHAKE_CHANGE_CIPHER_SPEC && !incoming) {
+ server_sent_ccs++;
+ assert(msg->size == 1 && msg->data[0] == 0x01);
+ }
+ }
+ return 0;
+}
+
+static void server(int fd, unsigned ccs_check)
+{
+ int ret;
+ gnutls_session_t session;
+ gnutls_certificate_credentials_t x509_cred;
+
+ /* this must be called once in the program
+ */
+ global_init();
+
+ client_sent_ccs = 0;
+ server_sent_ccs = 0;
+
+ if (debug) {
+ gnutls_global_set_log_function(server_log_func);
+ gnutls_global_set_log_level(4711);
+ }
+
+ gnutls_certificate_allocate_credentials(&x509_cred);
+ gnutls_certificate_set_x509_key_mem(x509_cred, &server_cert,
+ &server_key,
+ GNUTLS_X509_FMT_PEM);
+
+ gnutls_init(&session, GNUTLS_SERVER);
+
+ gnutls_handshake_set_timeout(session, 20 * 1000);
+
+ if (ccs_check)
+ gnutls_handshake_set_hook_function(session, GNUTLS_HANDSHAKE_CHANGE_CIPHER_SPEC,
+ GNUTLS_HOOK_PRE,
+ hsk_callback);
+ else
+ gnutls_handshake_set_hook_function(session, GNUTLS_HANDSHAKE_ANY,
+ GNUTLS_HOOK_PRE,
+ hsk_callback);
+
+ /* avoid calling all the priority functions, since the defaults
+ * are adequate.
+ */
+ assert(gnutls_priority_set_direct(session, "NORMAL:+VERS-TLS1.3", NULL) >= 0);
+ gnutls_session_set_ptr(session, &ccs_check);
+
+ gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, x509_cred);
+
+ gnutls_transport_set_int(session, fd);
+
+ do {
+ ret = gnutls_handshake(session);
+ } while (ret < 0 && gnutls_error_is_fatal(ret) == 0);
+
+ if (ret != 0)
+ fail("handshake failed: %s\n", gnutls_strerror(ret));
+
+ success("server handshake completed\n");
+
+ gnutls_certificate_server_set_request(session, GNUTLS_CERT_REQUIRE);
+ /* ask peer for re-authentication */
+ do {
+ ret = gnutls_record_send(session, "\x00", 1);
+ } while (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED);
+
+ if (ret < 0)
+ fail("server: gnutls_record_send did not succeed as expected: %s\n", gnutls_strerror(ret));
+
+ close(fd);
+ gnutls_deinit(session);
+
+ gnutls_certificate_free_credentials(x509_cred);
+
+ if (ccs_check) {
+ if (server_sent_ccs != 1) {
+ fail("server: did not sent CCS\n");
+ }
+ }
+
+ gnutls_global_deinit();
+
+ if (debug)
+ success("server: client/server hello were verified\n");
+}
+
+static void ch_handler(int sig)
+{
+ int status;
+ wait(&status);
+ check_wait_status(status);
+ return;
+}
+
+static
+void start(unsigned ccs_check)
+{
+ int fd[2];
+ int ret;
+ pid_t child;
+
+ signal(SIGCHLD, ch_handler);
+
+ ret = socketpair(AF_UNIX, SOCK_STREAM, 0, fd);
+ if (ret < 0) {
+ perror("socketpair");
+ exit(1);
+ }
+
+ child = fork();
+ if (child < 0) {
+ perror("fork");
+ fail("fork");
+ exit(1);
+ }
+
+ if (child) {
+ /* parent */
+ close(fd[1]);
+ server(fd[0], ccs_check);
+ kill(child, SIGTERM);
+ } else {
+ close(fd[0]);
+ client(fd[1], ccs_check);
+ exit(0);
+ }
+}
+
+void doit(void)
+{
+ start(0);
+ start(1);
+}
+
+#endif /* _WIN32 */
diff --git a/tests/tls13/ext-parse.h b/tests/tls13/ext-parse.h
index 5b9f5b868f..ff8a200768 100644
--- a/tests/tls13/ext-parse.h
+++ b/tests/tls13/ext-parse.h
@@ -107,39 +107,29 @@ static unsigned find_client_extension(const gnutls_datum_t *msg, unsigned extnr,
static unsigned find_server_extension(const gnutls_datum_t *msg, unsigned extnr, void *priv, ext_parse_func cb)
{
- unsigned tls13 = 0;
unsigned pos = 0;
success("server hello of %d bytes\n", msg->size);
/* we expect the legacy version to be present */
/* ProtocolVersion legacy_version = 0x0303 */
-#ifdef TLS13_FINAL_VERSION
- if (msg->data[0] != 0x03) {
-#else
- if (msg->data[0] != 0x7f) {
-#endif
+ if (msg->data[0] != 0x03 || msg->data[1] != 0x03) {
fail("ProtocolVersion contains %d.%d\n", (int)msg->data[0], (int)msg->data[1]);
}
if (msg->data[1] >= 0x04) {
success("assuming TLS 1.3 or better hello format (seen %d.%d)\n", (int)msg->data[0], (int)msg->data[1]);
- tls13 = 1;
}
pos += 2+TLS_RANDOM_SIZE;
- if (!tls13) {
- /* legacy_session_id */
- SKIP8(pos, msg->size);
- }
+ /* legacy_session_id */
+ SKIP8(pos, msg->size);
/* CipherSuite */
pos += 2;
- if (!tls13) {
- /* legacy_compression_methods */
- SKIP8(pos, msg->size);
- }
+ /* legacy_compression_methods */
+ SKIP8(pos, msg->size);
pos += 2;
diff --git a/tests/tls13/key_share.c b/tests/tls13/key_share.c
index a048ccfbdd..205f7d0056 100644
--- a/tests/tls13/key_share.c
+++ b/tests/tls13/key_share.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2017 Red Hat, Inc.
+ * Copyright (C) 2017-2018 Red Hat, Inc.
*
* Author: Nikos Mavrogiannopoulos
*
@@ -129,7 +129,7 @@ unsigned int tls_id_to_group[] = {
};
-#define TLS_EXT_KEY_SHARE 40
+#define TLS_EXT_KEY_SHARE 51
typedef struct ctx_st {
gnutls_group_t group;
@@ -154,7 +154,7 @@ void check_ks_contents(void *priv, gnutls_datum_t *msg)
pos = 2;
- while(pos < msg->size) {
+ while((unsigned)pos < msg->size) {
id = (msg->data[pos] << 8) | msg->data[pos+1];
pos += 2;
len -= 2;
diff --git a/tests/tls13/prf.c b/tests/tls13/prf.c
index 92178980a7..355bf37c63 100644
--- a/tests/tls13/prf.c
+++ b/tests/tls13/prf.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015-2017 Red Hat, Inc.
+ * Copyright (C) 2015-2018 Red Hat, Inc.
*
* This file is part of GnuTLS.
*
@@ -126,18 +126,20 @@ 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"
static void check_prfs(gnutls_session_t session)
{
unsigned char key_material[512];
int ret;
- TRY_OLD(13, "key expansion", 34, (uint8_t*)"\xb1\xc3\x5e\x95\x9f\xf7\x5f\x91\x40\x85\xd7\xe8\xe7\x87\x0f\xb3\x78\xec\xbf\x40\x22\xcb\x24\x6e\x85\x91\xa4\xda\xa0\x48\xa5\xb9\x17\x65");
- TRY_OLD(6, "hello", 31, (uint8_t*)"\x85\x18\x53\x95\xa8\x60\xa5\x75\xd9\xc3\x34\xa3\x45\xa4\x90\xf0\x9c\x3a\xe3\xcf\x9a\x56\x4c\xcc\xeb\xba\x62\x2f\x36\x68\x84");
+ TRY_OLD(13, "key expansion", 34, (uint8_t*)KEY_EXP_VALUE);
+ TRY_OLD(6, "hello", 31, (uint8_t*)HELLO_VALUE);
- TRY(13, "key expansion", 0, NULL, 34, (uint8_t*)"\xb1\xc3\x5e\x95\x9f\xf7\x5f\x91\x40\x85\xd7\xe8\xe7\x87\x0f\xb3\x78\xec\xbf\x40\x22\xcb\x24\x6e\x85\x91\xa4\xda\xa0\x48\xa5\xb9\x17\x65");
- TRY(6, "hello", 0, NULL, 31, (uint8_t*)"\x85\x18\x53\x95\xa8\x60\xa5\x75\xd9\xc3\x34\xa3\x45\xa4\x90\xf0\x9c\x3a\xe3\xcf\x9a\x56\x4c\xcc\xeb\xba\x62\x2f\x36\x68\x84");
- TRY(7, "context", 5, "abcd\xfa", 31, (uint8_t*)"\xf4\x49\x53\xf2\x8a\xcc\x59\x52\xa2\x29\x7d\xf4\x2f\x41\x92\x27\x6f\xc5\x1f\x52\xdb\x9a\xa5\x28\x33\x90\x28\x25\x52\x9f\x03");
- TRY(12, "null-context", 0, "", 31, (uint8_t*)"\x91\xb6\xe5\xaf\x3c\x7d\x75\x0a\x66\xe2\xd9\x3d\x57\x2c\x70\x73\x6f\xe2\x8f\x44\x5a\x22\x86\x46\x6b\xe9\x30\xc4\xf4\x0b\x7c");
+ 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 whether calling gnutls_prf() with non-null context or server-first
* param, will fail */
@@ -173,7 +175,7 @@ static void client(int fd)
/* Use default priorities */
ret = gnutls_priority_set_direct(session,
- "NONE:+VERS-TLS1.3:+AES-256-GCM:+AEAD:+SIGN-RSA-PSS-SHA384:+GROUP-SECP256R1",
+ "NONE:+VERS-TLS1.3:+AES-256-GCM:+AEAD:+SIGN-RSA-PSS-RSAE-SHA384:+GROUP-SECP256R1",
&err);
if (ret < 0) {
fail("client: priority set failed (%s): %s\n",
@@ -266,7 +268,7 @@ static void server(int fd)
* are adequate.
*/
ret = gnutls_priority_set_direct(session,
- "NORMAL:-VERS-ALL:+VERS-TLS1.3:-KX-ALL", NULL);
+ "NORMAL:-VERS-ALL:+VERS-TLS1.3:-KX-ALL:-SIGN-ALL:+SIGN-RSA-PSS-RSAE-SHA384:-GROUP-ALL:+GROUP-SECP256R1", NULL);
if (ret < 0) {
fail("server: priority set failed (%s)\n\n",
gnutls_strerror(ret));
diff --git a/tests/tls13/supported_versions.c b/tests/tls13/supported_versions.c
index 31eb4ddbb6..be0e6f3f2e 100644
--- a/tests/tls13/supported_versions.c
+++ b/tests/tls13/supported_versions.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2017 Red Hat, Inc.
+ * Copyright (C) 2017-2018 Red Hat, Inc.
*
* Author: Nikos Mavrogiannopoulos
*
@@ -152,12 +152,8 @@ static int client_hello_callback(gnutls_session_t session, unsigned int htype,
success("server hello:\n\t%d.%d\n",
(int)msg->data[pos], (int)msg->data[pos+1]);
-#ifdef TLS13_FINAL_VERSION
- if (msg->data[pos] != 0x03 || msg->data[pos+1] != 0x04) {
-#else
- if (msg->data[pos] != 0x7f || msg->data[pos+1] != 21) {
-#endif
- fail("fail expected TLS 1.3 in server hello, got %d.%d\n", (int)msg->data[pos], (int)msg->data[pos+1]);
+ if (msg->data[pos] != 0x03 || msg->data[pos+1] != 0x03) {
+ fail("fail expected TLS 1.2 in server hello, got %d.%d\n", (int)msg->data[pos], (int)msg->data[pos+1]);
}
server_hello_ok = 1;
@@ -228,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] != 21) {
+ if (msg->data[pos] != 0x7f || msg->data[pos+1] != 23) {
#endif
fail("fail expected TLS 1.3, got %d.%d\n", (int)msg->data[pos], (int)msg->data[pos+1]);
}