TLS_MD_SERVER_FINISH_CONST,TLS_MD_SERVER_FINISH_CONST_SIZE,
tls1_alert_code,
tls1_export_keying_material,
+ 0,
+ SSL3_HM_HEADER_LENGTH,
+ ssl3_set_handshake_header,
+ ssl3_handshake_write
+ };
+
+SSL3_ENC_METHOD TLSv1_1_enc_data={
+ tls1_enc,
+ tls1_mac,
+ tls1_setup_key_block,
+ tls1_generate_master_secret,
+ tls1_change_cipher_state,
+ tls1_final_finish_mac,
+ TLS1_FINISH_MAC_LENGTH,
+ tls1_cert_verify_mac,
+ TLS_MD_CLIENT_FINISH_CONST,TLS_MD_CLIENT_FINISH_CONST_SIZE,
+ TLS_MD_SERVER_FINISH_CONST,TLS_MD_SERVER_FINISH_CONST_SIZE,
+ tls1_alert_code,
+ tls1_export_keying_material,
+ SSL_ENC_FLAG_EXPLICIT_IV,
+ SSL3_HM_HEADER_LENGTH,
+ ssl3_set_handshake_header,
+ ssl3_handshake_write
+ };
+
+SSL3_ENC_METHOD TLSv1_2_enc_data={
+ tls1_enc,
+ tls1_mac,
+ tls1_setup_key_block,
+ tls1_generate_master_secret,
+ tls1_change_cipher_state,
+ tls1_final_finish_mac,
+ TLS1_FINISH_MAC_LENGTH,
+ tls1_cert_verify_mac,
+ TLS_MD_CLIENT_FINISH_CONST,TLS_MD_CLIENT_FINISH_CONST_SIZE,
+ TLS_MD_SERVER_FINISH_CONST,TLS_MD_SERVER_FINISH_CONST_SIZE,
+ tls1_alert_code,
+ tls1_export_keying_material,
+ SSL_ENC_FLAG_EXPLICIT_IV|SSL_ENC_FLAG_SIGALGS|SSL_ENC_FLAG_SHA256_PRF
+ |SSL_ENC_FLAG_TLS1_2_CIPHERS,
+ SSL3_HM_HEADER_LENGTH,
+ ssl3_set_handshake_header,
+ ssl3_handshake_write
};
long tls1_default_timeout(void)
NID_secp256k1, /* secp256k1 (22) */
NID_X9_62_prime256v1, /* secp256r1 (23) */
NID_secp384r1, /* secp384r1 (24) */
- NID_secp521r1 /* secp521r1 (25) */
+ NID_secp521r1, /* secp521r1 (25) */
+ NID_brainpoolP256r1, /* brainpoolP256r1 (26) */
+ NID_brainpoolP384r1, /* brainpoolP384r1 (27) */
+ NID_brainpoolP512r1 /* brainpool512r1 (28) */
};
0,14, /* sect571r1 (14) */
0,13, /* sect571k1 (13) */
0,25, /* secp521r1 (25) */
+ 0,28, /* brainpool512r1 (28) */
0,11, /* sect409k1 (11) */
0,12, /* sect409r1 (12) */
+ 0,27, /* brainpoolP384r1 (27) */
0,24, /* secp384r1 (24) */
0,9, /* sect283k1 (9) */
0,10, /* sect283r1 (10) */
+ 0,26, /* brainpoolP256r1 (26) */
0,22, /* secp256k1 (22) */
0,23, /* secp256r1 (23) */
0,8, /* sect239k1 (8) */
return 24;
case NID_secp521r1: /* secp521r1 (25) */
return 25;
+ case NID_brainpoolP256r1: /* brainpoolP256r1 (26) */
+ return 26;
+ case NID_brainpoolP384r1: /* brainpoolP384r1 (27) */
+ return 27;
+ case NID_brainpoolP512r1: /* brainpool512r1 (28) */
+ return 28;
default:
return 0;
}
return 1;
}
-#define MAX_CURVELIST 25
+#define MAX_CURVELIST 28
typedef struct
{
{
int is_prime, id;
const EC_GROUP *grp;
- const EC_POINT *pt;
const EC_METHOD *meth;
if (!ec)
return 0;
/* Determine if it is a prime field */
grp = EC_KEY_get0_group(ec);
- pt = EC_KEY_get0_public_key(ec);
- if (!grp || !pt)
+ if (!grp)
return 0;
meth = EC_GROUP_method_of(grp);
if (!meth)
}
if (comp_id)
{
+ if (EC_KEY_get0_public_key(ec) == NULL)
+ return 0;
if (EC_KEY_get_conv_form(ec) == POINT_CONVERSION_COMPRESSED)
{
if (is_prime)
#ifndef OPENSSL_NO_SHA
tlsext_sigalg(TLSEXT_hash_sha1)
#endif
-#ifndef OPENSSL_NO_MD5
- tlsext_sigalg_rsa(TLSEXT_hash_md5)
-#endif
};
#ifndef OPENSSL_NO_ECDSA
static unsigned char suiteb_sigalgs[] = {
else
{
*psigs = tls12_sigalgs;
-#ifdef OPENSSL_FIPS
- /* If FIPS mode don't include MD5 which is last */
- if (FIPS_mode())
- return sizeof(tls12_sigalgs) - 2;
- else
-#endif
- return sizeof(tls12_sigalgs);
+ return sizeof(tls12_sigalgs);
}
}
/* Check signature algorithm is consistent with sent supported signature
int have_rsa = 0, have_dsa = 0, have_ecdsa = 0;
c->mask_a = 0;
c->mask_k = 0;
- /* If less than TLS 1.2 don't allow TLS 1.2 only ciphers */
- if (TLS1_get_client_version(s) < TLS1_2_VERSION)
+ /* Don't allow TLS 1.2 only ciphers if we don't suppport them */
+ if (!SSL_CLIENT_USE_TLS1_2_CIPHERS(s))
c->mask_ssl = SSL_TLSV1_2;
else
c->mask_ssl = 0;
c->mask_k |= SSL_kPSK;
}
#endif /* OPENSSL_NO_PSK */
+#ifndef OPENSSL_NO_SRP
+ if (!(s->srp_ctx.srp_Mask & SSL_kSRP))
+ {
+ c->mask_a |= SSL_aSRP;
+ c->mask_k |= SSL_kSRP;
+ }
+#endif
c->valid = 1;
}
-/* byte_compare is a compare function for qsort(3) that compares bytes. */
-static int byte_compare(const void *in_a, const void *in_b)
- {
- unsigned char a = *((const unsigned char*) in_a);
- unsigned char b = *((const unsigned char*) in_b);
-
- if (a > b)
- return 1;
- else if (a < b)
- return -1;
- return 0;
-}
-
-unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *p, unsigned char *limit)
+unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *buf, unsigned char *limit, int *al)
{
int extdatalen=0;
- unsigned char *ret = p;
+ unsigned char *orig = buf;
+ unsigned char *ret = buf;
#ifndef OPENSSL_NO_EC
/* See if we support any ECC ciphersuites */
int using_ecc = 0;
- if (s->version != DTLS1_VERSION && s->version >= TLS1_VERSION)
+ if (s->version >= TLS1_VERSION || SSL_IS_DTLS(s))
{
int i;
unsigned long alg_k, alg_a;
/* don't add extensions for SSLv3 unless doing secure renegotiation */
if (s->client_version == SSL3_VERSION
&& !s->s3->send_connection_binding)
- return p;
+ return orig;
ret+=2;
return NULL;
}
- if((limit - p - 4 - el) < 0) return NULL;
+ if((limit - ret - 4 - el) < 0) return NULL;
s2n(TLSEXT_TYPE_renegotiate,ret);
s2n(el,ret);
}
skip_ext:
- if (TLS1_get_client_version(s) >= TLS1_2_VERSION)
+ if (SSL_USE_SIGALGS(s))
{
size_t salglen;
const unsigned char *salg;
}
#ifdef TLSEXT_TYPE_opaque_prf_input
- if (s->s3->client_opaque_prf_input != NULL &&
- s->version != DTLS1_VERSION)
+ if (s->s3->client_opaque_prf_input != NULL)
{
size_t col = s->s3->client_opaque_prf_input_len;
}
#endif
- if (s->tlsext_status_type == TLSEXT_STATUSTYPE_ocsp &&
- s->version != DTLS1_VERSION)
+ if (s->tlsext_status_type == TLSEXT_STATUSTYPE_ocsp)
{
int i;
long extlen, idlen, itmp;
#ifndef OPENSSL_NO_HEARTBEATS
/* Add Heartbeat extension */
+ if ((limit - ret - 4 - 1) < 0)
+ return NULL;
s2n(TLSEXT_TYPE_heartbeat,ret);
s2n(1,ret);
/* Set mode:
}
#endif
+ if (s->alpn_client_proto_list && !s->s3->tmp.finish_md_len)
+ {
+ if ((size_t)(limit - ret) < 6 + s->alpn_client_proto_list_len)
+ return NULL;
+ s2n(TLSEXT_TYPE_application_layer_protocol_negotiation,ret);
+ s2n(2 + s->alpn_client_proto_list_len,ret);
+ s2n(s->alpn_client_proto_list_len,ret);
+ memcpy(ret, s->alpn_client_proto_list,
+ s->alpn_client_proto_list_len);
+ ret += s->alpn_client_proto_list_len;
+ }
+
if(SSL_get_srtp_profiles(s))
{
int el;
ssl_add_clienthello_use_srtp_ext(s, 0, &el, 0);
- if((limit - p - 4 - el) < 0) return NULL;
+ if((limit - ret - 4 - el) < 0) return NULL;
s2n(TLSEXT_TYPE_use_srtp,ret);
s2n(el,ret);
}
ret += el;
}
-
- /* Add TLS extension Server_Authz_DataFormats to the ClientHello */
- /* 2 bytes for extension type */
- /* 2 bytes for extension length */
- /* 1 byte for the list length */
- /* 1 byte for the list (we only support audit proofs) */
- if (s->ctx->tlsext_authz_server_audit_proof_cb != NULL)
- {
- const unsigned short ext_len = 2;
- const unsigned char list_len = 1;
-
- if (limit < ret + 6)
- return NULL;
-
- s2n(TLSEXT_TYPE_server_authz, ret);
- /* Extension length: 2 bytes */
- s2n(ext_len, ret);
- *(ret++) = list_len;
- *(ret++) = TLSEXT_AUTHZDATAFORMAT_audit_proof;
- }
-
+ custom_ext_init(&s->cert->cli_ext);
/* Add custom TLS Extensions to ClientHello */
- if (s->ctx->custom_cli_ext_records_count)
- {
- size_t i;
- custom_cli_ext_record* record;
+ if (!custom_ext_add(s, 0, &ret, limit, al))
+ return NULL;
- for (i = 0; i < s->ctx->custom_cli_ext_records_count; i++)
+ /* Add padding to workaround bugs in F5 terminators.
+ * See https://tools.ietf.org/html/draft-agl-tls-padding-03
+ *
+ * NB: because this code works out the length of all existing
+ * extensions it MUST always appear last.
+ */
+ if (s->options & SSL_OP_TLSEXT_PADDING)
+ {
+ int hlen = ret - (unsigned char *)s->init_buf->data;
+ /* The code in s23_clnt.c to build ClientHello messages
+ * includes the 5-byte record header in the buffer, while
+ * the code in s3_clnt.c does not.
+ */
+ if (s->state == SSL23_ST_CW_CLNT_HELLO_A)
+ hlen -= 5;
+ if (hlen > 0xff && hlen < 0x200)
{
- const unsigned char* out = NULL;
- unsigned short outlen = 0;
+ hlen = 0x200 - hlen;
+ if (hlen >= 4)
+ hlen -= 4;
+ else
+ hlen = 0;
- record = &s->ctx->custom_cli_ext_records[i];
- /* NULL callback sends empty extension */
- /* -1 from callback omits extension */
- if (record->fn1)
- {
- int cb_retval = 0;
- cb_retval = record->fn1(s, record->ext_type,
- &out, &outlen,
- record->arg);
- if (cb_retval == 0)
- return NULL; /* error */
- if (cb_retval == -1)
- continue; /* skip this extension */
- }
- if (limit < ret + 4 + outlen)
- return NULL;
- s2n(record->ext_type, ret);
- s2n(outlen, ret);
- memcpy(ret, out, outlen);
- ret += outlen;
+ s2n(TLSEXT_TYPE_padding, ret);
+ s2n(hlen, ret);
+ memset(ret, 0, hlen);
+ ret += hlen;
}
}
- if ((extdatalen = ret-p-2) == 0)
- return p;
+ if ((extdatalen = ret-orig-2)== 0)
+ return orig;
- s2n(extdatalen,p);
+ s2n(extdatalen, orig);
return ret;
}
-unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *p, unsigned char *limit)
+unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *buf, unsigned char *limit, int *al)
{
int extdatalen=0;
- unsigned char *ret = p;
+ unsigned char *orig = buf;
+ unsigned char *ret = buf;
#ifndef OPENSSL_NO_NEXTPROTONEG
int next_proto_neg_seen;
#endif
#endif
/* don't add extensions for SSLv3, unless doing secure renegotiation */
if (s->version == SSL3_VERSION && !s->s3->send_connection_binding)
- return p;
+ return orig;
ret+=2;
if (ret>=limit) return NULL; /* this really never occurs, but ... */
return NULL;
}
- if((limit - p - 4 - el) < 0) return NULL;
+ if((limit - ret - 4 - el) < 0) return NULL;
s2n(TLSEXT_TYPE_renegotiate,ret);
s2n(el,ret);
}
#ifndef OPENSSL_NO_EC
- if (using_ecc && s->version != DTLS1_VERSION)
+ if (using_ecc)
{
const unsigned char *plist;
size_t plistlen;
}
#ifdef TLSEXT_TYPE_opaque_prf_input
- if (s->s3->server_opaque_prf_input != NULL &&
- s->version != DTLS1_VERSION)
+ if (s->s3->server_opaque_prf_input != NULL)
{
size_t sol = s->s3->server_opaque_prf_input_len;
ssl_add_serverhello_use_srtp_ext(s, 0, &el, 0);
- if((limit - p - 4 - el) < 0) return NULL;
+ if((limit - ret - 4 - el) < 0) return NULL;
s2n(TLSEXT_TYPE_use_srtp,ret);
s2n(el,ret);
/* Add Heartbeat extension if we've received one */
if (s->tlsext_heartbeat & SSL_TLSEXT_HB_ENABLED)
{
+ if ((limit - ret - 4 - 1) < 0)
+ return NULL;
s2n(TLSEXT_TYPE_heartbeat,ret);
s2n(1,ret);
/* Set mode:
}
}
#endif
+ if (!custom_ext_add(s, 1, &ret, limit, al))
+ return NULL;
- /* If the client supports authz then see whether we have any to offer
- * to it. */
- if (s->s3->tlsext_authz_client_types_len)
+ if (s->s3->alpn_selected)
{
- size_t authz_length;
- /* By now we already know the new cipher, so we can look ahead
- * to see whether the cert we are going to send
- * has any authz data attached to it. */
- const unsigned char* authz = ssl_get_authz_data(s, &authz_length);
- const unsigned char* const orig_authz = authz;
- size_t i;
- unsigned authz_count = 0;
-
- /* The authz data contains a number of the following structures:
- * uint8_t authz_type
- * uint16_t length
- * uint8_t data[length]
- *
- * First we walk over it to find the number of authz elements. */
- for (i = 0; i < authz_length; i++)
- {
- unsigned short length;
- unsigned char type;
-
- type = *(authz++);
- if (memchr(s->s3->tlsext_authz_client_types,
- type,
- s->s3->tlsext_authz_client_types_len) != NULL)
- authz_count++;
-
- n2s(authz, length);
- /* n2s increments authz by 2 */
- i += 2;
- authz += length;
- i += length;
- }
+ const unsigned char *selected = s->s3->alpn_selected;
+ unsigned len = s->s3->alpn_selected_len;
- if (authz_count)
- {
- /* Add TLS extension server_authz to the ServerHello message
- * 2 bytes for extension type
- * 2 bytes for extension length
- * 1 byte for the list length
- * n bytes for the list */
- const unsigned short ext_len = 1 + authz_count;
-
- if ((long)(limit - ret - 4 - ext_len) < 0) return NULL;
- s2n(TLSEXT_TYPE_server_authz, ret);
- s2n(ext_len, ret);
- *(ret++) = authz_count;
- s->s3->tlsext_authz_promised_to_client = 1;
- }
+ if ((long)(limit - ret - 4 - 2 - 1 - len) < 0)
+ return NULL;
+ s2n(TLSEXT_TYPE_application_layer_protocol_negotiation,ret);
+ s2n(3 + len,ret);
+ s2n(1 + len,ret);
+ *ret++ = len;
+ memcpy(ret, selected, len);
+ ret += len;
+ }
- authz = orig_authz;
- for (i = 0; i < authz_length; i++)
- {
- unsigned short length;
- unsigned char type;
-
- authz_count++;
- type = *(authz++);
- if (memchr(s->s3->tlsext_authz_client_types,
- type,
- s->s3->tlsext_authz_client_types_len) != NULL)
- *(ret++) = type;
- n2s(authz, length);
- /* n2s increments authz by 2 */
- i += 2;
- authz += length;
- i += length;
- }
+ if ((extdatalen = ret-orig-2)== 0)
+ return orig;
+
+ s2n(extdatalen, orig);
+ return ret;
+ }
+
+#ifndef OPENSSL_NO_EC
+/* ssl_check_for_safari attempts to fingerprint Safari using OS X
+ * SecureTransport using the TLS extension block in |d|, of length |n|.
+ * Safari, since 10.6, sends exactly these extensions, in this order:
+ * SNI,
+ * elliptic_curves
+ * ec_point_formats
+ *
+ * We wish to fingerprint Safari because they broke ECDHE-ECDSA support in 10.8,
+ * but they advertise support. So enabling ECDHE-ECDSA ciphers breaks them.
+ * Sadly we cannot differentiate 10.6, 10.7 and 10.8.4 (which work), from
+ * 10.8..10.8.3 (which don't work).
+ */
+static void ssl_check_for_safari(SSL *s, const unsigned char *data, const unsigned char *d, int n) {
+ unsigned short type, size;
+ static const unsigned char kSafariExtensionsBlock[] = {
+ 0x00, 0x0a, /* elliptic_curves extension */
+ 0x00, 0x08, /* 8 bytes */
+ 0x00, 0x06, /* 6 bytes of curve ids */
+ 0x00, 0x17, /* P-256 */
+ 0x00, 0x18, /* P-384 */
+ 0x00, 0x19, /* P-521 */
+
+ 0x00, 0x0b, /* ec_point_formats */
+ 0x00, 0x02, /* 2 bytes */
+ 0x01, /* 1 point format */
+ 0x00, /* uncompressed */
+ };
+
+ /* The following is only present in TLS 1.2 */
+ static const unsigned char kSafariTLS12ExtensionsBlock[] = {
+ 0x00, 0x0d, /* signature_algorithms */
+ 0x00, 0x0c, /* 12 bytes */
+ 0x00, 0x0a, /* 10 bytes */
+ 0x05, 0x01, /* SHA-384/RSA */
+ 0x04, 0x01, /* SHA-256/RSA */
+ 0x02, 0x01, /* SHA-1/RSA */
+ 0x04, 0x03, /* SHA-256/ECDSA */
+ 0x02, 0x03, /* SHA-1/ECDSA */
+ };
+
+ if (data >= (d+n-2))
+ return;
+ data += 2;
+
+ if (data > (d+n-4))
+ return;
+ n2s(data,type);
+ n2s(data,size);
+
+ if (type != TLSEXT_TYPE_server_name)
+ return;
+
+ if (data+size > d+n)
+ return;
+ data += size;
+
+ if (TLS1_get_client_version(s) >= TLS1_2_VERSION)
+ {
+ const size_t len1 = sizeof(kSafariExtensionsBlock);
+ const size_t len2 = sizeof(kSafariTLS12ExtensionsBlock);
+
+ if (data + len1 + len2 != d+n)
+ return;
+ if (memcmp(data, kSafariExtensionsBlock, len1) != 0)
+ return;
+ if (memcmp(data + len1, kSafariTLS12ExtensionsBlock, len2) != 0)
+ return;
+ }
+ else
+ {
+ const size_t len = sizeof(kSafariExtensionsBlock);
+
+ if (data + len != d+n)
+ return;
+ if (memcmp(data, kSafariExtensionsBlock, len) != 0)
+ return;
}
- /* If custom types were sent in ClientHello, add ServerHello responses */
- if (s->s3->tlsext_custom_types_count)
+ s->s3->is_probably_safari = 1;
+}
+#endif /* !OPENSSL_NO_EC */
+
+/* tls1_alpn_handle_client_hello is called to process the ALPN extension in a
+ * ClientHello.
+ * data: the contents of the extension, not including the type and length.
+ * data_len: the number of bytes in |data|
+ * al: a pointer to the alert value to send in the event of a non-zero
+ * return.
+ *
+ * returns: 0 on success. */
+static int tls1_alpn_handle_client_hello(SSL *s, const unsigned char *data,
+ unsigned data_len, int *al)
+ {
+ unsigned i;
+ unsigned proto_len;
+ const unsigned char *selected;
+ unsigned char selected_len;
+ int r;
+
+ if (s->ctx->alpn_select_cb == NULL)
+ return 0;
+
+ if (data_len < 2)
+ goto parse_error;
+
+ /* data should contain a uint16 length followed by a series of 8-bit,
+ * length-prefixed strings. */
+ i = ((unsigned) data[0]) << 8 |
+ ((unsigned) data[1]);
+ data_len -= 2;
+ data += 2;
+ if (data_len != i)
+ goto parse_error;
+
+ if (data_len < 2)
+ goto parse_error;
+
+ for (i = 0; i < data_len;)
{
- size_t i;
+ proto_len = data[i];
+ i++;
- for (i = 0; i < s->s3->tlsext_custom_types_count; i++)
- {
- size_t j;
- custom_srv_ext_record *record;
+ if (proto_len == 0)
+ goto parse_error;
- for (j = 0; j < s->ctx->custom_srv_ext_records_count; j++)
- {
- record = &s->ctx->custom_srv_ext_records[j];
- if (s->s3->tlsext_custom_types[i] == record->ext_type)
- {
- const unsigned char *out = NULL;
- unsigned short outlen = 0;
- int cb_retval = 0;
-
- /* NULL callback or -1 omits extension */
- if (!record->fn2)
- break;
- cb_retval = record->fn2(s, record->ext_type,
- &out, &outlen,
- record->arg);
- if (cb_retval == 0)
- return NULL; /* error */
- if (cb_retval == -1)
- break; /* skip this extension */
- if (limit < ret + 4 + outlen)
- return NULL;
- s2n(record->ext_type, ret);
- s2n(outlen, ret);
- memcpy(ret, out, outlen);
- ret += outlen;
- break;
- }
- }
- }
+ if (i + proto_len < i || i + proto_len > data_len)
+ goto parse_error;
+
+ i += proto_len;
}
- if ((extdatalen = ret-p-2)== 0)
- return p;
+ r = s->ctx->alpn_select_cb(s, &selected, &selected_len, data, data_len,
+ s->ctx->alpn_select_cb_arg);
+ if (r == SSL_TLSEXT_ERR_OK) {
+ if (s->s3->alpn_selected)
+ OPENSSL_free(s->s3->alpn_selected);
+ s->s3->alpn_selected = OPENSSL_malloc(selected_len);
+ if (!s->s3->alpn_selected)
+ {
+ *al = SSL_AD_INTERNAL_ERROR;
+ return -1;
+ }
+ memcpy(s->s3->alpn_selected, selected, selected_len);
+ s->s3->alpn_selected_len = selected_len;
+ }
+ return 0;
- s2n(extdatalen,p);
- return ret;
+parse_error:
+ *al = SSL_AD_DECODE_ERROR;
+ return -1;
}
static int ssl_scan_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, int n, int *al)
s->s3->next_proto_neg_seen = 0;
#endif
+ if (s->s3->alpn_selected)
+ {
+ OPENSSL_free(s->s3->alpn_selected);
+ s->s3->alpn_selected = NULL;
+ }
+
#ifndef OPENSSL_NO_HEARTBEATS
s->tlsext_heartbeat &= ~(SSL_TLSEXT_HB_ENABLED |
SSL_TLSEXT_HB_DONT_SEND_REQUESTS);
#endif
+
+#ifndef OPENSSL_NO_EC
+ if (s->options & SSL_OP_SAFARI_ECDHE_ECDSA_BUG)
+ ssl_check_for_safari(s, data, d, n);
+#endif /* !OPENSSL_NO_EC */
+
/* Clear any signature algorithms extension received */
if (s->cert->peer_sigalgs)
{
#endif
#ifndef OPENSSL_NO_EC
- else if (type == TLSEXT_TYPE_ec_point_formats &&
- s->version != DTLS1_VERSION)
+ else if (type == TLSEXT_TYPE_ec_point_formats)
{
unsigned char *sdata = data;
int ecpointformatlist_length = *(sdata++);
fprintf(stderr,"\n");
#endif
}
- else if (type == TLSEXT_TYPE_elliptic_curves &&
- s->version != DTLS1_VERSION)
+ else if (type == TLSEXT_TYPE_elliptic_curves)
{
unsigned char *sdata = data;
int ellipticcurvelist_length = (*(sdata++) << 8);
}
#endif /* OPENSSL_NO_EC */
#ifdef TLSEXT_TYPE_opaque_prf_input
- else if (type == TLSEXT_TYPE_opaque_prf_input &&
- s->version != DTLS1_VERSION)
+ else if (type == TLSEXT_TYPE_opaque_prf_input)
{
unsigned char *sdata = data;
return 0;
}
}
- else if (type == TLSEXT_TYPE_status_request &&
- s->version != DTLS1_VERSION && s->ctx->tlsext_status_cb)
+ else if (type == TLSEXT_TYPE_status_request)
{
if (size < 5)
#endif
#ifndef OPENSSL_NO_NEXTPROTONEG
else if (type == TLSEXT_TYPE_next_proto_neg &&
- s->s3->tmp.finish_md_len == 0)
+ s->s3->tmp.finish_md_len == 0 &&
+ s->s3->alpn_selected == NULL)
{
/* We shouldn't accept this extension on a
* renegotiation.
}
#endif
+ else if (type == TLSEXT_TYPE_application_layer_protocol_negotiation &&
+ s->ctx->alpn_select_cb &&
+ s->s3->tmp.finish_md_len == 0)
+ {
+ if (tls1_alpn_handle_client_hello(s, data, size, al) != 0)
+ return 0;
+#ifndef OPENSSL_NO_NEXTPROTONEG
+ /* ALPN takes precedence over NPN. */
+ s->s3->next_proto_neg_seen = 0;
+#endif
+ }
+
/* session ticket processed earlier */
else if (type == TLSEXT_TYPE_use_srtp)
{
al))
return 0;
}
-
- else if (type == TLSEXT_TYPE_server_authz)
- {
- unsigned char *sdata = data;
- unsigned char server_authz_dataformatlist_length;
-
- if (size == 0)
- {
- *al = TLS1_AD_DECODE_ERROR;
- return 0;
- }
-
- server_authz_dataformatlist_length = *(sdata++);
-
- if (server_authz_dataformatlist_length != size - 1)
- {
- *al = TLS1_AD_DECODE_ERROR;
- return 0;
- }
-
- /* Successful session resumption uses the same authz
- * information as the original session so we ignore this
- * in the case of a session resumption. */
- if (!s->hit)
- {
- if (s->s3->tlsext_authz_client_types != NULL)
- OPENSSL_free(s->s3->tlsext_authz_client_types);
- s->s3->tlsext_authz_client_types =
- OPENSSL_malloc(server_authz_dataformatlist_length);
- if (!s->s3->tlsext_authz_client_types)
- {
- *al = TLS1_AD_INTERNAL_ERROR;
- return 0;
- }
-
- s->s3->tlsext_authz_client_types_len =
- server_authz_dataformatlist_length;
- memcpy(s->s3->tlsext_authz_client_types,
- sdata,
- server_authz_dataformatlist_length);
-
- /* Sort the types in order to check for duplicates. */
- qsort(s->s3->tlsext_authz_client_types,
- server_authz_dataformatlist_length,
- 1 /* element size */,
- byte_compare);
-
- for (i = 0; i < server_authz_dataformatlist_length; i++)
- {
- if (i > 0 &&
- s->s3->tlsext_authz_client_types[i] ==
- s->s3->tlsext_authz_client_types[i-1])
- {
- *al = TLS1_AD_DECODE_ERROR;
- return 0;
- }
- }
- }
- }
-
/* If this ClientHello extension was unhandled and this is
* a nonresumed connection, check whether the extension is a
* custom TLS Extension (has a custom_srv_ext_record), and if
* so call the callback and record the extension number so that
* an appropriate ServerHello may be later returned.
*/
- else if (!s->hit && s->ctx->custom_srv_ext_records_count)
+ else if (!s->hit)
{
- custom_srv_ext_record *record;
-
- for (i=0; i < s->ctx->custom_srv_ext_records_count; i++)
- {
- record = &s->ctx->custom_srv_ext_records[i];
- if (type == record->ext_type)
- {
- size_t j;
-
- /* Error on duplicate TLS Extensions */
- for (j = 0; j < s->s3->tlsext_custom_types_count; j++)
- {
- if (type == s->s3->tlsext_custom_types[j])
- {
- *al = TLS1_AD_DECODE_ERROR;
- return 0;
- }
- }
-
- /* NULL callback still notes the extension */
- if (record->fn1 && !record->fn1(s, type, data, size, al, record->arg))
- return 0;
-
- /* Add the (non-duplicated) entry */
- s->s3->tlsext_custom_types_count++;
- s->s3->tlsext_custom_types = OPENSSL_realloc(
- s->s3->tlsext_custom_types,
- s->s3->tlsext_custom_types_count * 2);
- if (s->s3->tlsext_custom_types == NULL)
- {
- s->s3->tlsext_custom_types = 0;
- *al = TLS1_AD_INTERNAL_ERROR;
- return 0;
- }
- s->s3->tlsext_custom_types[
- s->s3->tlsext_custom_types_count - 1] = type;
- }
- }
+ if (custom_ext_parse(s, 1, type, data, size, al) <= 0)
+ return 0;
}
data+=size;
int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, int n)
{
int al = -1;
+ custom_ext_init(&s->cert->srv_ext);
if (ssl_scan_clienthello_tlsext(s, p, d, n, &al) <= 0)
{
ssl3_send_alert(s,SSL3_AL_FATAL,al);
s->s3->next_proto_neg_seen = 0;
#endif
+ if (s->s3->alpn_selected)
+ {
+ OPENSSL_free(s->s3->alpn_selected);
+ s->s3->alpn_selected = NULL;
+ }
+
#ifndef OPENSSL_NO_HEARTBEATS
s->tlsext_heartbeat &= ~(SSL_TLSEXT_HB_ENABLED |
SSL_TLSEXT_HB_DONT_SEND_REQUESTS);
}
#ifndef OPENSSL_NO_EC
- else if (type == TLSEXT_TYPE_ec_point_formats &&
- s->version != DTLS1_VERSION)
+ else if (type == TLSEXT_TYPE_ec_point_formats)
{
unsigned char *sdata = data;
int ecpointformatlist_length = *(sdata++);
*al = TLS1_AD_DECODE_ERROR;
return 0;
}
- s->session->tlsext_ecpointformatlist_length = 0;
- if (s->session->tlsext_ecpointformatlist != NULL) OPENSSL_free(s->session->tlsext_ecpointformatlist);
- if ((s->session->tlsext_ecpointformatlist = OPENSSL_malloc(ecpointformatlist_length)) == NULL)
+ if (!s->hit)
{
- *al = TLS1_AD_INTERNAL_ERROR;
- return 0;
+ s->session->tlsext_ecpointformatlist_length = 0;
+ if (s->session->tlsext_ecpointformatlist != NULL) OPENSSL_free(s->session->tlsext_ecpointformatlist);
+ if ((s->session->tlsext_ecpointformatlist = OPENSSL_malloc(ecpointformatlist_length)) == NULL)
+ {
+ *al = TLS1_AD_INTERNAL_ERROR;
+ return 0;
+ }
+ s->session->tlsext_ecpointformatlist_length = ecpointformatlist_length;
+ memcpy(s->session->tlsext_ecpointformatlist, sdata, ecpointformatlist_length);
}
- s->session->tlsext_ecpointformatlist_length = ecpointformatlist_length;
- memcpy(s->session->tlsext_ecpointformatlist, sdata, ecpointformatlist_length);
#if 0
fprintf(stderr,"ssl_parse_serverhello_tlsext s->session->tlsext_ecpointformatlist ");
sdata = s->session->tlsext_ecpointformatlist;
s->tlsext_ticket_expected = 1;
}
#ifdef TLSEXT_TYPE_opaque_prf_input
- else if (type == TLSEXT_TYPE_opaque_prf_input &&
- s->version != DTLS1_VERSION)
+ else if (type == TLSEXT_TYPE_opaque_prf_input)
{
unsigned char *sdata = data;
}
}
#endif
- else if (type == TLSEXT_TYPE_status_request &&
- s->version != DTLS1_VERSION)
+ else if (type == TLSEXT_TYPE_status_request)
{
/* MUST be empty and only sent if we've requested
* a status request message.
s->s3->next_proto_neg_seen = 1;
}
#endif
+
+ else if (type == TLSEXT_TYPE_application_layer_protocol_negotiation)
+ {
+ unsigned len;
+
+ /* We must have requested it. */
+ if (s->alpn_client_proto_list == NULL)
+ {
+ *al = TLS1_AD_UNSUPPORTED_EXTENSION;
+ return 0;
+ }
+ if (size < 4)
+ {
+ *al = TLS1_AD_DECODE_ERROR;
+ return 0;
+ }
+ /* The extension data consists of:
+ * uint16 list_length
+ * uint8 proto_length;
+ * uint8 proto[proto_length]; */
+ len = data[0];
+ len <<= 8;
+ len |= data[1];
+ if (len != (unsigned) size - 2)
+ {
+ *al = TLS1_AD_DECODE_ERROR;
+ return 0;
+ }
+ len = data[2];
+ if (len != (unsigned) size - 3)
+ {
+ *al = TLS1_AD_DECODE_ERROR;
+ return 0;
+ }
+ if (s->s3->alpn_selected)
+ OPENSSL_free(s->s3->alpn_selected);
+ s->s3->alpn_selected = OPENSSL_malloc(len);
+ if (!s->s3->alpn_selected)
+ {
+ *al = TLS1_AD_INTERNAL_ERROR;
+ return 0;
+ }
+ memcpy(s->s3->alpn_selected, data + 3, len);
+ s->s3->alpn_selected_len = len;
+ }
+
else if (type == TLSEXT_TYPE_renegotiate)
{
if(!ssl_parse_serverhello_renegotiate_ext(s, data, size, al))
al))
return 0;
}
-
- else if (type == TLSEXT_TYPE_server_authz)
- {
- /* We only support audit proofs. It's an error to send
- * an authz hello extension if the client
- * didn't request a proof. */
- unsigned char *sdata = data;
- unsigned char server_authz_dataformatlist_length;
-
- if (!s->ctx->tlsext_authz_server_audit_proof_cb)
- {
- *al = TLS1_AD_UNSUPPORTED_EXTENSION;
- return 0;
- }
-
- if (!size)
- {
- *al = TLS1_AD_DECODE_ERROR;
- return 0;
- }
-
- server_authz_dataformatlist_length = *(sdata++);
- if (server_authz_dataformatlist_length != size - 1)
- {
- *al = TLS1_AD_DECODE_ERROR;
- return 0;
- }
-
- /* We only support audit proofs, so a legal ServerHello
- * authz list contains exactly one entry. */
- if (server_authz_dataformatlist_length != 1 ||
- sdata[0] != TLSEXT_AUTHZDATAFORMAT_audit_proof)
- {
- *al = TLS1_AD_UNSUPPORTED_EXTENSION;
- return 0;
- }
-
- s->s3->tlsext_authz_server_promised = 1;
- }
-
/* If this extension type was not otherwise handled, but
* matches a custom_cli_ext_record, then send it to the c
* callback */
- else if (s->ctx->custom_cli_ext_records_count)
- {
- size_t i;
- custom_cli_ext_record* record;
-
- for (i = 0; i < s->ctx->custom_cli_ext_records_count; i++)
- {
- record = &s->ctx->custom_cli_ext_records[i];
- if (record->ext_type == type)
- {
- if (record->fn2 && !record->fn2(s, type, data, size, al, record->arg))
- return 0;
- break;
- }
- }
- }
+ else if (custom_ext_parse(s, 0, type, data, size, al) <= 0)
+ return 0;
data += size;
}
if (p >= limit)
return -1;
/* Skip past DTLS cookie */
- if (s->version == DTLS1_VERSION || s->version == DTLS1_BAD_VER)
+ if (SSL_IS_DTLS(s))
{
i = *(p++);
p+= i;
}
EVP_DecryptUpdate(&ctx, sdec, &slen, p, eticklen);
if (EVP_DecryptFinal(&ctx, sdec + slen, &mlen) <= 0)
+ {
+ EVP_CIPHER_CTX_cleanup(&ctx);
+ OPENSSL_free(sdec);
return 2;
+ }
slen += mlen;
EVP_CIPHER_CTX_cleanup(&ctx);
p = sdec;
TLS_SIGALGS *salgs = NULL;
CERT *c = s->cert;
unsigned int is_suiteb = tls1_suiteb(s);
+ if (c->shared_sigalgs)
+ {
+ OPENSSL_free(c->shared_sigalgs);
+ c->shared_sigalgs = NULL;
+ }
/* If client use client signature algorithms if not NULL */
if (!s->server && c->client_sigalgs && !is_suiteb)
{
const EVP_MD *md;
CERT *c = s->cert;
TLS_SIGALGS *sigptr;
- /* Extension ignored for TLS versions below 1.2 */
- if (TLS1_get_version(s) < TLS1_2_VERSION)
+ /* Extension ignored for inappropriate versions */
+ if (!SSL_USE_SIGALGS(s))
return 1;
/* Should never happen */
if (!c)
return 0;
+ if (c->peer_sigalgs)
+ OPENSSL_free(c->peer_sigalgs);
c->peer_sigalgs = OPENSSL_malloc(dsize);
if (!c->peer_sigalgs)
return 0;
unsigned int payload;
unsigned int padding = 16; /* Use minimum padding */
- /* Read type and payload length first */
- hbtype = *p++;
- n2s(p, payload);
- pl = p;
-
if (s->msg_callback)
s->msg_callback(0, s->version, TLS1_RT_HEARTBEAT,
&s->s3->rrec.data[0], s->s3->rrec.length,
s, s->msg_callback_arg);
+ /* Read type and payload length first */
+ if (1 + 2 + 16 > s->s3->rrec.length)
+ return 0; /* silently discard */
+ hbtype = *p++;
+ n2s(p, payload);
+ if (1 + 2 + payload + 16 > s->s3->rrec.length)
+ return 0; /* silently discard per RFC 6520 sec. 4 */
+ pl = p;
+
if (hbtype == TLS1_HB_REQUEST)
{
unsigned char *buffer, *bp;