return EXT_RETURN_SENT;
}
+/* Push a Max Fragment Len extension into ClientHello */
+EXT_RETURN tls_construct_ctos_maxfragmentlen(SSL *s, WPACKET *pkt,
+ unsigned int context, X509 *x,
+ size_t chainidx, int *al)
+{
+ if (s->ext.max_fragment_len_mode == TLSEXT_max_fragment_length_DISABLED)
+ return EXT_RETURN_NOT_SENT;
+
+ /* Add Max Fragment Length extension if client enabled it. */
+ /*-
+ * 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)
+ /* Sub-packet for Max Fragment Length extension (1 byte) */
+ || !WPACKET_start_sub_packet_u16(pkt)
+ || !WPACKET_put_bytes_u8(pkt, s->ext.max_fragment_len_mode)
+ || !WPACKET_close(pkt)) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_MAXFRAGMENTLEN, ERR_R_INTERNAL_ERROR);
+ return EXT_RETURN_FAIL;
+ }
+
+ return EXT_RETURN_SENT;
+}
+
#ifndef OPENSSL_NO_SRP
EXT_RETURN tls_construct_ctos_srp(SSL *s, WPACKET *pkt, unsigned int context,
X509 *x, size_t chainidx, int *al)
unsigned int context, X509 *x,
size_t chainidx, int *al)
{
- const unsigned char *pcurves = NULL, *pcurvestmp;
- size_t num_curves = 0, i;
+ const uint16_t *pgroups = NULL;
+ size_t num_groups = 0, i;
if (!use_ecc(s))
return EXT_RETURN_NOT_SENT;
* Add TLS extension supported_groups to the ClientHello message
*/
/* TODO(TLS1.3): Add support for DHE groups */
- if (!tls1_get_curvelist(s, 0, &pcurves, &num_curves)) {
- SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_GROUPS,
- ERR_R_INTERNAL_ERROR);
- return EXT_RETURN_FAIL;
- }
- pcurvestmp = pcurves;
+ tls1_get_supported_groups(s, &pgroups, &num_groups);
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_supported_groups)
/* Sub-packet for supported_groups extension */
return EXT_RETURN_FAIL;
}
/* Copy curve ID if supported */
- for (i = 0; i < num_curves; i++, pcurvestmp += 2) {
- if (tls_curve_allowed(s, pcurvestmp, SSL_SECOP_CURVE_SUPPORTED)) {
- if (!WPACKET_put_bytes_u8(pkt, pcurvestmp[0])
- || !WPACKET_put_bytes_u8(pkt, pcurvestmp[1])) {
+ for (i = 0; i < num_groups; i++) {
+ uint16_t ctmp = pgroups[i];
+
+ if (tls_curve_allowed(s, ctmp, SSL_SECOP_CURVE_SUPPORTED)) {
+ if (!WPACKET_put_bytes_u16(pkt, ctmp)) {
SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_GROUPS,
ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
*/
key_share_key = s->s3->tmp.pkey;
} else {
- key_share_key = ssl_generate_pkey_curve(curve_id);
+ key_share_key = ssl_generate_pkey_group(curve_id);
if (key_share_key == NULL) {
SSLerr(SSL_F_ADD_KEY_SHARE, ERR_R_EVP_LIB);
return 0;
size_t chainidx, int *al)
{
#ifndef OPENSSL_NO_TLS1_3
- size_t i, num_curves = 0;
- const unsigned char *pcurves = NULL;
- unsigned int curve_id = 0;
+ size_t i, num_groups = 0;
+ const uint16_t *pgroups = NULL;
+ uint16_t curve_id = 0;
/* key_share extension */
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_key_share)
return EXT_RETURN_FAIL;
}
- if (!tls1_get_curvelist(s, 0, &pcurves, &num_curves)) {
- SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_KEY_SHARE, ERR_R_INTERNAL_ERROR);
- return EXT_RETURN_FAIL;
- }
+ tls1_get_supported_groups(s, &pgroups, &num_groups);
/*
* TODO(TLS1.3): Make the number of key_shares sent configurable. For
if (s->s3->group_id != 0) {
curve_id = s->s3->group_id;
} else {
- for (i = 0; i < num_curves; i++, pcurves += 2) {
+ for (i = 0; i < num_groups; i++) {
- if (!tls_curve_allowed(s, pcurves, SSL_SECOP_CURVE_SUPPORTED))
+ if (!tls_curve_allowed(s, pgroups[i], SSL_SECOP_CURVE_SUPPORTED))
continue;
- curve_id = bytestogroup(pcurves);
+ curve_id = pgroups[i];
break;
}
}
unsigned int context, X509 *x,
size_t chainidx, int *al)
{
- const unsigned char *id;
+ const unsigned char *id = NULL;
size_t idlen = 0;
SSL_SESSION *psksess = NULL;
SSL_SESSION *edsess = NULL;
edsess = s->session->ext.max_early_data != 0 ? s->session : psksess;
s->max_early_data = edsess->ext.max_early_data;
- if ((s->ext.hostname == NULL && edsess->ext.hostname != NULL)
- || (s->ext.hostname != NULL
- && (edsess->ext.hostname == NULL
- || strcmp(s->ext.hostname, edsess->ext.hostname) != 0))) {
- SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA,
- SSL_R_INCONSISTENT_EARLY_DATA_SNI);
- return EXT_RETURN_FAIL;
+ if (edsess->ext.hostname != NULL) {
+ if (s->ext.hostname == NULL
+ || (s->ext.hostname != NULL
+ && strcmp(s->ext.hostname, edsess->ext.hostname) != 0)) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA,
+ SSL_R_INCONSISTENT_EARLY_DATA_SNI);
+ return EXT_RETURN_FAIL;
+ }
}
if ((s->ext.alpn == NULL && edsess->ext.alpn_selected != NULL)) {
* 1 byte long so as not to have an empty extension last (WebSphere 7.x,
* 8.x are intolerant of that condition)
*/
- if (hlen >= 4)
+ if (hlen > 4)
hlen -= 4;
else
hlen = 1;
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_padding)
|| !WPACKET_sub_allocate_bytes_u16(pkt, hlen, &padbytes)) {
SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_PADDING, ERR_R_INTERNAL_ERROR);
- return 0;
+ return EXT_RETURN_FAIL;
}
memset(padbytes, 0, hlen);
}
err:
return ret;
#else
- return 1;
+ return EXT_RETURN_NOT_SENT;
#endif
}
return 1;
}
+/* Parse the server's max fragment len extension packet */
+int tls_parse_stoc_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;
+ }
+
+ /* |value| should contains a valid max-fragment-length code. */
+ if (!IS_MAX_FRAGMENT_LENGTH_EXT_VALID(value)) {
+ *al = SSL_AD_ILLEGAL_PARAMETER;
+ return 0;
+ }
+
+ /* Must be the same value as client-configured one who was sent to server */
+ /*-
+ * RFC 6066: if a client receives a maximum fragment length negotiation
+ * response that differs from the length it requested, ...
+ * It must abort with SSL_AD_ILLEGAL_PARAMETER alert
+ */
+ if (value != s->ext.max_fragment_len_mode) {
+ *al = SSL_AD_ILLEGAL_PARAMETER;
+ return 0;
+ }
+
+ /*
+ * Maximum Fragment Length Negotiation succeeded.
+ * The negotiated Maximum Fragment Length is binding now.
+ */
+ s->session->ext.max_fragment_len_mode = value;
+
+ return 1;
+}
+
int tls_parse_stoc_server_name(SSL *s, PACKET *pkt, unsigned int context,
X509 *x, size_t chainidx, int *al)
{
OPENSSL_free(s->ext.scts);
s->ext.scts = NULL;
- s->ext.scts_len = size;
+ s->ext.scts_len = (uint16_t)size;
if (size > 0) {
s->ext.scts = OPENSSL_malloc(size);
if (s->ext.scts == NULL
}
s->s3->alpn_selected_len = len;
- if (s->session->ext.alpn_selected != NULL
- && (s->session->ext.alpn_selected_len != len
- || memcmp(s->session->ext.alpn_selected, s->s3->alpn_selected,
- len) != 0)) {
+ if (s->session->ext.alpn_selected == NULL
+ || s->session->ext.alpn_selected_len != len
+ || memcmp(s->session->ext.alpn_selected, s->s3->alpn_selected, len)
+ != 0) {
/* ALPN not consistent with the old session so cannot use early_data */
s->ext.early_data_ok = 0;
}
}
if ((context & SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST) != 0) {
- unsigned const char *pcurves = NULL;
- size_t i, num_curves;
+ const uint16_t *pgroups = NULL;
+ size_t i, num_groups;
if (PACKET_remaining(pkt) != 0) {
*al = SSL_AD_DECODE_ERROR;
}
/* Validate the selected group is one we support */
- if (!tls1_get_curvelist(s, 0, &pcurves, &num_curves)) {
- SSLerr(SSL_F_TLS_PARSE_STOC_KEY_SHARE, ERR_R_INTERNAL_ERROR);
- return 0;
- }
- for (i = 0; i < num_curves; i++, pcurves += 2) {
- if (group_id == bytestogroup(pcurves))
+ tls1_get_supported_groups(s, &pgroups, &num_groups);
+ for (i = 0; i < num_groups; i++) {
+ if (group_id == pgroups[i])
break;
}
- if (i >= num_curves
- || !tls_curve_allowed(s, pcurves, SSL_SECOP_CURVE_SUPPORTED)) {
+ if (i >= num_groups
+ || !tls_curve_allowed(s, group_id, SSL_SECOP_CURVE_SUPPORTED)) {
*al = SSL_AD_ILLEGAL_PARAMETER;
SSLerr(SSL_F_TLS_PARSE_STOC_KEY_SHARE, SSL_R_BAD_KEY_SHARE);
return 0;