X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=blobdiff_plain;f=ssl%2Ft1_lib.c;h=c9e489898a4060bb0982a23027f37d7c2fe80d7d;hp=8f54311d8ade44707d2abbc9aa8b7411c455b7ce;hb=09599b52d4e295c380512ba39958a11994d63401;hpb=319354eb6c6cac74213d754dad105f71abc72547 diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c index 8f54311d8a..c9e489898a 100644 --- a/ssl/t1_lib.c +++ b/ssl/t1_lib.c @@ -115,6 +115,10 @@ #include #include #include +#ifndef OPENSSL_NO_DH +#include +#include +#endif #include "ssl_locl.h" const char tls1_version_str[]="TLSv1" OPENSSL_VERSION_PTEXT; @@ -123,7 +127,7 @@ const char tls1_version_str[]="TLSv1" OPENSSL_VERSION_PTEXT; static int tls_decrypt_ticket(SSL *s, const unsigned char *tick, int ticklen, const unsigned char *sess_id, int sesslen, SSL_SESSION **psess); -static int ssl_check_clienthello_tlsext(SSL *s); +static int ssl_check_clienthello_tlsext_early(SSL *s); int ssl_check_serverhello_tlsext(SSL *s); #endif @@ -140,6 +144,49 @@ SSL3_ENC_METHOD TLSv1_enc_data={ 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) @@ -201,7 +248,10 @@ static int nid_list[] = 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) */ }; @@ -217,11 +267,14 @@ static const unsigned char eccurves_default[] = 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) */ @@ -311,6 +364,12 @@ int tls1_ec_nid2curve_id(int nid) 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; } @@ -484,7 +543,7 @@ int tls1_set_curves(unsigned char **pext, size_t *pextlen, return 1; } -#define MAX_CURVELIST 25 +#define MAX_CURVELIST 28 typedef struct { @@ -525,6 +584,8 @@ int tls1_set_curves_list(unsigned char **pext, size_t *pextlen, ncb.nidcnt = 0; if (!CONF_parse_list(str, ':', 1, nid_cb, &ncb)) return 0; + if (pext == NULL) + return 1; return tls1_set_curves(pext, pextlen, ncb.nid_arr, ncb.nidcnt); } /* For an EC key set TLS id and required compression based on parameters */ @@ -533,14 +594,12 @@ static int tls1_set_ec_id(unsigned char *curve_id, unsigned char *comp_id, { 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) @@ -568,6 +627,8 @@ static int tls1_set_ec_id(unsigned char *curve_id, unsigned char *comp_id, } 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) @@ -622,6 +683,27 @@ static int tls1_check_ec_key(SSL *s, return 1; } +static void tls1_get_formatlist(SSL *s, const unsigned char **pformats, + size_t *pformatslen) + { + /* If we have a custom point format list use it otherwise + * use default */ + if (s->tlsext_ecpointformatlist) + { + *pformats = s->tlsext_ecpointformatlist; + *pformatslen = s->tlsext_ecpointformatlist_length; + } + else + { + *pformats = ecformats_default; + /* For Suite B we don't support char2 fields */ + if (tls1_suiteb(s)) + *pformatslen = sizeof(ecformats_default) - 1; + else + *pformatslen = sizeof(ecformats_default); + } + } + /* Check cert parameters compatible with extensions: currently just checks * EC certificates have compatible curves and compression. */ @@ -688,7 +770,7 @@ int tls1_check_ec_tmp_key(SSL *s, unsigned long cid) EC_KEY *ec = s->cert->ecdh_tmp; #ifdef OPENSSL_SSL_DEBUG_BROKEN_PROTOCOL /* Allow any curve: not just those peer supports */ - if (s->cert->cert_flags & SSL_CERT_FLAG_BROKEN_PROTCOL) + if (s->cert->cert_flags & SSL_CERT_FLAG_BROKEN_PROTOCOL) return 1; #endif /* If Suite B, AES128 MUST use P-256 and AES256 MUST use P-384, @@ -748,6 +830,13 @@ int tls1_check_ec_tmp_key(SSL *s, unsigned long cid) #endif } +#else + +static int tls1_check_cert_param(SSL *s, X509 *x, int set_ee_md) + { + return 1; + } + #endif /* OPENSSL_NO_EC */ #ifndef OPENSSL_NO_TLSEXT @@ -791,21 +880,19 @@ static unsigned char tls12_sigalgs[] = { #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[] = { tlsext_sigalg_ecdsa(TLSEXT_hash_sha256) tlsext_sigalg_ecdsa(TLSEXT_hash_sha384) }; - +#endif size_t tls12_get_psigalgs(SSL *s, const unsigned char **psigs) { /* If Suite B mode use Suite B sigalgs only, ignore any other * preferences. */ +#ifndef OPENSSL_NO_EC switch (tls1_suiteb(s)) { case SSL_CERT_FLAG_SUITEB_128_LOS: @@ -820,7 +907,7 @@ size_t tls12_get_psigalgs(SSL *s, const unsigned char **psigs) *psigs = suiteb_sigalgs + 2; return 2; } - +#endif /* If server use client authentication sigalgs if not NULL */ if (s->server && s->cert->client_sigalgs) { @@ -835,13 +922,7 @@ size_t tls12_get_psigalgs(SSL *s, const unsigned char **psigs) 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 @@ -862,6 +943,7 @@ int tls12_check_peer_sigalg(const EVP_MD **pmd, SSL *s, SSLerr(SSL_F_TLS12_CHECK_PEER_SIGALG,SSL_R_WRONG_SIGNATURE_TYPE); return 0; } +#ifndef OPENSSL_NO_EC if (pkey->type == EVP_PKEY_EC) { unsigned char curve_id[2], comp_id; @@ -902,6 +984,7 @@ int tls12_check_peer_sigalg(const EVP_MD **pmd, SSL *s, } else if (tls1_suiteb(s)) return 0; +#endif /* Check signature matches a type we sent */ sent_sigslen = tls12_get_psigalgs(s, &sent_sigs); @@ -943,8 +1026,8 @@ void ssl_set_client_disabled(SSL *s) 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_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; @@ -1010,27 +1093,14 @@ void ssl_set_client_disabled(SSL *s) 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 *p, unsigned char *limit, int *al) { int extdatalen=0; unsigned char *ret = p; #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; @@ -1042,7 +1112,7 @@ unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *p, unsigned cha alg_k = c->algorithm_mkey; alg_a = c->algorithm_auth; - if ((alg_k & (SSL_kEECDH|SSL_kECDHr|SSL_kECDHe) + if ((alg_k & (SSL_kECDHE|SSL_kECDHr|SSL_kECDHe) || (alg_a & SSL_aECDSA))) { using_ecc = 1; @@ -1153,16 +1223,8 @@ unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *p, unsigned cha long lenmax; const unsigned char *plist; size_t plistlen; - /* If we have a custom point format list use it otherwise - * use default */ - plist = s->tlsext_ecpointformatlist; - if (plist) - plistlen = s->tlsext_ecpointformatlist_length; - else - { - plist = ecformats_default; - plistlen = sizeof(ecformats_default); - } + + tls1_get_formatlist(s, &plist, &plistlen); if ((lenmax = limit - ret - 5) < 0) return NULL; if (plistlen > (size_t)lenmax) return NULL; @@ -1240,7 +1302,7 @@ unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *p, unsigned cha } skip_ext: - if (TLS1_get_client_version(s) >= TLS1_2_VERSION) + if (SSL_USE_SIGALGS(s)) { size_t salglen; const unsigned char *salg; @@ -1255,8 +1317,7 @@ unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *p, unsigned cha } #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; @@ -1273,8 +1334,7 @@ unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *p, unsigned cha } #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; @@ -1348,6 +1408,18 @@ unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *p, unsigned cha } #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; @@ -1367,25 +1439,72 @@ unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *p, unsigned cha 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) + /* Add custom TLS Extensions to ClientHello */ + if (s->ctx->custom_cli_ext_records_count) { - size_t lenmax; - const unsigned short ext_len = 2; - const unsigned char list_len = 1; + size_t i; + custom_cli_ext_record* record; - if ((lenmax = limit - ret - 6) < 0) return NULL; + for (i = 0; i < s->ctx->custom_cli_ext_records_count; i++) + { + const unsigned char* out = NULL; + unsigned short outlen = 0; - s2n(TLSEXT_TYPE_server_authz, ret); - /* Extension length: 2 bytes */ - s2n(ext_len, ret); - *(ret++) = list_len; - *(ret++) = TLSEXT_AUTHZDATAFORMAT_audit_proof; + 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, al, + 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; + } } +#ifdef TLSEXT_TYPE_encrypt_then_mac + s2n(TLSEXT_TYPE_encrypt_then_mac,ret); + s2n(0,ret); +#endif +#ifdef TLSEXT_TYPE_padding + /* Add padding to workaround bugs in F5 terminators. + * See https://tools.ietf.org/html/draft-agl-tls-padding-02 + * + * NB: because this code works out the length of all existing + * extensions it MUST always appear last. + */ + { + 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) + { + hlen = 0x200 - hlen; + if (hlen >= 4) + hlen -= 4; + else + hlen = 0; + + s2n(TLSEXT_TYPE_padding, ret); + s2n(hlen, ret); + memset(ret, 0, hlen); + ret += hlen; + } + } +#endif if ((extdatalen = ret-p-2) == 0) return p; @@ -1394,14 +1513,21 @@ unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *p, unsigned cha 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 *p, unsigned char *limit, int *al) { int extdatalen=0; unsigned char *ret = p; + size_t i; + custom_srv_ext_record *record; #ifndef OPENSSL_NO_NEXTPROTONEG int next_proto_neg_seen; #endif - +#ifndef OPENSSL_NO_EC + unsigned long alg_k = s->s3->tmp.new_cipher->algorithm_mkey; + unsigned long alg_a = s->s3->tmp.new_cipher->algorithm_auth; + int using_ecc = (alg_k & (SSL_kECDHE|SSL_kECDHr|SSL_kECDHe)) || (alg_a & SSL_aECDSA); + using_ecc = using_ecc && (s->session->tlsext_ecpointformatlist != NULL); +#endif /* don't add extensions for SSLv3, unless doing secure renegotiation */ if (s->version == SSL3_VERSION && !s->s3->send_connection_binding) return p; @@ -1442,25 +1568,28 @@ unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *p, unsigned cha } #ifndef OPENSSL_NO_EC - if (s->tlsext_ecpointformatlist != NULL && - s->version != DTLS1_VERSION) + if (using_ecc) { + const unsigned char *plist; + size_t plistlen; /* Add TLS extension ECPointFormats to the ServerHello message */ long lenmax; + tls1_get_formatlist(s, &plist, &plistlen); + if ((lenmax = limit - ret - 5) < 0) return NULL; - if (s->tlsext_ecpointformatlist_length > (unsigned long)lenmax) return NULL; - if (s->tlsext_ecpointformatlist_length > 255) + if (plistlen > (size_t)lenmax) return NULL; + if (plistlen > 255) { SSLerr(SSL_F_SSL_ADD_SERVERHELLO_TLSEXT, ERR_R_INTERNAL_ERROR); return NULL; } s2n(TLSEXT_TYPE_ec_point_formats,ret); - s2n(s->tlsext_ecpointformatlist_length + 1,ret); - *(ret++) = (unsigned char) s->tlsext_ecpointformatlist_length; - memcpy(ret, s->tlsext_ecpointformatlist, s->tlsext_ecpointformatlist_length); - ret+=s->tlsext_ecpointformatlist_length; + s2n(plistlen + 1,ret); + *(ret++) = (unsigned char) plistlen; + memcpy(ret, plist, plistlen); + ret+=plistlen; } /* Currently the server should not respond with a SupportedCurves extension */ @@ -1482,8 +1611,7 @@ unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *p, unsigned cha } #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; @@ -1574,78 +1702,61 @@ unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *p, unsigned cha } #endif - /* If the client supports authz then see whether we have any to offer - * to it. */ - if (s->s3->tlsext_authz_client_types_len) + for (i = 0; i < s->ctx->custom_srv_ext_records_count; i++) { - 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 *out = NULL; + unsigned short outlen = 0; + int cb_retval = 0; - 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; - } + record = &s->ctx->custom_srv_ext_records[i]; - authz = orig_authz; - for (i = 0; i < authz_length; i++) + /* NULL callback or -1 omits extension */ + if (!record->fn2) + continue; + cb_retval = record->fn2(s, record->ext_type, + &out, &outlen, al, + 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; + } +#ifdef TLSEXT_TYPE_encrypt_then_mac + if (s->s3->flags & TLS1_FLAGS_ENCRYPT_THEN_MAC) + { + /* Don't use encrypt_then_mac if AEAD: might want + * to disable for other ciphersuites too. + */ + if (s->s3->tmp.new_cipher->algorithm_mac == SSL_AEAD) + s->s3->flags &= ~TLS1_FLAGS_ENCRYPT_THEN_MAC; + else { - 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; + s2n(TLSEXT_TYPE_encrypt_then_mac,ret); + s2n(0,ret); } } +#endif + + if (s->s3->alpn_selected) + { + const unsigned char *selected = s->s3->alpn_selected; + unsigned len = s->s3->alpn_selected_len; + + 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; + } if ((extdatalen = ret-p-2)== 0) return p; @@ -1654,6 +1765,159 @@ unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *p, unsigned cha return ret; } +/* 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;) + { + proto_len = data[i]; + i++; + + if (proto_len == 0) + goto parse_error; + + if (i + proto_len < i || i + proto_len > data_len) + goto parse_error; + + i += proto_len; + } + + 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; + +parse_error: + *al = SSL_AD_DECODE_ERROR; + return -1; + } + +#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; + } + + s->s3->is_probably_safari = 1; +} +#endif /* !OPENSSL_NO_EC */ + static int ssl_scan_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, int n, int *al) { unsigned short type; @@ -1669,10 +1933,30 @@ static int ssl_scan_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char s->s3->next_proto_neg_seen = 0; #endif + if (s->s3->alpn_selected) + { + OPENSSL_free(s->s3->alpn_selected); + s->s3->alpn_selected = NULL; + } + + /* Clear observed custom extensions */ + s->s3->serverinfo_client_tlsext_custom_types_count = 0; + if (s->s3->serverinfo_client_tlsext_custom_types != NULL) + { + OPENSSL_free(s->s3->serverinfo_client_tlsext_custom_types); + s->s3->serverinfo_client_tlsext_custom_types = 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) { @@ -1692,6 +1976,10 @@ static int ssl_scan_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char s->cert->pkeys[i].valid_flags = 0; } +#ifdef TLSEXT_TYPE_encrypt_then_mac + s->s3->flags &= ~TLS1_FLAGS_ENCRYPT_THEN_MAC; +#endif + if (data >= (d+n-2)) goto ri_check; n2s(data,len); @@ -1845,13 +2133,13 @@ static int ssl_scan_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char #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++); - if (ecpointformatlist_length != size - 1) + if (ecpointformatlist_length != size - 1 || + ecpointformatlist_length < 1) { *al = TLS1_AD_DECODE_ERROR; return 0; @@ -1880,14 +2168,14 @@ static int ssl_scan_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char 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); ellipticcurvelist_length += (*(sdata++)); - if (ellipticcurvelist_length != size - 2) + if (ellipticcurvelist_length != size - 2 || + ellipticcurvelist_length < 1) { *al = TLS1_AD_DECODE_ERROR; return 0; @@ -1918,8 +2206,7 @@ static int ssl_scan_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char } #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; @@ -1994,8 +2281,7 @@ static int ssl_scan_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char 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) @@ -2125,7 +2411,8 @@ static int ssl_scan_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char #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. @@ -2146,6 +2433,18 @@ static int ssl_scan_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char } #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) { @@ -2153,65 +2452,30 @@ static int ssl_scan_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char al)) return 0; } - - else if (type == TLSEXT_TYPE_server_authz) + /* 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) { - unsigned char *sdata = data; - unsigned char server_authz_dataformatlist_length; + custom_srv_ext_record *record; - 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) + for (i=0; i < s->ctx->custom_srv_ext_records_count; i++) { - 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) + record = &s->ctx->custom_srv_ext_records[i]; + if (type == record->ext_type) { - *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; + if (record->fn1 && !record->fn1(s, type, data, size, al, record->arg)) return 0; - } - } + } } } +#ifdef TLSEXT_TYPE_encrypt_then_mac + else if (type == TLSEXT_TYPE_encrypt_then_mac) + s->s3->flags |= TLS1_FLAGS_ENCRYPT_THEN_MAC; +#endif data+=size; } @@ -2246,7 +2510,7 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in return 0; } - if (ssl_check_clienthello_tlsext(s) <= 0) + if (ssl_check_clienthello_tlsext_early(s) <= 0) { SSLerr(SSL_F_SSL_PARSE_CLIENTHELLO_TLSEXT,SSL_R_CLIENTHELLO_TLSEXT); return 0; @@ -2287,11 +2551,21 @@ static int ssl_scan_serverhello_tlsext(SSL *s, unsigned char **p, unsigned char 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 +#ifdef TLSEXT_TYPE_encrypt_then_mac + s->s3->flags &= ~TLS1_FLAGS_ENCRYPT_THEN_MAC; +#endif + if (data >= (d+n-2)) goto ri_check; @@ -2325,8 +2599,7 @@ static int ssl_scan_serverhello_tlsext(SSL *s, unsigned char **p, unsigned char } #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++); @@ -2372,8 +2645,7 @@ static int ssl_scan_serverhello_tlsext(SSL *s, unsigned char **p, unsigned char 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; @@ -2403,8 +2675,7 @@ static int ssl_scan_serverhello_tlsext(SSL *s, unsigned char **p, unsigned char } } #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. @@ -2425,7 +2696,7 @@ static int ssl_scan_serverhello_tlsext(SSL *s, unsigned char **p, unsigned char unsigned char selected_len; /* We must have requested it. */ - if ((s->ctx->next_proto_select_cb == NULL)) + if (s->ctx->next_proto_select_cb == NULL) { *al = TLS1_AD_UNSUPPORTED_EXTENSION; return 0; @@ -2452,6 +2723,52 @@ static int ssl_scan_serverhello_tlsext(SSL *s, unsigned char **p, unsigned char 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)) @@ -2481,45 +2798,33 @@ static int ssl_scan_serverhello_tlsext(SSL *s, unsigned char **p, unsigned char al)) return 0; } - - else if (type == TLSEXT_TYPE_server_authz) + /* 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) { - /* 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; + size_t i; + custom_cli_ext_record* record; - if (!s->ctx->tlsext_authz_server_audit_proof_cb) + for (i = 0; i < s->ctx->custom_cli_ext_records_count; i++) { - *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; + 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; + } + } + } +#ifdef TLSEXT_TYPE_encrypt_then_mac + else if (type == TLSEXT_TYPE_encrypt_then_mac) + { + /* Ignore if inappropriate ciphersuite */ + if (s->s3->tmp.new_cipher->algorithm_mac != SSL_AEAD) + s->s3->flags |= TLS1_FLAGS_ENCRYPT_THEN_MAC; } +#endif data += size; } @@ -2618,36 +2923,10 @@ int ssl_prepare_clienthello_tlsext(SSL *s) int ssl_prepare_serverhello_tlsext(SSL *s) { -#ifndef OPENSSL_NO_EC - /* If we are server and using an ECC cipher suite, send the point formats we support - * if the client sent us an ECPointsFormat extension. Note that the server is not - * supposed to send an EllipticCurves extension. - */ - - unsigned long alg_k = s->s3->tmp.new_cipher->algorithm_mkey; - unsigned long alg_a = s->s3->tmp.new_cipher->algorithm_auth; - int using_ecc = (alg_k & (SSL_kEECDH|SSL_kECDHr|SSL_kECDHe)) || (alg_a & SSL_aECDSA); - using_ecc = using_ecc && (s->session->tlsext_ecpointformatlist != NULL); - - if (using_ecc) - { - if (s->tlsext_ecpointformatlist != NULL) OPENSSL_free(s->tlsext_ecpointformatlist); - if ((s->tlsext_ecpointformatlist = OPENSSL_malloc(3)) == NULL) - { - SSLerr(SSL_F_SSL_PREPARE_SERVERHELLO_TLSEXT,ERR_R_MALLOC_FAILURE); - return -1; - } - s->tlsext_ecpointformatlist_length = 3; - s->tlsext_ecpointformatlist[0] = TLSEXT_ECPOINTFORMAT_uncompressed; - s->tlsext_ecpointformatlist[1] = TLSEXT_ECPOINTFORMAT_ansiX962_compressed_prime; - s->tlsext_ecpointformatlist[2] = TLSEXT_ECPOINTFORMAT_ansiX962_compressed_char2; - } -#endif /* OPENSSL_NO_EC */ - return 1; } -static int ssl_check_clienthello_tlsext(SSL *s) +static int ssl_check_clienthello_tlsext_early(SSL *s) { int ret=SSL_TLSEXT_ERR_NOACK; int al = SSL_AD_UNRECOGNIZED_NAME; @@ -2666,42 +2945,12 @@ static int ssl_check_clienthello_tlsext(SSL *s) else if (s->initial_ctx != NULL && s->initial_ctx->tlsext_servername_callback != 0) ret = s->initial_ctx->tlsext_servername_callback(s, &al, s->initial_ctx->tlsext_servername_arg); - /* If status request then ask callback what to do. - * Note: this must be called after servername callbacks in case - * the certificate has changed. - */ - if ((s->tlsext_status_type != -1) && s->ctx && s->ctx->tlsext_status_cb) - { - int r; - r = s->ctx->tlsext_status_cb(s, s->ctx->tlsext_status_arg); - switch (r) - { - /* We don't want to send a status request response */ - case SSL_TLSEXT_ERR_NOACK: - s->tlsext_status_expected = 0; - break; - /* status request response should be sent */ - case SSL_TLSEXT_ERR_OK: - if (s->tlsext_ocsp_resp) - s->tlsext_status_expected = 1; - else - s->tlsext_status_expected = 0; - break; - /* something bad happened */ - case SSL_TLSEXT_ERR_ALERT_FATAL: - ret = SSL_TLSEXT_ERR_ALERT_FATAL; - al = SSL_AD_INTERNAL_ERROR; - goto err; - } - } - else - s->tlsext_status_expected = 0; - #ifdef TLSEXT_TYPE_opaque_prf_input { /* This sort of belongs into ssl_prepare_serverhello_tlsext(), * but we might be sending an alert in response to the client hello, - * so this has to happen here in ssl_check_clienthello_tlsext(). */ + * so this has to happen here in + * ssl_check_clienthello_tlsext_early(). */ int r = 1; @@ -2753,8 +3002,8 @@ static int ssl_check_clienthello_tlsext(SSL *s) } } -#endif err: +#endif switch (ret) { case SSL_TLSEXT_ERR_ALERT_FATAL: @@ -2772,6 +3021,71 @@ static int ssl_check_clienthello_tlsext(SSL *s) } } +int ssl_check_clienthello_tlsext_late(SSL *s) + { + int ret = SSL_TLSEXT_ERR_OK; + int al; + + /* If status request then ask callback what to do. + * Note: this must be called after servername callbacks in case + * the certificate has changed, and must be called after the cipher + * has been chosen because this may influence which certificate is sent + */ + if ((s->tlsext_status_type != -1) && s->ctx && s->ctx->tlsext_status_cb) + { + int r; + CERT_PKEY *certpkey; + certpkey = ssl_get_server_send_pkey(s); + /* If no certificate can't return certificate status */ + if (certpkey == NULL) + { + s->tlsext_status_expected = 0; + return 1; + } + /* Set current certificate to one we will use so + * SSL_get_certificate et al can pick it up. + */ + s->cert->key = certpkey; + r = s->ctx->tlsext_status_cb(s, s->ctx->tlsext_status_arg); + switch (r) + { + /* We don't want to send a status request response */ + case SSL_TLSEXT_ERR_NOACK: + s->tlsext_status_expected = 0; + break; + /* status request response should be sent */ + case SSL_TLSEXT_ERR_OK: + if (s->tlsext_ocsp_resp) + s->tlsext_status_expected = 1; + else + s->tlsext_status_expected = 0; + break; + /* something bad happened */ + case SSL_TLSEXT_ERR_ALERT_FATAL: + ret = SSL_TLSEXT_ERR_ALERT_FATAL; + al = SSL_AD_INTERNAL_ERROR; + goto err; + } + } + else + s->tlsext_status_expected = 0; + + err: + switch (ret) + { + case SSL_TLSEXT_ERR_ALERT_FATAL: + ssl3_send_alert(s, SSL3_AL_FATAL, al); + return -1; + + case SSL_TLSEXT_ERR_ALERT_WARNING: + ssl3_send_alert(s, SSL3_AL_WARNING, al); + return 1; + + default: + return 1; + } + } + int ssl_check_serverhello_tlsext(SSL *s) { int ret=SSL_TLSEXT_ERR_NOACK; @@ -2786,7 +3100,7 @@ int ssl_check_serverhello_tlsext(SSL *s) unsigned long alg_a = s->s3->tmp.new_cipher->algorithm_auth; if ((s->tlsext_ecpointformatlist != NULL) && (s->tlsext_ecpointformatlist_length > 0) && (s->session->tlsext_ecpointformatlist != NULL) && (s->session->tlsext_ecpointformatlist_length > 0) && - ((alg_k & (SSL_kEECDH|SSL_kECDHr|SSL_kECDHe)) || (alg_a & SSL_aECDSA))) + ((alg_k & (SSL_kECDHE|SSL_kECDHr|SSL_kECDHe)) || (alg_a & SSL_aECDSA))) { /* we are using an ECC cipher */ size_t i; @@ -2956,7 +3270,7 @@ int tls1_process_ticket(SSL *s, unsigned char *session_id, int len, 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; @@ -3092,7 +3406,7 @@ static int tls_decrypt_ticket(SSL *s, const unsigned char *etick, int eticklen, HMAC_Update(&hctx, etick, eticklen); HMAC_Final(&hctx, tick_hmac, NULL); HMAC_CTX_cleanup(&hctx); - if (memcmp(tick_hmac, etick + eticklen, mlen)) + if (CRYPTO_memcmp(tick_hmac, etick + eticklen, mlen)) return 2; /* Attempt to decrypt session data */ /* Move p after IV to start of encrypted ticket, update length */ @@ -3334,6 +3648,11 @@ static int tls1_set_shared_sigalgs(SSL *s) 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) { @@ -3383,13 +3702,15 @@ int tls1_process_sigalgs(SSL *s, const unsigned char *data, int dsize) 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; @@ -3399,7 +3720,7 @@ int tls1_process_sigalgs(SSL *s, const unsigned char *data, int dsize) tls1_set_shared_sigalgs(s); #ifdef OPENSSL_SSL_DEBUG_BROKEN_PROTOCOL - if (s->cert->cert_flags & SSL_CERT_FLAG_BROKEN_PROTCOL) + if (s->cert->cert_flags & SSL_CERT_FLAG_BROKEN_PROTOCOL) { /* Use first set signature preference to force message * digest, ignoring any peer preferences. @@ -3719,6 +4040,8 @@ int tls1_set_sigalgs_list(CERT *c, const char *str, int client) sig.sigalgcnt = 0; if (!CONF_parse_list(str, ':', 1, sig_cb, &sig)) return 0; + if (c == NULL) + return 1; return tls1_set_sigalgs(c, sig.sigalgs, sig.sigalgcnt, client); } @@ -3839,7 +4162,7 @@ int tls1_check_chain(SSL *s, X509 *x, EVP_PKEY *pk, STACK_OF(X509) *chain, goto end; #ifdef OPENSSL_SSL_DEBUG_BROKEN_PROTOCOL /* Allow any certificate to pass test */ - if (s->cert->cert_flags & SSL_CERT_FLAG_BROKEN_PROTCOL) + if (s->cert->cert_flags & SSL_CERT_FLAG_BROKEN_PROTOCOL) { rv = CERT_PKEY_STRICT_FLAGS|CERT_PKEY_EXPLICIT_SIGN|CERT_PKEY_VALID|CERT_PKEY_SIGN; cpk->valid_flags = rv; @@ -4120,3 +4443,47 @@ int SSL_check_chain(SSL *s, X509 *x, EVP_PKEY *pk, STACK_OF(X509) *chain) } #endif + +#ifndef OPENSSL_NO_DH +DH *ssl_get_auto_dh(SSL *s) + { + int dh_secbits = 80; + if (s->cert->dh_tmp_auto == 2) + return DH_get_1024_160(); + if (s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL) + { + if (s->s3->tmp.new_cipher->strength_bits == 256) + dh_secbits = 128; + else + dh_secbits = 80; + } + else + { + CERT_PKEY *cpk = ssl_get_server_send_pkey(s); + dh_secbits = EVP_PKEY_security_bits(cpk->privatekey); + } + + if (dh_secbits >= 128) + { + DH *dhp = DH_new(); + if (!dhp) + return NULL; + dhp->g = BN_new(); + if (dhp->g) + BN_set_word(dhp->g, 2); + if (dh_secbits >= 192) + dhp->p = get_rfc3526_prime_8192(NULL); + else + dhp->p = get_rfc3526_prime_3072(NULL); + if (!dhp->p || !dhp->g) + { + DH_free(dhp); + return NULL; + } + return dhp; + } + if (dh_secbits >= 112) + return DH_get_2048_224(); + return DH_get_1024_160(); + } +#endif