/*
- * Copyright 2016-2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
{
int currv, min_version, max_version, reason;
+ reason = ssl_get_min_max_version(s, &min_version, &max_version);
+ if (reason != 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_VERSIONS, reason);
+ return EXT_RETURN_FAIL;
+ }
+
+ /*
+ * Don't include this if we can't negotiate TLSv1.3. We can do a straight
+ * comparison here because we will never be called in DTLS.
+ */
+ if (max_version < TLS1_3_VERSION)
+ return EXT_RETURN_NOT_SENT;
+
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_supported_versions)
|| !WPACKET_start_sub_packet_u16(pkt)
|| !WPACKET_start_sub_packet_u8(pkt)) {
return EXT_RETURN_FAIL;
}
- reason = ssl_get_min_max_version(s, &min_version, &max_version);
- if (reason != 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_VERSIONS, reason);
- return EXT_RETURN_FAIL;
- }
-
/*
* TODO(TLS1.3): There is some discussion on the TLS list as to whether
* we should include versions <TLS1.2. For the moment we do. To be
size_t encodedlen;
if (s->s3->tmp.pkey != NULL) {
- if (!ossl_assert(s->hello_retry_request)) {
+ if (!ossl_assert(s->hello_retry_request == SSL_HRR_PENDING)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_ADD_KEY_SHARE,
ERR_R_INTERNAL_ERROR);
return 0;
SSL_SESSION *edsess = NULL;
const EVP_MD *handmd = NULL;
- if (s->hello_retry_request)
+ if (s->hello_retry_request == SSL_HRR_PENDING)
handmd = ssl_handshake_md(s);
if (s->psk_use_session_cb != NULL
|| (s->session->ext.ticklen == 0 && s->psksession == NULL))
return EXT_RETURN_NOT_SENT;
- if (s->hello_retry_request)
+ if (s->hello_retry_request == SSL_HRR_PENDING)
handmd = ssl_handshake_md(s);
if (s->session->ext.ticklen != 0) {
goto dopsksess;
}
- if (s->hello_retry_request && mdres != handmd) {
+ if (s->hello_retry_request == SSL_HRR_PENDING && mdres != handmd) {
/*
* Selected ciphersuite hash does not match the hash for the session
* so we can't use it.
*/
now = (uint32_t)time(NULL);
agesec = now - (uint32_t)s->session->time;
+ /*
+ * We calculate the age in seconds but the server may work in ms. Due to
+ * rounding errors we could overestimate the age by up to 1s. It is
+ * better to underestimate it. Otherwise, if the RTT is very short, when
+ * the server calculates the age reported by the client it could be
+ * bigger than the age calculated on the server - which should never
+ * happen.
+ */
+ if (agesec > 0)
+ agesec--;
if (s->session->ext.tick_lifetime_hint < agesec) {
/* Ticket is too old. Ignore it. */
return EXT_RETURN_FAIL;
}
- if (s->hello_retry_request && mdpsk != handmd) {
+ if (s->hello_retry_request == SSL_HRR_PENDING && mdpsk != handmd) {
/*
* Selected ciphersuite hash does not match the hash for the PSK
* session. This is an application bug.
#endif
}
+EXT_RETURN tls_construct_ctos_post_handshake_auth(SSL *s, WPACKET *pkt,
+ unsigned int context,
+ X509 *x, size_t chainidx)
+{
+#ifndef OPENSSL_NO_TLS1_3
+ if (!s->pha_forced) {
+ int i, n = 0;
+
+ /* check for cert, if present, we can do post-handshake auth */
+ if (s->cert == NULL)
+ return EXT_RETURN_NOT_SENT;
+
+ for (i = 0; i < SSL_PKEY_NUM; i++) {
+ if (s->cert->pkeys[i].x509 != NULL
+ && s->cert->pkeys[i].privatekey != NULL)
+ n++;
+ }
+
+ /* no identity certificates, so no extension */
+ if (n == 0)
+ return EXT_RETURN_NOT_SENT;
+ }
+
+ /* construct extension - 0 length, no contents */
+ if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_post_handshake_auth)
+ || !WPACKET_start_sub_packet_u16(pkt)
+ || !WPACKET_close(pkt)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_CONSTRUCT_CTOS_POST_HANDSHAKE_AUTH,
+ ERR_R_INTERNAL_ERROR);
+ return EXT_RETURN_FAIL;
+ }
+
+ s->post_handshake_auth = SSL_PHA_EXT_SENT;
+
+ return EXT_RETURN_SENT;
+#else
+ return EXT_RETURN_NOT_SENT;
+#endif
+}
+
+
/*
* Parse the server's renegotiation binding and abort if it's not right
*/
unsigned int value;
if (PACKET_remaining(pkt) != 1 || !PACKET_get_1(pkt, &value)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_MAXFRAGMENTLEN,
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_MAXFRAGMENTLEN,
SSL_R_BAD_EXTENSION);
return 0;
}
int tls_parse_stoc_ec_pt_formats(SSL *s, PACKET *pkt, unsigned int context,
X509 *x, size_t chainidx)
{
- unsigned int ecpointformats_len;
+ size_t ecpointformats_len;
PACKET ecptformatlist;
if (!PACKET_as_length_prefixed_1(pkt, &ecptformatlist)) {
}
if (!s->hit) {
ecpointformats_len = PACKET_remaining(&ecptformatlist);
- s->session->ext.ecpointformats_len = 0;
+ if (ecpointformats_len == 0) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR,
+ SSL_F_TLS_PARSE_STOC_EC_PT_FORMATS, SSL_R_BAD_LENGTH);
+ return 0;
+ }
+ s->session->ext.ecpointformats_len = 0;
OPENSSL_free(s->session->ext.ecpointformats);
s->session->ext.ecpointformats = OPENSSL_malloc(ecpointformats_len);
if (s->session->ext.ecpointformats == NULL) {
return 1;
}
+int tls_parse_stoc_supported_versions(SSL *s, PACKET *pkt, unsigned int context,
+ X509 *x, size_t chainidx)
+{
+ unsigned int version;
+
+ if (!PACKET_get_net_2(pkt, &version)
+ || PACKET_remaining(pkt) != 0) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR,
+ SSL_F_TLS_PARSE_STOC_SUPPORTED_VERSIONS,
+ SSL_R_LENGTH_MISMATCH);
+ return 0;
+ }
+
+ /* TODO(TLS1.3): Remove this before release */
+ if (version == TLS1_3_VERSION_DRAFT)
+ version = TLS1_3_VERSION;
+
+ /* We ignore this extension for HRRs except to sanity check it */
+ if (context == SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST) {
+ /*
+ * The only protocol version we support which has an HRR message is
+ * TLSv1.3, therefore we shouldn't be getting an HRR for anything else.
+ */
+ if (version != TLS1_3_VERSION) {
+ SSLfatal(s, SSL_AD_PROTOCOL_VERSION,
+ SSL_F_TLS_PARSE_STOC_SUPPORTED_VERSIONS,
+ SSL_R_BAD_HRR_VERSION);
+ return 0;
+ }
+ return 1;
+ }
+
+ /* We just set it here. We validate it in ssl_choose_client_version */
+ s->version = version;
+
+ return 1;
+}
+
int tls_parse_stoc_key_share(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
size_t chainidx)
{