X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=blobdiff_plain;f=ssl%2Ft1_lib.c;h=debad3bb492fc8ac69366a4b714433ee5eebf72b;hp=fd13a317c16d9f7676327622e7aef09bbd23807d;hb=740580c2b2b86c2ffdc4a2d36850248c6091d6a0;hpb=e83aefb3a0c645c77849f889bc166935b2cc935c diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c index fd13a317c1..debad3bb49 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; @@ -127,7 +131,26 @@ static int ssl_check_clienthello_tlsext_early(SSL *s); int ssl_check_serverhello_tlsext(SSL *s); #endif -SSL3_ENC_METHOD TLSv1_enc_data={ +SSL3_ENC_METHOD const TLSv1_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, + 0, + SSL3_HM_HEADER_LENGTH, + ssl3_set_handshake_header, + ssl3_handshake_write + }; + +SSL3_ENC_METHOD const TLSv1_1_enc_data={ tls1_enc, tls1_mac, tls1_setup_key_block, @@ -140,6 +163,30 @@ SSL3_ENC_METHOD TLSv1_enc_data={ 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 const 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) @@ -175,33 +222,46 @@ void tls1_clear(SSL *s) #ifndef OPENSSL_NO_EC -static int nid_list[] = +typedef struct { - NID_sect163k1, /* sect163k1 (1) */ - NID_sect163r1, /* sect163r1 (2) */ - NID_sect163r2, /* sect163r2 (3) */ - NID_sect193r1, /* sect193r1 (4) */ - NID_sect193r2, /* sect193r2 (5) */ - NID_sect233k1, /* sect233k1 (6) */ - NID_sect233r1, /* sect233r1 (7) */ - NID_sect239k1, /* sect239k1 (8) */ - NID_sect283k1, /* sect283k1 (9) */ - NID_sect283r1, /* sect283r1 (10) */ - NID_sect409k1, /* sect409k1 (11) */ - NID_sect409r1, /* sect409r1 (12) */ - NID_sect571k1, /* sect571k1 (13) */ - NID_sect571r1, /* sect571r1 (14) */ - NID_secp160k1, /* secp160k1 (15) */ - NID_secp160r1, /* secp160r1 (16) */ - NID_secp160r2, /* secp160r2 (17) */ - NID_secp192k1, /* secp192k1 (18) */ - NID_X9_62_prime192v1, /* secp192r1 (19) */ - NID_secp224k1, /* secp224k1 (20) */ - NID_secp224r1, /* secp224r1 (21) */ - NID_secp256k1, /* secp256k1 (22) */ - NID_X9_62_prime256v1, /* secp256r1 (23) */ - NID_secp384r1, /* secp384r1 (24) */ - NID_secp521r1 /* secp521r1 (25) */ + int nid; /* Curve NID */ + int secbits; /* Bits of security (from SP800-57) */ + unsigned int flags; /* Flags: currently just field type */ + } tls_curve_info; + +#define TLS_CURVE_CHAR2 0x1 +#define TLS_CURVE_PRIME 0x0 + +static const tls_curve_info nid_list[] = + { + {NID_sect163k1, 80, TLS_CURVE_CHAR2},/* sect163k1 (1) */ + {NID_sect163r1, 80, TLS_CURVE_CHAR2},/* sect163r1 (2) */ + {NID_sect163r2, 80, TLS_CURVE_CHAR2},/* sect163r2 (3) */ + {NID_sect193r1, 80, TLS_CURVE_CHAR2},/* sect193r1 (4) */ + {NID_sect193r2, 80, TLS_CURVE_CHAR2},/* sect193r2 (5) */ + {NID_sect233k1, 112, TLS_CURVE_CHAR2},/* sect233k1 (6) */ + {NID_sect233r1, 112, TLS_CURVE_CHAR2},/* sect233r1 (7) */ + {NID_sect239k1, 112, TLS_CURVE_CHAR2},/* sect239k1 (8) */ + {NID_sect283k1, 128, TLS_CURVE_CHAR2},/* sect283k1 (9) */ + {NID_sect283r1, 128, TLS_CURVE_CHAR2},/* sect283r1 (10) */ + {NID_sect409k1, 192, TLS_CURVE_CHAR2},/* sect409k1 (11) */ + {NID_sect409r1, 192, TLS_CURVE_CHAR2},/* sect409r1 (12) */ + {NID_sect571k1, 256, TLS_CURVE_CHAR2},/* sect571k1 (13) */ + {NID_sect571r1, 256, TLS_CURVE_CHAR2},/* sect571r1 (14) */ + {NID_secp160k1, 80, TLS_CURVE_PRIME},/* secp160k1 (15) */ + {NID_secp160r1, 80, TLS_CURVE_PRIME},/* secp160r1 (16) */ + {NID_secp160r2, 80, TLS_CURVE_PRIME},/* secp160r2 (17) */ + {NID_secp192k1, 80, TLS_CURVE_PRIME},/* secp192k1 (18) */ + {NID_X9_62_prime192v1, 80, TLS_CURVE_PRIME},/* secp192r1 (19) */ + {NID_secp224k1, 112, TLS_CURVE_PRIME},/* secp224k1 (20) */ + {NID_secp224r1, 112, TLS_CURVE_PRIME},/* secp224r1 (21) */ + {NID_secp256k1, 128, TLS_CURVE_PRIME},/* secp256k1 (22) */ + {NID_X9_62_prime256v1, 128, TLS_CURVE_PRIME},/* secp256r1 (23) */ + {NID_secp384r1, 192, TLS_CURVE_PRIME},/* secp384r1 (24) */ + {NID_secp521r1, 256, TLS_CURVE_PRIME},/* secp521r1 (25) */ + {NID_brainpoolP256r1, 128, TLS_CURVE_PRIME}, /* brainpoolP256r1 (26) */ + {NID_brainpoolP384r1, 192, TLS_CURVE_PRIME}, /* brainpoolP384r1 (27) */ + {NID_brainpoolP512r1, 256, TLS_CURVE_PRIME},/* brainpool512r1 (28) */ }; @@ -217,11 +277,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) */ @@ -249,16 +312,16 @@ static const unsigned char suiteb_curves[] = int tls1_ec_curve_id2nid(int curve_id) { - /* ECC curves from draft-ietf-tls-ecc-12.txt (Oct. 17, 2005) */ + /* ECC curves from RFC 4492 and RFC 7027 */ if ((curve_id < 1) || ((unsigned int)curve_id > sizeof(nid_list)/sizeof(nid_list[0]))) return 0; - return nid_list[curve_id-1]; + return nid_list[curve_id-1].nid; } int tls1_ec_nid2curve_id(int nid) { - /* ECC curves from draft-ietf-tls-ecc-12.txt (Oct. 17, 2005) */ + /* ECC curves from RFC 4492 and RFC 7027 */ switch (nid) { case NID_sect163k1: /* sect163k1 (1) */ @@ -311,55 +374,104 @@ 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; } } -/* Get curves list, if "sess" is set return client curves otherwise - * preferred list +/* + * Get curves list, if "sess" is set return client curves otherwise + * preferred list. + * Sets |num_curves| to the number of curves in the list, i.e., + * the length of |pcurves| is 2 * num_curves. + * Returns 1 on success and 0 if the client curves list has invalid format. + * The latter indicates an internal error: we should not be accepting such + * lists in the first place. + * TODO(emilia): we should really be storing the curves list in explicitly + * parsed form instead. (However, this would affect binary compatibility + * so cannot happen in the 1.0.x series.) */ -static void tls1_get_curvelist(SSL *s, int sess, +static int tls1_get_curvelist(SSL *s, int sess, const unsigned char **pcurves, - size_t *pcurveslen) + size_t *num_curves) { + size_t pcurveslen = 0; if (sess) { *pcurves = s->session->tlsext_ellipticcurvelist; - *pcurveslen = s->session->tlsext_ellipticcurvelist_length; - return; + pcurveslen = s->session->tlsext_ellipticcurvelist_length; } - /* For Suite B mode only include P-256, P-384 */ - switch (tls1_suiteb(s)) + else { - case SSL_CERT_FLAG_SUITEB_128_LOS: - *pcurves = suiteb_curves; - *pcurveslen = sizeof(suiteb_curves); - break; + /* For Suite B mode only include P-256, P-384 */ + switch (tls1_suiteb(s)) + { + case SSL_CERT_FLAG_SUITEB_128_LOS: + *pcurves = suiteb_curves; + pcurveslen = sizeof(suiteb_curves); + break; - case SSL_CERT_FLAG_SUITEB_128_LOS_ONLY: - *pcurves = suiteb_curves; - *pcurveslen = 2; - break; + case SSL_CERT_FLAG_SUITEB_128_LOS_ONLY: + *pcurves = suiteb_curves; + pcurveslen = 2; + break; - case SSL_CERT_FLAG_SUITEB_192_LOS: - *pcurves = suiteb_curves + 2; - *pcurveslen = 2; - break; - default: - *pcurves = s->tlsext_ellipticcurvelist; - *pcurveslen = s->tlsext_ellipticcurvelist_length; + case SSL_CERT_FLAG_SUITEB_192_LOS: + *pcurves = suiteb_curves + 2; + pcurveslen = 2; + break; + default: + *pcurves = s->tlsext_ellipticcurvelist; + pcurveslen = s->tlsext_ellipticcurvelist_length; + } + if (!*pcurves) + { + *pcurves = eccurves_default; + pcurveslen = sizeof(eccurves_default); + } + } + + /* We do not allow odd length arrays to enter the system. */ + if (pcurveslen & 1) + { + SSLerr(SSL_F_TLS1_GET_CURVELIST, ERR_R_INTERNAL_ERROR); + *num_curves = 0; + return 0; } - if (!*pcurves) + else { - *pcurves = eccurves_default; - *pcurveslen = sizeof(eccurves_default); + *num_curves = pcurveslen / 2; + return 1; } } + +/* See if curve is allowed by security callback */ +static int tls_curve_allowed(SSL *s, const unsigned char *curve, int op) + { + const tls_curve_info *cinfo; + if (curve[0]) + return 1; + if ((curve[1] < 1) || ((size_t)curve[1] > + sizeof(nid_list)/sizeof(nid_list[0]))) + return 0; + cinfo = &nid_list[curve[1]-1]; +#ifdef OPENSSL_NO_EC2M + if (cinfo->flags & TLS_CURVE_CHAR2) + return 0; +#endif + return ssl_security(s, op, cinfo->secbits, cinfo->nid, (void *)curve); + } + /* Check a curve is one of our preferences */ int tls1_check_curve(SSL *s, const unsigned char *p, size_t len) { const unsigned char *curves; - size_t curveslen, i; + size_t num_curves, i; unsigned int suiteb_flags = tls1_suiteb(s); if (len != 3 || p[0] != NAMED_CURVE_TYPE) return 0; @@ -382,11 +494,12 @@ int tls1_check_curve(SSL *s, const unsigned char *p, size_t len) else /* Should never happen */ return 0; } - tls1_get_curvelist(s, 0, &curves, &curveslen); - for (i = 0; i < curveslen; i += 2, curves += 2) + if (!tls1_get_curvelist(s, 0, &curves, &num_curves)) + return 0; + for (i = 0; i < num_curves; i++, curves += 2) { if (p[1] == curves[0] && p[2] == curves[1]) - return 1; + return tls_curve_allowed(s, p + 1, SSL_SECOP_CURVE_CHECK); } return 0; } @@ -399,7 +512,7 @@ int tls1_check_curve(SSL *s, const unsigned char *p, size_t len) int tls1_shared_curve(SSL *s, int nmatch) { const unsigned char *pref, *supp; - size_t preflen, supplen, i, j; + size_t num_pref, num_supp, i, j; int k; /* Can't do anything on client side */ if (s->server == 0) @@ -423,20 +536,26 @@ int tls1_shared_curve(SSL *s, int nmatch) /* If not Suite B just return first preference shared curve */ nmatch = 0; } - tls1_get_curvelist(s, !!(s->options & SSL_OP_CIPHER_SERVER_PREFERENCE), - &supp, &supplen); - tls1_get_curvelist(s, !(s->options & SSL_OP_CIPHER_SERVER_PREFERENCE), - &pref, &preflen); - preflen /= 2; - supplen /= 2; + /* + * Avoid truncation. tls1_get_curvelist takes an int + * but s->options is a long... + */ + if (!tls1_get_curvelist(s, (s->options & SSL_OP_CIPHER_SERVER_PREFERENCE) != 0, + &supp, &num_supp)) + return 0; + if(!tls1_get_curvelist(s, !(s->options & SSL_OP_CIPHER_SERVER_PREFERENCE), + &pref, &num_pref)) + return 0; k = 0; - for (i = 0; i < preflen; i++, pref+=2) + for (i = 0; i < num_pref; i++, pref+=2) { const unsigned char *tsupp = supp; - for (j = 0; j < supplen; j++, tsupp+=2) + for (j = 0; j < num_supp; j++, tsupp+=2) { if (pref[0] == tsupp[0] && pref[1] == tsupp[1]) { + if (!tls_curve_allowed(s, pref, SSL_SECOP_CURVE_SHARED)) + continue; if (nmatch == k) { int id = (pref[0] << 8) | pref[1]; @@ -484,7 +603,7 @@ int tls1_set_curves(unsigned char **pext, size_t *pextlen, return 1; } -#define MAX_CURVELIST 25 +#define MAX_CURVELIST 28 typedef struct { @@ -535,14 +654,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) @@ -570,6 +687,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) @@ -586,22 +705,22 @@ static int tls1_set_ec_id(unsigned char *curve_id, unsigned char *comp_id, static int tls1_check_ec_key(SSL *s, unsigned char *curve_id, unsigned char *comp_id) { - const unsigned char *p; - size_t plen, i; + const unsigned char *pformats, *pcurves; + size_t num_formats, num_curves, i; int j; /* If point formats extension present check it, otherwise everything * is supported (see RFC4492). */ if (comp_id && s->session->tlsext_ecpointformatlist) { - p = s->session->tlsext_ecpointformatlist; - plen = s->session->tlsext_ecpointformatlist_length; - for (i = 0; i < plen; i++, p++) + pformats = s->session->tlsext_ecpointformatlist; + num_formats = s->session->tlsext_ecpointformatlist_length; + for (i = 0; i < num_formats; i++, pformats++) { - if (*comp_id == *p) + if (*comp_id == *pformats) break; } - if (i == plen) + if (i == num_formats) return 0; } if (!curve_id) @@ -609,21 +728,44 @@ static int tls1_check_ec_key(SSL *s, /* Check curve is consistent with client and server preferences */ for (j = 0; j <= 1; j++) { - tls1_get_curvelist(s, j, &p, &plen); - for (i = 0; i < plen; i+=2, p+=2) + if (!tls1_get_curvelist(s, j, &pcurves, &num_curves)) + return 0; + for (i = 0; i < num_curves; i++, pcurves += 2) { - if (p[0] == curve_id[0] && p[1] == curve_id[1]) + if (pcurves[0] == curve_id[0] && + pcurves[1] == curve_id[1]) break; } - if (i == plen) + if (i == num_curves) return 0; /* For clients can only check sent curve list */ if (!s->server) - return 1; + break; } return 1; } +static void tls1_get_formatlist(SSL *s, const unsigned char **pformats, + size_t *num_formats) + { + /* If we have a custom point format list use it otherwise + * use default */ + if (s->tlsext_ecpointformatlist) + { + *pformats = s->tlsext_ecpointformatlist; + *num_formats = s->tlsext_ecpointformatlist_length; + } + else + { + *pformats = ecformats_default; + /* For Suite B we don't support char2 fields */ + if (tls1_suiteb(s)) + *num_formats = sizeof(ecformats_default) - 1; + else + *num_formats = sizeof(ecformats_default); + } + } + /* Check cert parameters compatible with extensions: currently just checks * EC certificates have compatible curves and compression. */ @@ -750,6 +892,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 @@ -793,21 +942,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: @@ -822,7 +969,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) { @@ -837,13 +984,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 @@ -864,6 +1005,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; @@ -904,6 +1046,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); @@ -924,6 +1067,14 @@ int tls12_check_peer_sigalg(const EVP_MD **pmd, SSL *s, SSLerr(SSL_F_TLS12_CHECK_PEER_SIGALG,SSL_R_UNKNOWN_DIGEST); return 0; } + /* Make sure security callback allows algorithm */ + if (!ssl_security(s, SSL_SECOP_SIGALG_CHECK, + EVP_MD_size(*pmd) * 4, EVP_MD_type(*pmd), + (void *)sig)) + { + SSLerr(SSL_F_TLS12_CHECK_PEER_SIGALG,SSL_R_WRONG_SIGNATURE_TYPE); + return 0; + } /* Store the digest used so applications can retrieve it if they * wish. */ @@ -931,6 +1082,7 @@ int tls12_check_peer_sigalg(const EVP_MD **pmd, SSL *s, s->session->sess_cert->peer_key->digest = *pmd; return 1; } + /* Get a mask of disabled algorithms: an algorithm is disabled * if it isn't supported or doesn't appear in supported signature * algorithms. Unlike ssl_cipher_get_disabled this applies to a specific @@ -940,60 +1092,23 @@ int tls12_check_peer_sigalg(const EVP_MD **pmd, SSL *s, void ssl_set_client_disabled(SSL *s) { CERT *c = s->cert; - const unsigned char *sigalgs; - size_t i, sigalgslen; - 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; - /* Now go through all signature algorithms seeing if we support - * any for RSA, DSA, ECDSA. Do this for all versions not just - * TLS 1.2. - */ - sigalgslen = tls12_get_psigalgs(s, &sigalgs); - for (i = 0; i < sigalgslen; i += 2, sigalgs += 2) - { - switch(sigalgs[1]) - { -#ifndef OPENSSL_NO_RSA - case TLSEXT_signature_rsa: - have_rsa = 1; - break; -#endif -#ifndef OPENSSL_NO_DSA - case TLSEXT_signature_dsa: - have_dsa = 1; - break; -#endif -#ifndef OPENSSL_NO_ECDSA - case TLSEXT_signature_ecdsa: - have_ecdsa = 1; - break; -#endif - } - } - /* Disable auth and static DH if we don't include any appropriate + ssl_set_sig_mask(&c->mask_a, s, SSL_SECOP_SIGALG_MASK); + /* Disable static DH if we don't include any appropriate * signature algorithms. */ - if (!have_rsa) - { - c->mask_a |= SSL_aRSA; + if (c->mask_a & SSL_aRSA) c->mask_k |= SSL_kDHr|SSL_kECDHr; - } - if (!have_dsa) - { - c->mask_a |= SSL_aDSS; + if (c->mask_a & SSL_aDSS) c->mask_k |= SSL_kDHd; - } - if (!have_ecdsa) - { - c->mask_a |= SSL_aECDSA; + if (c->mask_a & SSL_aECDSA) c->mask_k |= SSL_kECDHe; - } #ifndef OPENSSL_NO_KRB5 if (!kssl_tgt_is_available(s->kssl_ctx)) { @@ -1009,30 +1124,40 @@ void ssl_set_client_disabled(SSL *s) 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) +int ssl_cipher_disabled(SSL *s, const SSL_CIPHER *c, int op) { - unsigned char a = *((const unsigned char*) in_a); - unsigned char b = *((const unsigned char*) in_b); - - if (a > b) + CERT *ct = s->cert; + if (c->algorithm_ssl & ct->mask_ssl || c->algorithm_mkey & ct->mask_k || c->algorithm_auth & ct->mask_a) return 1; - else if (a < b) - return -1; - return 0; -} + return !ssl_security(s, op, c->strength_bits, 0, (void *)c); + } + +static int tls_use_ticket(SSL *s) + { + if (s->options & SSL_OP_NO_TICKET) + return 0; + return ssl_security(s, SSL_SECOP_TICKET, 0, 0, NULL); + } -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; @@ -1044,7 +1169,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; @@ -1054,15 +1179,38 @@ unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *p, unsigned cha } #endif - /* don't add extensions for SSLv3 unless doing secure renegotiation */ - if (s->client_version == SSL3_VERSION - && !s->s3->send_connection_binding) - return p; - ret+=2; if (ret>=limit) return NULL; /* this really never occurs, but ... */ + /* Add RI if renegotiating */ + if (s->renegotiate) + { + int el; + + if(!ssl_add_clienthello_renegotiate_ext(s, 0, &el, 0)) + { + SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR); + return NULL; + } + + if((limit - ret - 4 - el) < 0) return NULL; + + s2n(TLSEXT_TYPE_renegotiate,ret); + s2n(el,ret); + + if(!ssl_add_clienthello_renegotiate_ext(s, ret, &el, el)) + { + SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR); + return NULL; + } + + ret += el; + } + /* Only add RI for SSLv3 */ + if (s->client_version == SSL3_VERSION) + goto done; + if (s->tlsext_hostname != NULL) { /* Add TLS extension servername to the Client Hello message */ @@ -1095,31 +1243,6 @@ unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *p, unsigned cha ret+=size_str; } - /* Add RI if renegotiating */ - if (s->renegotiate) - { - int el; - - if(!ssl_add_clienthello_renegotiate_ext(s, 0, &el, 0)) - { - SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR); - return NULL; - } - - if((limit - p - 4 - el) < 0) return NULL; - - s2n(TLSEXT_TYPE_renegotiate,ret); - s2n(el,ret); - - if(!ssl_add_clienthello_renegotiate_ext(s, ret, &el, el)) - { - SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR); - return NULL; - } - - ret += el; - } - #ifndef OPENSSL_NO_SRP /* Add SRP username if there is one */ if (s->srp_ctx.login != NULL) @@ -1153,60 +1276,63 @@ unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *p, unsigned cha { /* Add TLS extension ECPointFormats to the ClientHello message */ 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); - } + const unsigned char *pcurves, *pformats; + size_t num_curves, num_formats, curves_list_len; + size_t i; + unsigned char *etmp; + + tls1_get_formatlist(s, &pformats, &num_formats); if ((lenmax = limit - ret - 5) < 0) return NULL; - if (plistlen > (size_t)lenmax) return NULL; - if (plistlen > 255) + if (num_formats > (size_t)lenmax) return NULL; + if (num_formats > 255) { SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR); return NULL; } s2n(TLSEXT_TYPE_ec_point_formats,ret); - s2n(plistlen + 1,ret); - *(ret++) = (unsigned char)plistlen ; - memcpy(ret, plist, plistlen); - ret+=plistlen; + /* The point format list has 1-byte length. */ + s2n(num_formats + 1,ret); + *(ret++) = (unsigned char)num_formats ; + memcpy(ret, pformats, num_formats); + ret+=num_formats; /* Add TLS extension EllipticCurves to the ClientHello message */ - plist = s->tlsext_ellipticcurvelist; - tls1_get_curvelist(s, 0, &plist, &plistlen); + pcurves = s->tlsext_ellipticcurvelist; + if (!tls1_get_curvelist(s, 0, &pcurves, &num_curves)) + return NULL; if ((lenmax = limit - ret - 6) < 0) return NULL; - if (plistlen > (size_t)lenmax) return NULL; - if (plistlen > 65532) + if (num_curves > (size_t)lenmax / 2) return NULL; + if (num_curves > 65532 / 2) { SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR); return NULL; } + s2n(TLSEXT_TYPE_elliptic_curves,ret); - s2n(plistlen + 2, ret); + etmp = ret + 4; + /* Copy curve ID if supported */ + for (i = 0; i < num_curves; i++, pcurves += 2) + { + if (tls_curve_allowed(s, pcurves, SSL_SECOP_CURVE_SUPPORTED)) + { + *etmp++ = pcurves[0]; + *etmp++ = pcurves[1]; + } + } - /* NB: draft-ietf-tls-ecc-12.txt uses a one-byte prefix for - * elliptic_curve_list, but the examples use two bytes. - * http://www1.ietf.org/mail-archive/web/tls/current/msg00538.html - * resolves this to two bytes. - */ - s2n(plistlen, ret); - memcpy(ret, plist, plistlen); - ret+=plistlen; + curves_list_len = etmp - ret - 4; + + s2n(curves_list_len + 2, ret); + s2n(curves_list_len, ret); + ret += curves_list_len; } #endif /* OPENSSL_NO_EC */ - if (!(SSL_get_options(s) & SSL_OP_NO_TICKET)) + if (tls_use_ticket(s)) { int ticklen; if (!s->new_session && s->session && s->session->tlsext_tick) @@ -1242,27 +1368,31 @@ 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; + unsigned char *etmp; salglen = tls12_get_psigalgs(s, &salg); if ((size_t)(limit - ret) < salglen + 6) return NULL; s2n(TLSEXT_TYPE_signature_algorithms,ret); - s2n(salglen + 2, ret); - s2n(salglen, ret); - memcpy(ret, salg, salglen); + etmp = ret; + /* Skip over lengths for now */ + ret += 4; + salglen = tls12_copy_sigalgs(s, ret, salg, salglen); + /* Fill in lengths */ + s2n(salglen + 2, etmp); + s2n(salglen, etmp); ret += salglen; } #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; - if ((long)(limit - ret - 6 - col < 0)) + if ((long)(limit - ret - 6 - col) < 0) return NULL; if (col > 0xFFFD) /* can't happen */ return NULL; @@ -1275,8 +1405,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; @@ -1326,6 +1455,8 @@ unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *p, unsigned cha #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: @@ -1350,13 +1481,25 @@ unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *p, unsigned cha } #endif - if(SSL_get_srtp_profiles(s)) + 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_IS_DTLS(s) && 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); @@ -1368,57 +1511,72 @@ unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *p, unsigned cha } ret += el; } + custom_ext_init(&s->cert->cli_ext); + /* Add custom TLS Extensions to ClientHello */ + if (!custom_ext_add(s, 0, &ret, limit, al)) + return NULL; +#ifdef TLSEXT_TYPE_encrypt_then_mac + s2n(TLSEXT_TYPE_encrypt_then_mac,ret); + s2n(0,ret); +#endif - /* 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 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) { - size_t lenmax; - const unsigned short ext_len = 2; - const unsigned char list_len = 1; - - if ((lenmax = limit - ret - 6) < 0) return NULL; + 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_server_authz, ret); - /* Extension length: 2 bytes */ - s2n(ext_len, ret); - *(ret++) = list_len; - *(ret++) = TLSEXT_AUTHZDATAFORMAT_audit_proof; + s2n(TLSEXT_TYPE_padding, ret); + s2n(hlen, ret); + memset(ret, 0, hlen); + ret += hlen; + } } - if ((extdatalen = ret-p-2) == 0) - return p; + done: + + 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 - - /* don't add extensions for SSLv3, unless doing secure renegotiation */ - if (s->version == SSL3_VERSION && !s->s3->send_connection_binding) - return p; +#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 ret+=2; if (ret>=limit) return NULL; /* this really never occurs, but ... */ - if (!s->hit && s->servername_done == 1 && s->session->tlsext_hostname != NULL) - { - if ((long)(limit - ret - 4) < 0) return NULL; - - s2n(TLSEXT_TYPE_server_name,ret); - s2n(0,ret); - } - if(s->s3->send_connection_binding) { int el; @@ -1429,7 +1587,7 @@ unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *p, unsigned cha 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); @@ -1443,33 +1601,47 @@ unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *p, unsigned cha ret += el; } + /* Only add RI for SSLv3 */ + if (s->version == SSL3_VERSION) + goto done; + + if (!s->hit && s->servername_done == 1 && s->session->tlsext_hostname != NULL) + { + if ((long)(limit - ret - 4) < 0) return NULL; + + s2n(TLSEXT_TYPE_server_name,ret); + s2n(0,ret); + } + #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 */ #endif /* OPENSSL_NO_EC */ - if (s->tlsext_ticket_expected - && !(SSL_get_options(s) & SSL_OP_NO_TICKET)) + if (s->tlsext_ticket_expected && tls_use_ticket(s)) { if ((long)(limit - ret - 4) < 0) return NULL; s2n(TLSEXT_TYPE_session_ticket,ret); @@ -1484,8 +1656,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; @@ -1502,13 +1673,13 @@ unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *p, unsigned cha } #endif - if(s->srtp_profile) + if(SSL_IS_DTLS(s) && s->srtp_profile) { int el; 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); @@ -1540,6 +1711,8 @@ unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *p, unsigned cha /* 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: @@ -1575,87 +1748,203 @@ 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) + if (!custom_ext_add(s, 1, &ret, limit, al)) + return NULL; +#ifdef TLSEXT_TYPE_encrypt_then_mac + if (s->s3->flags & TLS1_FLAGS_ENCRYPT_THEN_MAC) { - 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++) + /* Don't use encrypt_then_mac if AEAD or RC4 + * might want to disable for other cases too. + */ + if (s->s3->tmp.new_cipher->algorithm_mac == SSL_AEAD + || s->s3->tmp.new_cipher->algorithm_enc == SSL_RC4) + s->s3->flags &= ~TLS1_FLAGS_ENCRYPT_THEN_MAC; + else { - 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; + s2n(TLSEXT_TYPE_encrypt_then_mac,ret); + s2n(0,ret); } + } +#endif - 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 (s->s3->alpn_selected) + { + const unsigned char *selected = s->s3->alpn_selected; + unsigned len = s->s3->alpn_selected_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 ((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; + done: + + if ((extdatalen = ret-orig-2)== 0) + return orig; - s2n(extdatalen,p); + s2n(extdatalen, orig); 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; @@ -1663,7 +1952,6 @@ static int ssl_scan_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char unsigned short len; unsigned char *data = *p; int renegotiate_seen = 0; - size_t i; s->servername_done = 0; s->tlsext_status_type = -1; @@ -1671,28 +1959,32 @@ 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; + } + #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) { OPENSSL_free(s->cert->peer_sigalgs); s->cert->peer_sigalgs = NULL; } - /* Clear any shared sigtnature algorithms */ - if (s->cert->shared_sigalgs) - { - OPENSSL_free(s->cert->shared_sigalgs); - s->cert->shared_sigalgs = NULL; - } - /* Clear certificate digests and validity flags */ - for (i = 0; i < SSL_PKEY_NUM; i++) - { - s->cert->pkeys[i].digest = NULL; - 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; @@ -1714,6 +2006,14 @@ static int ssl_scan_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char if (s->tlsext_debug_cb) s->tlsext_debug_cb(s, 0, type, data, size, s->tlsext_debug_arg); + if (type == TLSEXT_TYPE_renegotiate) + { + if(!ssl_parse_clienthello_renegotiate_ext(s, data, size, al)) + return 0; + renegotiate_seen = 1; + } + else if (s->version == SSL3_VERSION) + {} /* The servername extension is treated as follows: - Only the hostname type is supported with a maximum length of 255. @@ -1737,7 +2037,7 @@ static int ssl_scan_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char */ - if (type == TLSEXT_TYPE_server_name) + else if (type == TLSEXT_TYPE_server_name) { unsigned char *sdata; int servname_type; @@ -1847,8 +2147,7 @@ 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++); @@ -1883,15 +2182,16 @@ 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 || - ellipticcurvelist_length < 1) + ellipticcurvelist_length < 1 || + /* Each NamedCurve is 2 bytes. */ + ellipticcurvelist_length & 1) { *al = TLS1_AD_DECODE_ERROR; return 0; @@ -1922,8 +2222,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; @@ -1961,12 +2260,6 @@ static int ssl_scan_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char return 0; } } - else if (type == TLSEXT_TYPE_renegotiate) - { - if(!ssl_parse_clienthello_renegotiate_ext(s, data, size, al)) - return 0; - renegotiate_seen = 1; - } else if (type == TLSEXT_TYPE_signature_algorithms) { int dsize; @@ -1982,24 +2275,13 @@ static int ssl_scan_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *al = SSL_AD_DECODE_ERROR; return 0; } - if (!tls1_process_sigalgs(s, data, dsize)) + if (!tls1_save_sigalgs(s, data, dsize)) { *al = SSL_AD_DECODE_ERROR; return 0; } - /* If sigalgs received and no shared algorithms fatal - * error. - */ - if (s->cert->peer_sigalgs && !s->cert->shared_sigalgs) - { - SSLerr(SSL_F_SSL_SCAN_CLIENTHELLO_TLSEXT, - SSL_R_NO_SHARED_SIGATURE_ALGORITHMS); - *al = SSL_AD_ILLEGAL_PARAMETER; - 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) @@ -2129,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. @@ -2150,71 +2433,40 @@ 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) + else if (SSL_IS_DTLS(s) && SSL_get_srtp_profiles(s) + && type == TLSEXT_TYPE_use_srtp) { if(ssl_parse_clienthello_use_srtp_ext(s, data, size, al)) return 0; } - - else if (type == TLSEXT_TYPE_server_authz) +#ifdef TLSEXT_TYPE_encrypt_then_mac + else if (type == TLSEXT_TYPE_encrypt_then_mac) + s->s3->flags |= TLS1_FLAGS_ENCRYPT_THEN_MAC; +#endif + /* 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) { - unsigned char *sdata = data; - unsigned char server_authz_dataformatlist_length; - - if (size == 0) - { - *al = TLS1_AD_DECODE_ERROR; + if (custom_ext_parse(s, 1, type, data, size, al) <= 0) 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; - } - } - } } data+=size; @@ -2234,9 +2486,6 @@ static int ssl_scan_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED); return 0; } - /* If no signature algorithms extension set default values */ - if (!s->cert->peer_sigalgs) - ssl_cert_set_default_md(s->cert); return 1; } @@ -2244,6 +2493,7 @@ static int ssl_scan_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char 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); @@ -2290,12 +2540,23 @@ static int ssl_scan_serverhello_tlsext(SSL *s, unsigned char **p, unsigned char #ifndef OPENSSL_NO_NEXTPROTONEG s->s3->next_proto_neg_seen = 0; #endif + s->tlsext_ticket_expected = 0; + + 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; @@ -2318,7 +2579,16 @@ static int ssl_scan_serverhello_tlsext(SSL *s, unsigned char **p, unsigned char s->tlsext_debug_cb(s, 1, type, data, size, s->tlsext_debug_arg); - if (type == TLSEXT_TYPE_server_name) + + if (type == TLSEXT_TYPE_renegotiate) + { + if(!ssl_parse_serverhello_renegotiate_ext(s, data, size, al)) + return 0; + renegotiate_seen = 1; + } + else if (s->version == SSL3_VERSION) + {} + else if (type == TLSEXT_TYPE_server_name) { if (s->tlsext_hostname == NULL || size > 0) { @@ -2329,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++); @@ -2340,15 +2609,18 @@ static int ssl_scan_serverhello_tlsext(SSL *s, unsigned char **p, unsigned char *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; @@ -2367,8 +2639,7 @@ static int ssl_scan_serverhello_tlsext(SSL *s, unsigned char **p, unsigned char *al = TLS1_AD_INTERNAL_ERROR; return 0; } - if ((SSL_get_options(s) & SSL_OP_NO_TICKET) - || (size > 0)) + if (!tls_use_ticket(s) || (size > 0)) { *al = TLS1_AD_UNSUPPORTED_EXTENSION; return 0; @@ -2376,8 +2647,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; @@ -2407,8 +2677,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. @@ -2429,38 +2698,77 @@ 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; + } + /* The data must be valid */ + if (!ssl_next_proto_validate(data, size)) + { + *al = TLS1_AD_DECODE_ERROR; + return 0; + } + if (s->ctx->next_proto_select_cb(s, &selected, &selected_len, data, size, s->ctx->next_proto_select_cb_arg) != SSL_TLSEXT_ERR_OK) + { + *al = TLS1_AD_INTERNAL_ERROR; + return 0; + } + s->next_proto_negotiated = OPENSSL_malloc(selected_len); + if (!s->next_proto_negotiated) + { + *al = TLS1_AD_INTERNAL_ERROR; + return 0; + } + memcpy(s->next_proto_negotiated, selected, selected_len); + s->next_proto_negotiated_len = selected_len; + 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; } - /* The data must be valid */ - if (!ssl_next_proto_validate(data, size)) + 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; } - if (s->ctx->next_proto_select_cb(s, &selected, &selected_len, data, size, s->ctx->next_proto_select_cb_arg) != SSL_TLSEXT_ERR_OK) + len = data[2]; + if (len != (unsigned) size - 3) { - *al = TLS1_AD_INTERNAL_ERROR; + *al = TLS1_AD_DECODE_ERROR; return 0; } - s->next_proto_negotiated = OPENSSL_malloc(selected_len); - if (!s->next_proto_negotiated) + 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->next_proto_negotiated, selected, selected_len); - s->next_proto_negotiated_len = selected_len; - s->s3->next_proto_neg_seen = 1; - } -#endif - else if (type == TLSEXT_TYPE_renegotiate) - { - if(!ssl_parse_serverhello_renegotiate_ext(s, data, size, al)) - return 0; - renegotiate_seen = 1; + memcpy(s->s3->alpn_selected, data + 3, len); + s->s3->alpn_selected_len = len; } #ifndef OPENSSL_NO_HEARTBEATS else if (type == TLSEXT_TYPE_heartbeat) @@ -2479,51 +2787,26 @@ static int ssl_scan_serverhello_tlsext(SSL *s, unsigned char **p, unsigned char } } #endif - else if (type == TLSEXT_TYPE_use_srtp) + else if (SSL_IS_DTLS(s) && type == TLSEXT_TYPE_use_srtp) { if(ssl_parse_serverhello_use_srtp_ext(s, data, size, al)) return 0; } - - else if (type == TLSEXT_TYPE_server_authz) +#ifdef TLSEXT_TYPE_encrypt_then_mac + else if (type == TLSEXT_TYPE_encrypt_then_mac) { - /* 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; + /* Ignore if inappropriate ciphersuite */ + if (s->s3->tmp.new_cipher->algorithm_mac != SSL_AEAD + && s->s3->tmp.new_cipher->algorithm_enc != SSL_RC4) + s->s3->flags |= TLS1_FLAGS_ENCRYPT_THEN_MAC; } +#endif + /* If this extension type was not otherwise handled, but + * matches a custom_cli_ext_record, then send it to the c + * callback */ + else if (custom_ext_parse(s, 0, type, data, size, al) <= 0) + return 0; data += size; } @@ -2622,32 +2905,6 @@ 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; } @@ -2746,6 +3003,50 @@ static int ssl_check_clienthello_tlsext_early(SSL *s) } } +int tls1_set_server_sigalgs(SSL *s) + { + int al; + size_t i; + /* Clear any shared sigtnature algorithms */ + if (s->cert->shared_sigalgs) + { + OPENSSL_free(s->cert->shared_sigalgs); + s->cert->shared_sigalgs = NULL; + } + /* Clear certificate digests and validity flags */ + for (i = 0; i < SSL_PKEY_NUM; i++) + { + s->cert->pkeys[i].digest = NULL; + s->cert->pkeys[i].valid_flags = 0; + } + + /* If sigalgs received process it. */ + if (s->cert->peer_sigalgs) + { + if (!tls1_process_sigalgs(s)) + { + SSLerr(SSL_F_TLS1_SET_SERVER_SIGALGS, + ERR_R_MALLOC_FAILURE); + al = SSL_AD_INTERNAL_ERROR; + goto err; + } + /* Fatal error is no shared signature algorithms */ + if (!s->cert->shared_sigalgs) + { + SSLerr(SSL_F_TLS1_SET_SERVER_SIGALGS, + SSL_R_NO_SHARED_SIGATURE_ALGORITHMS); + al = SSL_AD_ILLEGAL_PARAMETER; + goto err; + } + } + else + ssl_cert_set_default_md(s->cert); + return 1; + err: + ssl3_send_alert(s, SSL3_AL_FATAL, al); + return 0; + } + int ssl_check_clienthello_tlsext_late(SSL *s) { int ret = SSL_TLSEXT_ERR_OK; @@ -2825,7 +3126,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; @@ -2988,14 +3289,14 @@ int tls1_process_ticket(SSL *s, unsigned char *session_id, int len, /* If tickets disabled behave as if no ticket present * to permit stateful resumption. */ - if (SSL_get_options(s) & SSL_OP_NO_TICKET) + if (!tls_use_ticket(s)) return 0; if ((s->version <= SSL3_VERSION) || !limit) return 0; 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; @@ -3131,8 +3432,11 @@ 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)) + { + EVP_CIPHER_CTX_cleanup(&ctx); return 2; + } /* Attempt to decrypt session data */ /* Move p after IV to start of encrypted ticket, update length */ p = etick + 16 + EVP_CIPHER_CTX_iv_length(&ctx); @@ -3145,7 +3449,11 @@ static int tls_decrypt_ticket(SSL *s, const unsigned char *etick, int eticklen, } 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; @@ -3242,40 +3550,60 @@ int tls12_get_sigid(const EVP_PKEY *pk) sizeof(tls12_sig)/sizeof(tls12_lookup)); } -const EVP_MD *tls12_get_hash(unsigned char hash_alg) +typedef struct { - switch(hash_alg) - { -#ifndef OPENSSL_NO_MD5 - case TLSEXT_hash_md5: -#ifdef OPENSSL_FIPS - if (FIPS_mode()) - return NULL; + int nid; + int secbits; + const EVP_MD *(*mfunc)(void); + } tls12_hash_info; + +static const tls12_hash_info tls12_md_info[] = { +#ifdef OPENSSL_NO_MD5 + {NID_md5, 64, 0}, +#else + {NID_md5, 64, EVP_md5}, #endif - return EVP_md5(); +#ifdef OPENSSL_NO_SHA + {NID_sha1, 80, 0}, +#else + {NID_sha1, 80, EVP_sha1}, #endif -#ifndef OPENSSL_NO_SHA - case TLSEXT_hash_sha1: - return EVP_sha1(); +#ifdef OPENSSL_NO_SHA256 + {NID_sha224, 112, 0}, + {NID_sha256, 128, 0}, +#else + {NID_sha224, 112, EVP_sha224}, + {NID_sha256, 128, EVP_sha256}, #endif -#ifndef OPENSSL_NO_SHA256 - case TLSEXT_hash_sha224: - return EVP_sha224(); - - case TLSEXT_hash_sha256: - return EVP_sha256(); +#ifdef OPENSSL_NO_SHA512 + {NID_sha384, 192, 0}, + {NID_sha512, 256, 0} +#else + {NID_sha384, 192, EVP_sha384}, + {NID_sha512, 256, EVP_sha512} #endif -#ifndef OPENSSL_NO_SHA512 - case TLSEXT_hash_sha384: - return EVP_sha384(); +}; - case TLSEXT_hash_sha512: - return EVP_sha512(); -#endif - default: +static const tls12_hash_info *tls12_get_hash_info(unsigned char hash_alg) + { + if (hash_alg == 0) return NULL; + if (hash_alg > sizeof(tls12_md_info)/sizeof(tls12_md_info[0])) + return NULL; + return tls12_md_info + hash_alg - 1; + } - } +const EVP_MD *tls12_get_hash(unsigned char hash_alg) + { + const tls12_hash_info *inf; +#ifndef OPENSSL_FIPS + if (hash_alg == TLSEXT_hash_md5 && FIPS_mode()) + return NULL; +#endif + inf = tls12_get_hash_info(hash_alg); + if (!inf || !inf->mfunc) + return NULL; + return inf->mfunc(); } static int tls12_get_pkey_idx(unsigned char sig_alg) @@ -3328,8 +3656,86 @@ static void tls1_lookup_sigalg(int *phash_nid, int *psign_nid, *psignhash_nid = NID_undef; } } +/* Check to see if a signature algorithm is allowed */ +static int tls12_sigalg_allowed(SSL *s, int op, const unsigned char *ptmp) + { + /* See if we have an entry in the hash table and it is enabled */ + const tls12_hash_info *hinf = tls12_get_hash_info(ptmp[0]); + if (!hinf || !hinf->mfunc) + return 0; + /* See if public key algorithm allowed */ + if (tls12_get_pkey_idx(ptmp[1]) == -1) + return 0; + /* Finally see if security callback allows it */ + return ssl_security(s, op, hinf->secbits, hinf->nid, (void *)ptmp); + } + +/* Get a mask of disabled public key algorithms based on supported + * signature algorithms. For example if no signature algorithm supports RSA + * then RSA is disabled. + */ + +void ssl_set_sig_mask(unsigned long *pmask_a, SSL *s, int op) + { + const unsigned char *sigalgs; + size_t i, sigalgslen; + int have_rsa = 0, have_dsa = 0, have_ecdsa = 0; + /* Now go through all signature algorithms seeing if we support + * any for RSA, DSA, ECDSA. Do this for all versions not just + * TLS 1.2. To keep down calls to security callback only check + * if we have to. + */ + sigalgslen = tls12_get_psigalgs(s, &sigalgs); + for (i = 0; i < sigalgslen; i += 2, sigalgs += 2) + { + switch(sigalgs[1]) + { +#ifndef OPENSSL_NO_RSA + case TLSEXT_signature_rsa: + if (!have_rsa && tls12_sigalg_allowed(s, op, sigalgs)) + have_rsa = 1; + break; +#endif +#ifndef OPENSSL_NO_DSA + case TLSEXT_signature_dsa: + if (!have_dsa && tls12_sigalg_allowed(s, op, sigalgs)) + have_dsa = 1; + break; +#endif +#ifndef OPENSSL_NO_ECDSA + case TLSEXT_signature_ecdsa: + if (!have_ecdsa && tls12_sigalg_allowed(s, op, sigalgs)) + have_ecdsa = 1; + break; +#endif + } + } + if (!have_rsa) + *pmask_a |= SSL_aRSA; + if (!have_dsa) + *pmask_a |= SSL_aDSS; + if (!have_ecdsa) + *pmask_a |= SSL_aECDSA; + } + +size_t tls12_copy_sigalgs(SSL *s, unsigned char *out, + const unsigned char *psig, size_t psiglen) + { + unsigned char *tmpout = out; + size_t i; + for (i = 0; i < psiglen; i += 2, psig += 2) + { + if (tls12_sigalg_allowed(s, SSL_SECOP_SIGALG_SUPPORTED, psig)) + { + *tmpout++ = psig[0]; + *tmpout++ = psig[1]; + } + } + return tmpout - out; + } + /* Given preference and allowed sigalgs set shared sigalgs */ -static int tls12_do_shared_sigalgs(TLS_SIGALGS *shsig, +static int tls12_shared_sigalgs(SSL *s, TLS_SIGALGS *shsig, const unsigned char *pref, size_t preflen, const unsigned char *allow, size_t allowlen) { @@ -3338,9 +3744,7 @@ static int tls12_do_shared_sigalgs(TLS_SIGALGS *shsig, for (i = 0, ptmp = pref; i < preflen; i+=2, ptmp+=2) { /* Skip disabled hashes or signature algorithms */ - if (tls12_get_hash(ptmp[0]) == NULL) - continue; - if (tls12_get_pkey_idx(ptmp[1]) == -1) + if (!tls12_sigalg_allowed(s, SSL_SECOP_SIGALG_SHARED, ptmp)) continue; for (j = 0, atmp = allow; j < allowlen; j+=2, atmp+=2) { @@ -3373,6 +3777,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) { @@ -3400,13 +3809,13 @@ static int tls1_set_shared_sigalgs(SSL *s) pref = c->peer_sigalgs; preflen = c->peer_sigalgslen; } - nmatch = tls12_do_shared_sigalgs(NULL, pref, preflen, allow, allowlen); + nmatch = tls12_shared_sigalgs(s, NULL, pref, preflen, allow, allowlen); if (!nmatch) return 1; salgs = OPENSSL_malloc(nmatch * sizeof(TLS_SIGALGS)); if (!salgs) return 0; - nmatch = tls12_do_shared_sigalgs(salgs, pref, preflen, allow, allowlen); + nmatch = tls12_shared_sigalgs(s, salgs, pref, preflen, allow, allowlen); c->shared_sigalgs = salgs; c->shared_sigalgslen = nmatch; return 1; @@ -3415,27 +3824,35 @@ static int tls1_set_shared_sigalgs(SSL *s) /* Set preferred digest for each key type */ -int tls1_process_sigalgs(SSL *s, const unsigned char *data, int dsize) +int tls1_save_sigalgs(SSL *s, const unsigned char *data, int dsize) { - int idx; - size_t i; - 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; c->peer_sigalgslen = dsize; memcpy(c->peer_sigalgs, data, dsize); + return 1; + } - tls1_set_shared_sigalgs(s); +int tls1_process_sigalgs(SSL *s) + { + int idx; + size_t i; + const EVP_MD *md; + CERT *c = s->cert; + TLS_SIGALGS *sigptr; + if (!tls1_set_shared_sigalgs(s)) + return 0; #ifdef OPENSSL_SSL_DEBUG_BROKEN_PROTOCOL if (s->cert->cert_flags & SSL_CERT_FLAG_BROKEN_PROTOCOL) @@ -3561,16 +3978,20 @@ tls1_process_heartbeat(SSL *s) 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; @@ -3909,13 +4330,10 @@ int tls1_check_chain(SSL *s, X509 *x, EVP_PKEY *pk, STACK_OF(X509) *chain, if (check_flags) check_flags |= CERT_PKEY_SUITEB; ok = X509_chain_check_suiteb(NULL, x, chain, suiteb_flags); - if (ok != X509_V_OK) - { - if (check_flags) - rv |= CERT_PKEY_SUITEB; - else - goto end; - } + if (ok == X509_V_OK) + rv |= CERT_PKEY_SUITEB; + else if (!check_flags) + goto end; } /* Check all signature algorithms are consistent with @@ -4161,3 +4579,131 @@ 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 + +static int ssl_security_cert_key(SSL *s, SSL_CTX *ctx, X509 *x, int op) + { + int secbits; + EVP_PKEY *pkey = X509_get_pubkey(x); + if (pkey) + { + secbits = EVP_PKEY_security_bits(pkey); + EVP_PKEY_free(pkey); + } + else + secbits = -1; + if (s) + return ssl_security(s, op, secbits, 0, x); + else + return ssl_ctx_security(ctx, op, secbits, 0, x); + } + +static int ssl_security_cert_sig(SSL *s, SSL_CTX *ctx, X509 *x, int op) + { + /* Lookup signature algorithm digest */ + int secbits = -1, md_nid = NID_undef, sig_nid; + sig_nid = X509_get_signature_nid(x); + if (sig_nid && OBJ_find_sigid_algs(sig_nid, &md_nid, NULL)) + { + const EVP_MD *md; + if (md_nid && (md = EVP_get_digestbynid(md_nid))) + secbits = EVP_MD_size(md) * 4; + } + if (s) + return ssl_security(s, op, secbits, md_nid, x); + else + return ssl_ctx_security(ctx, op, secbits, md_nid, x); + } + +int ssl_security_cert(SSL *s, SSL_CTX *ctx, X509 *x, int vfy, int is_ee) + { + if (vfy) + vfy = SSL_SECOP_PEER; + if (is_ee) + { + if (!ssl_security_cert_key(s, ctx, x, SSL_SECOP_EE_KEY | vfy)) + return SSL_R_EE_KEY_TOO_SMALL; + } + else + { + if (!ssl_security_cert_key(s, ctx, x, SSL_SECOP_CA_KEY | vfy)) + return SSL_R_CA_KEY_TOO_SMALL; + } + if (!ssl_security_cert_sig(s, ctx, x, SSL_SECOP_CA_MD | vfy)) + return SSL_R_CA_MD_TOO_WEAK; + return 1; + } + +/* Check security of a chain, if sk includes the end entity certificate + * then x is NULL. If vfy is 1 then we are verifying a peer chain and + * not sending one to the peer. + * Return values: 1 if ok otherwise error code to use + */ + +int ssl_security_cert_chain(SSL *s, STACK_OF(X509) *sk, X509 *x, int vfy) + { + int rv, start_idx, i; + if (x == NULL) + { + x = sk_X509_value(sk, 0); + start_idx = 1; + } + else + start_idx = 0; + + rv = ssl_security_cert(s, NULL, x, vfy, 1); + if (rv != 1) + return rv; + + for (i = start_idx; i < sk_X509_num(sk); i++) + { + x = sk_X509_value(sk, i); + rv = ssl_security_cert(s, NULL, x, vfy, 0); + if (rv != 1) + return rv; + } + return 1; + }