# define SSL_F_DTLS_GET_REASSEMBLED_MESSAGE 370
# define SSL_F_DTLS_PROCESS_HELLO_VERIFY 386
# define SSL_F_OPENSSL_INIT_SSL 342
+# define SSL_F_OSSL_STATEM_CLIENT13_READ_TRANSITION 436
# define SSL_F_OSSL_STATEM_CLIENT_CONSTRUCT_MESSAGE 430
# define SSL_F_OSSL_STATEM_CLIENT_READ_TRANSITION 417
+# define SSL_F_OSSL_STATEM_SERVER13_READ_TRANSITION 437
# define SSL_F_OSSL_STATEM_SERVER_CONSTRUCT_MESSAGE 431
# define SSL_F_OSSL_STATEM_SERVER_READ_TRANSITION 418
# define SSL_F_READ_STATE_MACHINE 352
#endif
/* Derive premaster or master secret for ECDH/DH */
-int ssl_derive(SSL *s, EVP_PKEY *privkey, EVP_PKEY *pubkey)
+int ssl_derive(SSL *s, EVP_PKEY *privkey, EVP_PKEY *pubkey, int genmaster)
{
int rv = 0;
unsigned char *pms = NULL;
if (EVP_PKEY_derive(pctx, pms, &pmslen) <= 0)
goto err;
- if (s->server) {
- /* For server generate master secret and discard premaster */
+ if (genmaster) {
+ /* Generate master secret and discard premaster */
rv = ssl_generate_master_secret(s, pms, pmslen, 1);
pms = NULL;
} else {
- /* For client just save premaster secret */
+ /* Save premaster secret */
s->s3->tmp.pms = pms;
s->s3->tmp.pmslen = pmslen;
pms = NULL;
"dtls_get_reassembled_message"},
{ERR_FUNC(SSL_F_DTLS_PROCESS_HELLO_VERIFY), "dtls_process_hello_verify"},
{ERR_FUNC(SSL_F_OPENSSL_INIT_SSL), "OPENSSL_init_ssl"},
+ {ERR_FUNC(SSL_F_OSSL_STATEM_CLIENT13_READ_TRANSITION),
+ "ossl_statem_client13_read_transition"},
{ERR_FUNC(SSL_F_OSSL_STATEM_CLIENT_CONSTRUCT_MESSAGE),
"ossl_statem_client_construct_message"},
{ERR_FUNC(SSL_F_OSSL_STATEM_CLIENT_READ_TRANSITION),
"ossl_statem_client_read_transition"},
+ {ERR_FUNC(SSL_F_OSSL_STATEM_SERVER13_READ_TRANSITION),
+ "ossl_statem_server13_read_transition"},
{ERR_FUNC(SSL_F_OSSL_STATEM_SERVER_CONSTRUCT_MESSAGE),
"ossl_statem_server_construct_message"},
{ERR_FUNC(SSL_F_OSSL_STATEM_SERVER_READ_TRANSITION),
__owur int ssl_generate_master_secret(SSL *s, unsigned char *pms, size_t pmslen,
int free_pms);
__owur EVP_PKEY *ssl_generate_pkey(EVP_PKEY *pm);
-__owur int ssl_derive(SSL *s, EVP_PKEY *privkey, EVP_PKEY *pubkey);
+__owur int ssl_derive(SSL *s, EVP_PKEY *privkey, EVP_PKEY *pubkey,
+ int genmaster);
__owur EVP_PKEY *ssl_dh_to_pkey(DH *dh);
__owur const SSL_CIPHER *ssl3_get_cipher_by_char(const unsigned char *p);
return 0;
}
+/*
+ * ossl_statem_client_read_transition() encapsulates the logic for the allowed
+ * handshake state transitions when a TLS1.3 client is reading messages from the
+ * server. The message type that the server has sent is provided in |mt|. The
+ * current state is in |s->statem.hand_state|.
+ *
+ * Return values are:
+ * 1: Success (transition allowed)
+ * 0: Error (transition not allowed)
+ */
+static int ossl_statem_client13_read_transition(SSL *s, int mt)
+{
+ OSSL_STATEM *st = &s->statem;
+
+ /*
+ * Note: There is no case for TLS_ST_CW_CLNT_HELLO, because we haven't
+ * yet negotiated TLSv1.3 at that point so that is handled by
+ * ossl_statem_client_read_transition()
+ */
+
+ switch (st->hand_state) {
+ default:
+ break;
+
+ case TLS_ST_CR_SRVR_HELLO:
+ if (s->hit) {
+ if (s->tlsext_ticket_expected) {
+ if (mt == SSL3_MT_NEWSESSION_TICKET) {
+ st->hand_state = TLS_ST_CR_SESSION_TICKET;
+ return 1;
+ }
+ } else if (mt == SSL3_MT_CHANGE_CIPHER_SPEC) {
+ st->hand_state = TLS_ST_CR_CHANGE;
+ return 1;
+ }
+ } else {
+ if (mt == SSL3_MT_CERTIFICATE) {
+ st->hand_state = TLS_ST_CR_CERT;
+ return 1;
+ }
+ }
+ break;
+
+ case TLS_ST_CR_CERT:
+ /*
+ * The CertificateStatus message is optional even if
+ * |tlsext_status_expected| is set
+ */
+ if (s->tlsext_status_expected && mt == SSL3_MT_CERTIFICATE_STATUS) {
+ st->hand_state = TLS_ST_CR_CERT_STATUS;
+ return 1;
+ }
+ /* Fall through */
+
+ case TLS_ST_CR_CERT_STATUS:
+ if (mt == SSL3_MT_CERTIFICATE_REQUEST) {
+ if (cert_req_allowed(s)) {
+ st->hand_state = TLS_ST_CR_CERT_REQ;
+ return 1;
+ }
+ goto err;
+ }
+ /* Fall through */
+
+ case TLS_ST_CR_CERT_REQ:
+ if (mt == SSL3_MT_SERVER_DONE) {
+ st->hand_state = TLS_ST_CR_SRVR_DONE;
+ return 1;
+ }
+ break;
+
+ case TLS_ST_CW_FINISHED:
+ if (s->tlsext_ticket_expected) {
+ if (mt == SSL3_MT_NEWSESSION_TICKET) {
+ st->hand_state = TLS_ST_CR_SESSION_TICKET;
+ return 1;
+ }
+ } else if (mt == SSL3_MT_CHANGE_CIPHER_SPEC) {
+ st->hand_state = TLS_ST_CR_CHANGE;
+ return 1;
+ }
+ break;
+
+ case TLS_ST_CR_SESSION_TICKET:
+ if (mt == SSL3_MT_CHANGE_CIPHER_SPEC) {
+ st->hand_state = TLS_ST_CR_CHANGE;
+ return 1;
+ }
+ break;
+
+ case TLS_ST_CR_CHANGE:
+ if (mt == SSL3_MT_FINISHED) {
+ st->hand_state = TLS_ST_CR_FINISHED;
+ return 1;
+ }
+ break;
+ }
+
+ err:
+ /* No valid transition found */
+ ssl3_send_alert(s, SSL3_AL_FATAL, SSL3_AD_UNEXPECTED_MESSAGE);
+ SSLerr(SSL_F_OSSL_STATEM_CLIENT13_READ_TRANSITION,
+ SSL_R_UNEXPECTED_MESSAGE);
+ return 0;
+}
+
/*
* ossl_statem_client_read_transition() encapsulates the logic for the allowed
* handshake state transitions when the client is reading messages from the
OSSL_STATEM *st = &s->statem;
int ske_expected;
+ /*
+ * Note that after a ClientHello we don't know what version we are going
+ * to negotiate yet, so we don't take this branch until later
+ */
+ if (s->method->version == TLS1_3_VERSION)
+ return ossl_statem_client13_read_transition(s, mt);
+
switch (st->hand_state) {
default:
break;
}
/*
- * client_write_transition() works out what handshake state to move to next
- * when the client is writing messages to be sent to the server.
+ * ossl_statem_client13_write_transition() works out what handshake state to
+ * move to next when the TLSv1.3 client is writing messages to be sent to the
+ * server.
+ *
+ * Return values:
+ * WRITE_TRAN_ERROR - an error occurred
+ * WRITE_TRAN_CONTINUE - Successful transition, more writing to be done
+ * WRITE_TRAN_FINISHED - Successful transition, no more writing to be done
+ */
+static WRITE_TRAN ossl_statem_client13_write_transition(SSL *s)
+{
+ OSSL_STATEM *st = &s->statem;
+
+ /*
+ * Note: There are no cases for TLS_ST_BEFORE or TLS_ST_CW_CLNT_HELLO,
+ * because we haven't negotiated TLSv1.3 yet at that point. They are
+ * handled by ossl_statem_client_write_transition().
+ */
+ switch (st->hand_state) {
+ default:
+ /* Shouldn't happen */
+ return WRITE_TRAN_ERROR;
+
+ case TLS_ST_CR_SRVR_DONE:
+ if (s->s3->tmp.cert_req)
+ st->hand_state = TLS_ST_CW_CERT;
+ else
+ st->hand_state = TLS_ST_CW_CHANGE;
+ return WRITE_TRAN_CONTINUE;
+
+ case TLS_ST_CW_CERT:
+ /* If a non-empty Certificate we also send CertificateVerify */
+ if (s->s3->tmp.cert_req == 1)
+ st->hand_state = TLS_ST_CW_CERT_VRFY;
+ else
+ st->hand_state = TLS_ST_CW_CHANGE;
+ return WRITE_TRAN_CONTINUE;
+
+ case TLS_ST_CW_CERT_VRFY:
+ st->hand_state = TLS_ST_CW_CHANGE;
+ return WRITE_TRAN_CONTINUE;
+
+ case TLS_ST_CW_CHANGE:
+ st->hand_state = TLS_ST_CW_FINISHED;
+ return WRITE_TRAN_CONTINUE;
+
+ case TLS_ST_CW_FINISHED:
+ if (s->hit) {
+ st->hand_state = TLS_ST_OK;
+ ossl_statem_set_in_init(s, 0);
+ return WRITE_TRAN_CONTINUE;
+ } else {
+ return WRITE_TRAN_FINISHED;
+ }
+
+ case TLS_ST_CR_FINISHED:
+ if (s->hit) {
+ st->hand_state = TLS_ST_CW_CHANGE;
+ return WRITE_TRAN_CONTINUE;
+ } else {
+ st->hand_state = TLS_ST_OK;
+ ossl_statem_set_in_init(s, 0);
+ return WRITE_TRAN_CONTINUE;
+ }
+ }
+}
+
+/*
+ * ossl_statem_client_write_transition() works out what handshake state to
+ * move to next when the client is writing messages to be sent to the server.
+ *
+ * Return values:
+ * WRITE_TRAN_ERROR - an error occurred
+ * WRITE_TRAN_CONTINUE - Successful transition, more writing to be done
+ * WRITE_TRAN_FINISHED - Successful transition, no more writing to be done
*/
WRITE_TRAN ossl_statem_client_write_transition(SSL *s)
{
OSSL_STATEM *st = &s->statem;
+ /*
+ * Note that immediately before/after a ClientHello we don't know what
+ * version we are going to negotiate yet, so we don't take this branch until
+ * later
+ */
+ if (s->method->version == TLS1_3_VERSION)
+ return ossl_statem_client13_write_transition(s);
+
switch (st->hand_state) {
default:
/* Shouldn't happen */
ckey = ssl_generate_pkey(skey);
dh_clnt = EVP_PKEY_get0_DH(ckey);
- if (dh_clnt == NULL || ssl_derive(s, ckey, skey) == 0)
+ if (dh_clnt == NULL || ssl_derive(s, ckey, skey, 0) == 0)
goto err;
/* send off the data */
ckey = ssl_generate_pkey(skey);
- if (ssl_derive(s, ckey, skey) == 0) {
+ if (ssl_derive(s, ckey, skey, 0) == 0) {
SSLerr(SSL_F_TLS_CONSTRUCT_CKE_ECDHE, ERR_R_EVP_LIB);
goto err;
}
SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_VERIFY, ERR_R_INTERNAL_ERROR);
goto err;
}
+
if (SSL_USE_SIGALGS(s)&& !tls12_get_sigandhash(pkt, pkey, md)) {
SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_VERIFY, ERR_R_INTERNAL_ERROR);
goto err;
int *al);
/*
- * server_read_transition() encapsulates the logic for the allowed handshake
- * state transitions when the server is reading messages from the client. The
- * message type that the client has sent is provided in |mt|. The current state
- * is in |s->statem.hand_state|.
+ * ossl_statem_server13_read_transition() encapsulates the logic for the allowed
+ * handshake state transitions when a TLSv1.3 server is reading messages from
+ * the client. The message type that the client has sent is provided in |mt|.
+ * The current state is in |s->statem.hand_state|.
+ *
+ * Valid return values are:
+ * 1: Success (transition allowed)
+ * 0: Error (transition not allowed)
+ */
+static int ossl_statem_server13_read_transition(SSL *s, int mt)
+{
+ OSSL_STATEM *st = &s->statem;
+
+ /*
+ * Note: There is no case for TLS_ST_BEFORE because at that stage we have
+ * not negotiated TLSv1.3 yet, so that case is handled by
+ * ossl_statem_server_read_transition()
+ */
+ switch (st->hand_state) {
+ default:
+ break;
+
+ case TLS_ST_SW_SRVR_DONE:
+ if (s->s3->tmp.cert_request) {
+ if (mt == SSL3_MT_CERTIFICATE) {
+ st->hand_state = TLS_ST_SR_CERT;
+ return 1;
+ }
+ } else {
+ if (mt == SSL3_MT_CHANGE_CIPHER_SPEC) {
+ st->hand_state = TLS_ST_SR_CHANGE;
+ return 1;
+ }
+ }
+ break;
+
+ case TLS_ST_SR_CERT:
+ if (s->session->peer == NULL) {
+ if (mt == SSL3_MT_CHANGE_CIPHER_SPEC) {
+ st->hand_state = TLS_ST_SR_CHANGE;
+ return 1;
+ }
+ } else {
+ if (mt == SSL3_MT_CERTIFICATE_VERIFY) {
+ st->hand_state = TLS_ST_SR_CERT_VRFY;
+ return 1;
+ }
+ }
+ break;
+
+ case TLS_ST_SR_CERT_VRFY:
+ if (mt == SSL3_MT_CHANGE_CIPHER_SPEC) {
+ st->hand_state = TLS_ST_SR_CHANGE;
+ return 1;
+ }
+ break;
+
+ case TLS_ST_SR_CHANGE:
+ if (mt == SSL3_MT_FINISHED) {
+ st->hand_state = TLS_ST_SR_FINISHED;
+ return 1;
+ }
+ break;
+
+ case TLS_ST_SW_FINISHED:
+ if (mt == SSL3_MT_CHANGE_CIPHER_SPEC) {
+ st->hand_state = TLS_ST_SR_CHANGE;
+ return 1;
+ }
+ break;
+ }
+
+ /* No valid transition found */
+ ssl3_send_alert(s, SSL3_AL_FATAL, SSL3_AD_UNEXPECTED_MESSAGE);
+ SSLerr(SSL_F_OSSL_STATEM_SERVER13_READ_TRANSITION,
+ SSL_R_UNEXPECTED_MESSAGE);
+ return 0;
+}
+
+/*
+ * ossl_statem_server_read_transition() encapsulates the logic for the allowed
+ * handshake state transitions when the server is reading messages from the
+ * client. The message type that the client has sent is provided in |mt|. The
+ * current state is in |s->statem.hand_state|.
*
* Valid return values are:
* 1: Success (transition allowed)
{
OSSL_STATEM *st = &s->statem;
+ if (s->method->version == TLS1_3_VERSION)
+ return ossl_statem_server13_read_transition(s, mt);
+
switch (st->hand_state) {
default:
break;
}
/*
- * server_write_transition() works out what handshake state to move to next
- * when the server is writing messages to be sent to the client.
+ * ossl_statem_server13_write_transition() works out what handshake state to
+ * move to next when a TLSv1.3 server is writing messages to be sent to the
+ * client.
+ *
+ * Return values:
+ * WRITE_TRAN_ERROR - an error occurred
+ * WRITE_TRAN_CONTINUE - Successful transition, more writing to be done
+ * WRITE_TRAN_FINISHED - Successful transition, no more writing to be done
+ */
+static WRITE_TRAN ossl_statem_server13_write_transition(SSL *s)
+{
+ OSSL_STATEM *st = &s->statem;
+
+ /*
+ * No case for TLS_ST_BEFORE, because at that stage we have not negotiated
+ * TLSv1.3 yet, so that is handled by ossl_statem_server_write_transition()
+ */
+
+ switch (st->hand_state) {
+ default:
+ /* Shouldn't happen */
+ return WRITE_TRAN_ERROR;
+
+ case TLS_ST_SR_CLNT_HELLO:
+ st->hand_state = TLS_ST_SW_SRVR_HELLO;
+ return WRITE_TRAN_CONTINUE;
+
+ case TLS_ST_SW_SRVR_HELLO:
+ if (s->hit) {
+ if (s->tlsext_ticket_expected)
+ st->hand_state = TLS_ST_SW_SESSION_TICKET;
+ else
+ st->hand_state = TLS_ST_SW_CHANGE;
+ } else {
+ st->hand_state = TLS_ST_SW_CERT;
+ }
+ return WRITE_TRAN_CONTINUE;
+
+ case TLS_ST_SW_CERT:
+ if (s->tlsext_status_expected) {
+ st->hand_state = TLS_ST_SW_CERT_STATUS;
+ return WRITE_TRAN_CONTINUE;
+ }
+ /* Fall through */
+
+ case TLS_ST_SW_CERT_STATUS:
+ if (send_certificate_request(s)) {
+ st->hand_state = TLS_ST_SW_CERT_REQ;
+ return WRITE_TRAN_CONTINUE;
+ }
+ /* Fall through */
+
+ case TLS_ST_SW_CERT_REQ:
+ st->hand_state = TLS_ST_SW_SRVR_DONE;
+ return WRITE_TRAN_CONTINUE;
+
+ case TLS_ST_SW_SRVR_DONE:
+ return WRITE_TRAN_FINISHED;
+
+ case TLS_ST_SR_FINISHED:
+ if (s->hit) {
+ st->hand_state = TLS_ST_OK;
+ ossl_statem_set_in_init(s, 0);
+ return WRITE_TRAN_CONTINUE;
+ } else if (s->tlsext_ticket_expected) {
+ st->hand_state = TLS_ST_SW_SESSION_TICKET;
+ } else {
+ st->hand_state = TLS_ST_SW_CHANGE;
+ }
+ return WRITE_TRAN_CONTINUE;
+
+ case TLS_ST_SW_SESSION_TICKET:
+ st->hand_state = TLS_ST_SW_CHANGE;
+ return WRITE_TRAN_CONTINUE;
+
+ case TLS_ST_SW_CHANGE:
+ st->hand_state = TLS_ST_SW_FINISHED;
+ return WRITE_TRAN_CONTINUE;
+
+ case TLS_ST_SW_FINISHED:
+ if (s->hit) {
+ return WRITE_TRAN_FINISHED;
+ }
+ st->hand_state = TLS_ST_OK;
+ ossl_statem_set_in_init(s, 0);
+ return WRITE_TRAN_CONTINUE;
+ }
+}
+
+/*
+ * ossl_statem_server_write_transition() works out what handshake state to move
+ * to next when the server is writing messages to be sent to the client.
+ *
+ * Return values:
+ * WRITE_TRAN_ERROR - an error occurred
+ * WRITE_TRAN_CONTINUE - Successful transition, more writing to be done
+ * WRITE_TRAN_FINISHED - Successful transition, no more writing to be done
*/
WRITE_TRAN ossl_statem_server_write_transition(SSL *s)
{
OSSL_STATEM *st = &s->statem;
+ /*
+ * Note that before the ClientHello we don't know what version we are going
+ * to negotiate yet, so we don't take this branch until later
+ */
+
+ if (s->method->version == TLS1_3_VERSION)
+ return ossl_statem_server13_write_transition(s);
+
switch (st->hand_state) {
default:
/* Shouldn't happen */
goto err;
}
- if (ssl_derive(s, skey, ckey) == 0) {
+ if (ssl_derive(s, skey, ckey, 1) == 0) {
*al = SSL_AD_INTERNAL_ERROR;
SSLerr(SSL_F_TLS_PROCESS_CKE_DHE, ERR_R_INTERNAL_ERROR);
goto err;
}
}
- if (ssl_derive(s, skey, ckey) == 0) {
+ if (ssl_derive(s, skey, ckey, 1) == 0) {
*al = SSL_AD_INTERNAL_ERROR;
SSLerr(SSL_F_TLS_PROCESS_CKE_ECDHE, ERR_R_INTERNAL_ERROR);
goto err;
al = SSL_AD_INTERNAL_ERROR;
goto f_err;
}
+
#ifdef SSL_DEBUG
fprintf(stderr, "Using client verify alg %s\n", EVP_MD_name(md));
#endif
sk_X509_pop_free(s->session->peer_chain, X509_free);
s->session->peer_chain = sk;
+
+ /*
+ * Freeze the handshake buffer. For <TLS1.3 we do this after the CKE
+ * message
+ */
+ if (s->version == TLS1_3_VERSION && !ssl3_digest_cached_records(s, 1)) {
+ al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE, ERR_R_INTERNAL_ERROR);
+ goto f_err;
+ }
+
/*
* Inconsistency alert: cert_chain does *not* include the peer's own
* certificate, while we do include it in statem_clnt.c
int tls1_generate_master_secret(SSL *s, unsigned char *out, unsigned char *p,
size_t len, size_t *secret_size)
{
- if (s->session->flags & SSL_SESS_FLAG_EXTMS) {
+ /*
+ * TODO(TLS1.3): We haven't implemented TLS1.3 key derivation yet. For now
+ * we will just force no use of EMS (which adds complications around the
+ * handshake has). This will need to be removed later
+ */
+ if ((s->session->flags & SSL_SESS_FLAG_EXTMS)
+ && s->version != TLS1_3_VERSION) {
unsigned char hash[EVP_MAX_MD_SIZE * 2];
size_t hashlen;
/*
OPENSSL_free(encodedPoint);
return 0;
}
+ OPENSSL_free(encodedPoint);
s->s3->tmp.pkey = skey;
- OPENSSL_free(encodedPoint);
+
+ if (ssl_derive(s, skey, ckey, 1) == 0) {
+ *al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_SSL_ADD_SERVERHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
}
if (!custom_ext_add(s, 1, pkt, al)) {
s->s3->tmp.new_cipher->algorithm_mac != SSL_AEAD
&& s->s3->tmp.new_cipher->algorithm_enc != SSL_RC4)
s->s3->flags |= TLS1_FLAGS_ENCRYPT_THEN_MAC;
- } else if (type == TLSEXT_TYPE_extended_master_secret) {
+ } else if (type == TLSEXT_TYPE_extended_master_secret &&
+ (SSL_IS_DTLS(s) || s->version < TLS1_3_VERSION)) {
s->s3->flags |= TLS1_FLAGS_RECEIVED_EXTMS;
if (!s->hit)
s->session->flags |= SSL_SESS_FLAG_EXTMS;
return 0;
}
- /* TODO(TLS1.3): Create skey from ckey */
skey = ssl_generate_pkey(ckey);
if (!PACKET_as_length_prefixed_2(&spkt, &encoded_pt)) {
return 0;
}
- /*
- * TODO(TLS1.3): Throw it all away for now, later we will use the
- * two keys.
- */
+ if (ssl_derive(s, ckey, skey, 1) == 0) {
+ *al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_SSL_SCAN_SERVERHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
+ EVP_PKEY_free(skey);
+ return 0;
+ }
EVP_PKEY_free(skey);
/*
* If this extension type was not otherwise handled, but matches a
/*
* Sets the extended master secret flag if the extension is present in the
- * ClientHello
+ * ClientHello and we can support it
* Returns:
* 1 on success
* 0 on error
s->s3->flags &= ~TLS1_FLAGS_RECEIVED_EXTMS;
- if (s->version <= SSL3_VERSION)
+ if (!SSL_IS_DTLS(s) && (s->version < TLS1_VERSION
+ || s->version > TLS1_2_VERSION))
return 1;
emsext = tls_get_extension_by_type(hello->pre_proc_exts,
$shellotickext = 1;
}
}
- } elsif ($message->mt == TLSProxy::Message::MT_CLIENT_KEY_EXCHANGE) {
+ } elsif ($message->mt == TLSProxy::Message::MT_CERTIFICATE) {
#Must be doing a full handshake
$fullhand = 1;
} elsif ($message->mt == TLSProxy::Message::MT_NEW_SESSION_TICKET) {
plan skip_all => "$test_name needs the sock feature enabled"
if disabled("sock");
-plan skip_all => "$test_name needs TLS enabled"
- if alldisabled(available_protocols("tls"));
+plan skip_all => "$test_name needs TLSv1.0, TLSv1.1 or TLSv1.2 enabled"
+ if disabled("tls1") && disabled("tls1_1") && disabled("tls1_2");
$ENV{OPENSSL_ia32cap} = '~0x200000200000000';
(!$ENV{HARNESS_ACTIVE} || $ENV{HARNESS_VERBOSE})
);
+#Note that EXTMS is only relevant for <TLS1.3
+
#Test 1: By default server and client should send extended master secret
# extension.
#Expected result: ClientHello extension seen; ServerHello extension seen
# Full handshake
setrmextms(0, 0);
+$proxy->clientflags("-no_tls1_3");
$proxy->start() or plan skip_all => "Unable to start up Proxy for tests";
-plan tests => 9;
+my $numtests = 9;
+if (!disabled("tls1_3")) {
+ $numtests++;
+}
+plan tests => $numtests;
checkmessages(1, "Default extended master secret test", 1, 1, 1);
#Test 2: If client omits extended master secret extension, server should too.
clearall();
setrmextms(1, 0);
+$proxy->clientflags("-no_tls1_3");
$proxy->start();
checkmessages(2, "No client extension extended master secret test", 0, 0, 1);
# Expected result: same as test 1.
clearall();
-$proxy->clientflags("-no_ticket");
+$proxy->clientflags("-no_ticket -no_tls1_3");
setrmextms(0, 0);
$proxy->start();
checkmessages(3, "No ticket extended master secret test", 1, 1, 1);
# Expected result: same as test 2.
clearall();
-$proxy->clientflags("-no_ticket");
+$proxy->clientflags("-no_ticket -no_tls1_3");
setrmextms(1, 0);
$proxy->start();
-checkmessages(2, "No ticket, no client extension extended master secret test", 0, 0, 1);
+checkmessages(4, "No ticket, no client extension extended master secret test", 0, 0, 1);
#Test 5: Session resumption extended master secret test
#
setrmextms(0, 0);
(undef, my $session) = tempfile();
$proxy->serverconnects(2);
-$proxy->clientflags("-sess_out ".$session);
+$proxy->clientflags("-no_tls1_3 -sess_out ".$session);
$proxy->start();
$proxy->clearClient();
-$proxy->clientflags("-sess_in ".$session);
+$proxy->clientflags("-no_tls1_3 -sess_in ".$session);
$proxy->clientstart();
checkmessages(5, "Session resumption extended master secret test", 1, 1, 0);
unlink $session;
setrmextms(1, 0);
(undef, $session) = tempfile();
$proxy->serverconnects(2);
-$proxy->clientflags("-sess_out ".$session);
+$proxy->clientflags("-no_tls1_3 -sess_out ".$session);
$proxy->start();
$proxy->clearClient();
-$proxy->clientflags("-sess_in ".$session);
+$proxy->clientflags("-no_tls1_3 -sess_in ".$session);
setrmextms(0, 0);
$proxy->clientstart();
checkmessages(6, "Session resumption extended master secret test", 1, 1, 1);
setrmextms(0, 0);
(undef, $session) = tempfile();
$proxy->serverconnects(2);
-$proxy->clientflags("-sess_out ".$session);
+$proxy->clientflags("-no_tls1_3 -sess_out ".$session);
$proxy->start();
$proxy->clearClient();
-$proxy->clientflags("-sess_in ".$session);
+$proxy->clientflags("-no_tls1_3 -sess_in ".$session);
setrmextms(1, 0);
$proxy->clientstart();
ok(TLSProxy::Message->fail(), "Client inconsistent session resumption");
setrmextms(0, 0);
(undef, $session) = tempfile();
$proxy->serverconnects(2);
-$proxy->clientflags("-sess_out ".$session);
+$proxy->clientflags("-no_tls1_3 -sess_out ".$session);
$proxy->start();
$proxy->clearClient();
-$proxy->clientflags("-sess_in ".$session);
+$proxy->clientflags("-no_tls1_3 -sess_in ".$session);
setrmextms(0, 1);
$proxy->clientstart();
ok(TLSProxy::Message->fail(), "Server inconsistent session resumption 1");
setrmextms(0, 1);
(undef, $session) = tempfile();
$proxy->serverconnects(2);
-$proxy->clientflags("-sess_out ".$session);
+$proxy->clientflags("-no_tls1_3 -sess_out ".$session);
$proxy->start();
$proxy->clearClient();
-$proxy->clientflags("-sess_in ".$session);
+$proxy->clientflags("-no_tls1_3 -sess_in ".$session);
setrmextms(0, 0);
$proxy->clientstart();
ok(TLSProxy::Message->fail(), "Server inconsistent session resumption 2");
unlink $session;
+#Test 10: In TLS1.3 we should not negotiate extended master secret
+#Expected result: ClientHello extension seen; ServerHello extension not seen
+# TLS1.3 handshake (will appear as abbreviated handshake
+# because of no CKE message)
+if (!disabled("tls1_3")) {
+ clearall();
+ setrmextms(0, 0);
+ $proxy->start();
+ checkmessages(10, "TLS1.3 extended master secret test", 1, 0, 0);
+}
+
+
sub extms_filter
{
my $proxy = shift;
# conditions.
my %skip = (
"07-dtls-protocol-version.conf" => $no_dtls,
- "08-npn.conf" => $no_tls || $no_npn,
+ "08-npn.conf" => (disabled("tls1") && disabled("tls1_1")
+ && disabled("tls1_2")) || $no_npn,
"10-resumption.conf" => disabled("tls1_1") || disabled("tls1_2"),
"11-dtls_resumption.conf" => disabled("dtls1") || disabled("dtls1_2"),
"12-ct.conf" => $no_tls || $no_ct || $no_ec,
[0-npn-simple-client]
CipherString = DEFAULT
+MaxProtocol = TLSv1.2
VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem
VerifyMode = Peer
[1-npn-client-finds-match-client]
CipherString = DEFAULT
+MaxProtocol = TLSv1.2
VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem
VerifyMode = Peer
[2-npn-client-honours-server-pref-client]
CipherString = DEFAULT
+MaxProtocol = TLSv1.2
VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem
VerifyMode = Peer
[3-npn-client-first-pref-on-mismatch-client]
CipherString = DEFAULT
+MaxProtocol = TLSv1.2
VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem
VerifyMode = Peer
[4-npn-no-server-support-client]
CipherString = DEFAULT
+MaxProtocol = TLSv1.2
VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem
VerifyMode = Peer
[5-npn-no-client-support-client]
CipherString = DEFAULT
+MaxProtocol = TLSv1.2
VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem
VerifyMode = Peer
[6-npn-with-sni-no-context-switch-client]
CipherString = DEFAULT
+MaxProtocol = TLSv1.2
VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem
VerifyMode = Peer
[7-npn-with-sni-context-switch-client]
CipherString = DEFAULT
+MaxProtocol = TLSv1.2
VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem
VerifyMode = Peer
[8-npn-selected-sni-server-supports-npn-client]
CipherString = DEFAULT
+MaxProtocol = TLSv1.2
VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem
VerifyMode = Peer
[9-npn-selected-sni-server-does-not-support-npn-client]
CipherString = DEFAULT
+MaxProtocol = TLSv1.2
VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem
VerifyMode = Peer
[10-alpn-preferred-over-npn-client]
CipherString = DEFAULT
+MaxProtocol = TLSv1.2
VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem
VerifyMode = Peer
[11-sni-npn-preferred-over-alpn-client]
CipherString = DEFAULT
+MaxProtocol = TLSv1.2
VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem
VerifyMode = Peer
[12-npn-simple-resumption-client]
CipherString = DEFAULT
+MaxProtocol = TLSv1.2
VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem
VerifyMode = Peer
[13-npn-server-switch-resumption-client]
CipherString = DEFAULT
+MaxProtocol = TLSv1.2
VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem
VerifyMode = Peer
[14-npn-client-switch-resumption-client]
CipherString = DEFAULT
+MaxProtocol = TLSv1.2
VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem
VerifyMode = Peer
[14-npn-client-switch-resumption-resume-client]
CipherString = DEFAULT
+MaxProtocol = TLSv1.2
VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem
VerifyMode = Peer
[15-npn-client-first-pref-on-mismatch-resumption-client]
CipherString = DEFAULT
+MaxProtocol = TLSv1.2
VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem
VerifyMode = Peer
[16-npn-no-server-support-resumption-client]
CipherString = DEFAULT
+MaxProtocol = TLSv1.2
VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem
VerifyMode = Peer
[17-npn-no-client-support-resumption-client]
CipherString = DEFAULT
+MaxProtocol = TLSv1.2
VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem
VerifyMode = Peer
[17-npn-no-client-support-resumption-resume-client]
CipherString = DEFAULT
+MaxProtocol = TLSv1.2
VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem
VerifyMode = Peer
[18-alpn-preferred-over-npn-resumption-client]
CipherString = DEFAULT
+MaxProtocol = TLSv1.2
VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem
VerifyMode = Peer
[19-npn-used-if-alpn-not-supported-resumption-client]
CipherString = DEFAULT
+MaxProtocol = TLSv1.2
VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem
VerifyMode = Peer
# https://www.openssl.org/source/license.html
-## Test version negotiation
+## Test NPN. Note that NPN is only supported up to TLSv1.2
use strict;
use warnings;
package ssltests;
-
our @tests = (
{
name => "npn-simple",
extra => {
"NPNProtocols" => "foo",
},
+ "MaxProtocol" => "TLSv1.2"
},
test => {
"ExpectedNPNProtocol" => "foo",
extra => {
"NPNProtocols" => "foo,bar",
},
+ "MaxProtocol" => "TLSv1.2"
},
test => {
"ExpectedNPNProtocol" => "bar",
extra => {
"NPNProtocols" => "foo,bar",
},
+ "MaxProtocol" => "TLSv1.2"
},
test => {
"ExpectedNPNProtocol" => "bar",
extra => {
"NPNProtocols" => "foo,bar",
},
+ "MaxProtocol" => "TLSv1.2"
},
test => {
"ExpectedNPNProtocol" => "foo",
},
{
name => "npn-no-server-support",
- server => { },
+ server => {},
client => {
extra => {
"NPNProtocols" => "foo",
},
+ "MaxProtocol" => "TLSv1.2"
},
test => {
"ExpectedNPNProtocol" => undef,
"NPNProtocols" => "foo",
},
},
- client => { },
+ client => {
+ "MaxProtocol" => "TLSv1.2"
+ },
test => {
"ExpectedNPNProtocol" => undef,
},
"NPNProtocols" => "foo,bar",
"ServerName" => "server1",
},
+ "MaxProtocol" => "TLSv1.2"
},
test => {
"ExpectedServerName" => "server1",
"NPNProtocols" => "foo,bar",
"ServerName" => "server2",
},
+ "MaxProtocol" => "TLSv1.2"
},
test => {
"ExpectedServerName" => "server2",
"NPNProtocols" => "foo,bar",
"ServerName" => "server2",
},
+ "MaxProtocol" => "TLSv1.2"
},
test => {
"ExpectedServerName" => "server2",
"NPNProtocols" => "foo,bar",
"ServerName" => "server2",
},
+ "MaxProtocol" => "TLSv1.2"
},
test => {
"ExpectedServerName" => "server2",
"ALPNProtocols" => "foo",
"NPNProtocols" => "bar",
},
+ "MaxProtocol" => "TLSv1.2"
},
test => {
"ExpectedALPNProtocol" => "foo",
"ALPNProtocols" => "foo",
"NPNProtocols" => "bar",
},
+ "MaxProtocol" => "TLSv1.2"
},
test => {
"ExpectedALPNProtocol" => undef,
extra => {
"NPNProtocols" => "foo",
},
+ "MaxProtocol" => "TLSv1.2"
},
test => {
"HandshakeMode" => "Resume",
extra => {
"NPNProtocols" => "foo,bar,baz",
},
+ "MaxProtocol" => "TLSv1.2"
},
test => {
"HandshakeMode" => "Resume",
extra => {
"NPNProtocols" => "foo,baz",
},
+ "MaxProtocol" => "TLSv1.2"
},
resume_client => {
extra => {
"NPNProtocols" => "bar,baz",
},
+ "MaxProtocol" => "TLSv1.2"
},
test => {
"HandshakeMode" => "Resume",
extra => {
"NPNProtocols" => "foo,bar",
},
+ "MaxProtocol" => "TLSv1.2"
},
test => {
"HandshakeMode" => "Resume",
extra => {
"NPNProtocols" => "foo",
},
+ "MaxProtocol" => "TLSv1.2"
},
test => {
"HandshakeMode" => "Resume",
extra => {
"NPNProtocols" => "foo",
},
+ "MaxProtocol" => "TLSv1.2"
+ },
+ resume_client => {
+ "MaxProtocol" => "TLSv1.2"
},
- resume_client => { },
test => {
"HandshakeMode" => "Resume",
"ResumptionExpected" => "Yes",
"ALPNProtocols" => "foo",
"NPNProtocols" => "bar,baz",
},
+ "MaxProtocol" => "TLSv1.2"
},
test => {
"HandshakeMode" => "Resume",
"ALPNProtocols" => "foo",
"NPNProtocols" => "bar,baz",
},
+ "MaxProtocol" => "TLSv1.2"
},
test => {
"HandshakeMode" => "Resume",