s->servername_done = s->session->ext.hostname
&& PACKET_equal(&hostname, s->session->ext.hostname,
strlen(s->session->ext.hostname));
+
+ if (!s->servername_done && s->session->ext.hostname != NULL)
+ s->ext.early_data_ok = 0;
+ }
+
+ return 1;
+}
+
+int tls_parse_ctos_maxfragmentlen(SSL *s, PACKET *pkt, unsigned int context,
+ X509 *x, size_t chainidx, int *al)
+{
+ unsigned int value;
+
+ if (PACKET_remaining(pkt) != 1 || !PACKET_get_1(pkt, &value)) {
+ *al = TLS1_AD_DECODE_ERROR;
+ return 0;
+ }
+
+ /* Received |value| should be a valid max-fragment-length code. */
+ if (!IS_MAX_FRAGMENT_LENGTH_EXT_VALID(value)) {
+ *al = SSL_AD_ILLEGAL_PARAMETER;
+ return 0;
}
+ /*
+ * RFC 6066: The negotiated length applies for the duration of the session
+ * including session resumptions.
+ * We should receive the same code as in resumed session !
+ */
+ if (s->hit && s->session->ext.max_fragment_len_mode != value) {
+ *al = SSL_AD_ILLEGAL_PARAMETER;
+ return 0;
+ }
+
+ /*
+ * Store it in session, so it'll become binding for us
+ * and we'll include it in a next Server Hello.
+ */
+ s->session->ext.max_fragment_len_mode = value;
return 1;
}
#ifndef OPENSSL_NO_TLS1_3
unsigned int group_id;
PACKET key_share_list, encoded_pt;
- const unsigned char *clntcurves, *srvrcurves;
- size_t clnt_num_curves, srvr_num_curves;
- int group_nid, found = 0;
- unsigned int curve_flags;
+ const uint16_t *clntgroups, *srvrgroups;
+ size_t clnt_num_groups, srvr_num_groups;
+ int found = 0;
if (s->hit && (s->ext.psk_kex_mode & TLSEXT_KEX_MODE_FLAG_KE_DHE) == 0)
return 1;
return 0;
}
- /* Get our list of supported curves */
- if (!tls1_get_curvelist(s, 0, &srvrcurves, &srvr_num_curves)) {
- *al = SSL_AD_INTERNAL_ERROR;
- SSLerr(SSL_F_TLS_PARSE_CTOS_KEY_SHARE, ERR_R_INTERNAL_ERROR);
- return 0;
- }
-
- /* Get the clients list of supported curves. */
- if (!tls1_get_curvelist(s, 1, &clntcurves, &clnt_num_curves)) {
- *al = SSL_AD_INTERNAL_ERROR;
- SSLerr(SSL_F_TLS_PARSE_CTOS_KEY_SHARE, ERR_R_INTERNAL_ERROR);
- return 0;
- }
- if (clnt_num_curves == 0) {
+ /* Get our list of supported groups */
+ tls1_get_supported_groups(s, &srvrgroups, &srvr_num_groups);
+ /* Get the clients list of supported groups. */
+ tls1_get_peer_groups(s, &clntgroups, &clnt_num_groups);
+ if (clnt_num_groups == 0) {
/*
* This can only happen if the supported_groups extension was not sent,
* because we verify that the length is non-zero when we process that
continue;
/* Check if this share is in supported_groups sent from client */
- if (!check_in_list(s, group_id, clntcurves, clnt_num_curves, 0)) {
+ if (!check_in_list(s, group_id, clntgroups, clnt_num_groups, 0)) {
*al = SSL_AD_ILLEGAL_PARAMETER;
SSLerr(SSL_F_TLS_PARSE_CTOS_KEY_SHARE, SSL_R_BAD_KEY_SHARE);
return 0;
}
/* Check if this share is for a group we can use */
- if (!check_in_list(s, group_id, srvrcurves, srvr_num_curves, 1)) {
+ if (!check_in_list(s, group_id, srvrgroups, srvr_num_groups, 1)) {
/* Share not suitable */
continue;
}
- group_nid = tls1_ec_curve_id2nid(group_id, &curve_flags);
-
- if (group_nid == 0) {
+ if ((s->s3->peer_tmp = ssl_generate_param_group(group_id)) == NULL) {
*al = SSL_AD_INTERNAL_ERROR;
SSLerr(SSL_F_TLS_PARSE_CTOS_KEY_SHARE,
SSL_R_UNABLE_TO_FIND_ECDH_PARAMETERS);
return 0;
}
- if ((curve_flags & TLS_CURVE_TYPE) == TLS_CURVE_CUSTOM) {
- /* Can happen for some curves, e.g. X25519 */
- EVP_PKEY *key = EVP_PKEY_new();
-
- if (key == NULL || !EVP_PKEY_set_type(key, group_nid)) {
- *al = SSL_AD_INTERNAL_ERROR;
- SSLerr(SSL_F_TLS_PARSE_CTOS_KEY_SHARE, ERR_R_EVP_LIB);
- EVP_PKEY_free(key);
- return 0;
- }
- s->s3->peer_tmp = key;
- } else {
- /* Set up EVP_PKEY with named curve as parameters */
- EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL);
-
- if (pctx == NULL
- || EVP_PKEY_paramgen_init(pctx) <= 0
- || EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx,
- group_nid) <= 0
- || EVP_PKEY_paramgen(pctx, &s->s3->peer_tmp) <= 0) {
- *al = SSL_AD_INTERNAL_ERROR;
- SSLerr(SSL_F_TLS_PARSE_CTOS_KEY_SHARE, ERR_R_EVP_LIB);
- EVP_PKEY_CTX_free(pctx);
- return 0;
- }
- EVP_PKEY_CTX_free(pctx);
- pctx = NULL;
- }
s->s3->group_id = group_id;
if (!EVP_PKEY_set1_tls_encodedpoint(s->s3->peer_tmp,
OPENSSL_free(s->session->ext.supportedgroups);
s->session->ext.supportedgroups = NULL;
s->session->ext.supportedgroups_len = 0;
- if (!PACKET_memdup(&supported_groups_list,
+ if (!tls1_save_u16(&supported_groups_list,
&s->session->ext.supportedgroups,
&s->session->ext.supportedgroups_len)) {
*al = SSL_AD_INTERNAL_ERROR;
memcpy(sess->sid_ctx, s->sid_ctx, s->sid_ctx_length);
sess->sid_ctx_length = s->sid_ctx_length;
ext = 1;
+ if (id == 0)
+ s->ext.early_data_ok = 1;
} else {
uint32_t ticket_age = 0, now, agesec, agems;
int ret = tls_decrypt_ticket(s, PACKET_data(&identity),
* Therefore we add 1000ms to our age calculation to adjust for
* rounding errors.
*/
- if (sess->timeout >= (long)agesec
+ if (id == 0
+ && sess->timeout >= (long)agesec
&& agems / (uint32_t)1000 == agesec
&& ticket_age <= agems + 1000
&& ticket_age + TICKET_AGE_ALLOWANCE >= agems + 1000) {
/* The ciphersuite is not compatible with this session. */
SSL_SESSION_free(sess);
sess = NULL;
+ s->ext.early_data_ok = 0;
continue;
}
break;
return EXT_RETURN_SENT;
}
+/* Add/include the server's max fragment len extension into ServerHello */
+EXT_RETURN tls_construct_stoc_maxfragmentlen(SSL *s, WPACKET *pkt,
+ unsigned int context, X509 *x,
+ size_t chainidx, int *al)
+{
+ if (!USE_MAX_FRAGMENT_LENGTH_EXT(s->session))
+ return EXT_RETURN_NOT_SENT;
+
+ /*-
+ * 4 bytes for this extension type and extension length
+ * 1 byte for the Max Fragment Length code value.
+ */
+ if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_max_fragment_length)
+ || !WPACKET_start_sub_packet_u16(pkt)
+ || !WPACKET_put_bytes_u8(pkt, s->session->ext.max_fragment_len_mode)
+ || !WPACKET_close(pkt)) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_STOC_MAXFRAGMENTLEN, ERR_R_INTERNAL_ERROR);
+ return EXT_RETURN_FAIL;
+ }
+
+ return EXT_RETURN_SENT;
+}
+
#ifndef OPENSSL_NO_EC
EXT_RETURN tls_construct_stoc_ec_pt_formats(SSL *s, WPACKET *pkt,
unsigned int context, X509 *x,
unsigned int context, X509 *x,
size_t chainidx, int *al)
{
- const unsigned char *groups;
+ const uint16_t *groups;
size_t numgroups, i, first = 1;
/* s->s3->group_id is non zero if we accepted a key_share */
return EXT_RETURN_NOT_SENT;
/* Get our list of supported groups */
- if (!tls1_get_curvelist(s, 0, &groups, &numgroups) || numgroups == 0) {
+ tls1_get_supported_groups(s, &groups, &numgroups);
+ if (numgroups == 0) {
SSLerr(SSL_F_TLS_CONSTRUCT_STOC_SUPPORTED_GROUPS, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
/* Copy group ID if supported */
- for (i = 0; i < numgroups; i++, groups += 2) {
- if (tls_curve_allowed(s, groups, SSL_SECOP_CURVE_SUPPORTED)) {
+ for (i = 0; i < numgroups; i++) {
+ uint16_t group = groups[i];
+
+ if (tls_curve_allowed(s, group, SSL_SECOP_CURVE_SUPPORTED)) {
if (first) {
/*
* Check if the client is already using our preferred group. If
* so we don't need to add this extension
*/
- if (s->s3->group_id == GET_GROUP_ID(groups, 0))
+ if (s->s3->group_id == group)
return EXT_RETURN_NOT_SENT;
/* Add extension header */
first = 0;
}
- if (!WPACKET_put_bytes_u16(pkt, GET_GROUP_ID(groups, 0))) {
+ if (!WPACKET_put_bytes_u16(pkt, group)) {
SSLerr(SSL_F_TLS_CONSTRUCT_STOC_SUPPORTED_GROUPS,
ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;