X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=blobdiff_plain;f=ssl%2Ft1_lib.c;h=bddffd92cc045ae920d63e6e140c78b4d96c3425;hp=4734c37e0a02d90665a8ccd21f786b1a85d34b2e;hb=96db9023b881d7cd9f379b0c154650d6c108e9a3;hpb=1cb4d65b87ef7eafe6a7f5594276caf976303a78 diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c index 4734c37e0a..bddffd92cc 100644 --- a/ssl/t1_lib.c +++ b/ssl/t1_lib.c @@ -342,19 +342,11 @@ 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 }; int tls12_get_req_sig_algs(SSL *s, unsigned char *p) { size_t slen = sizeof(tls12_sigalgs); -#ifdef OPENSSL_FIPS - /* If FIPS mode don't include MD5 which is last */ - if (FIPS_mode()) - slen -= 2; -#endif if (p) memcpy(p, tls12_sigalgs, slen); return (int)slen; @@ -432,25 +424,29 @@ unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *p, unsigned cha } #ifndef OPENSSL_NO_SRP -#define MIN(x,y) (((x)<(y))?(x):(y)) - /* we add SRP username the first time only if we have one! */ + /* Add SRP username if there is one */ if (s->srp_ctx.login != NULL) - {/* Add TLS extension SRP username to the Client Hello message */ - int login_len = MIN(strlen(s->srp_ctx.login) + 1, 255); - long lenmax; + { /* Add TLS extension SRP username to the Client Hello message */ - if ((lenmax = limit - ret - 5) < 0) return NULL; - if (login_len > lenmax) return NULL; - if (login_len > 255) + int login_len = strlen(s->srp_ctx.login); + if (login_len > 255 || login_len == 0) { SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR); return NULL; - } + } + + /* check for enough space. + 4 for the srp type type and entension length + 1 for the srp user identity + + srp user identity length + */ + if ((limit - ret - 5 - login_len) < 0) return NULL; + + /* fill in the extension */ s2n(TLSEXT_TYPE_srp,ret); s2n(login_len+1,ret); - - (*ret++) = (unsigned char) MIN(strlen(s->srp_ctx.login), 254); - memcpy(ret, s->srp_ctx.login, MIN(strlen(s->srp_ctx.login), 254)); + (*ret++) = (unsigned char) login_len; + memcpy(ret, s->srp_ctx.login, login_len); ret+=login_len; } #endif @@ -540,7 +536,7 @@ unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *p, unsigned cha } skip_ext: - if (TLS1_get_version(s) >= TLS1_2_VERSION) + if (TLS1_get_client_version(s) >= TLS1_2_VERSION) { if ((size_t)(limit - ret) < sizeof(tls12_sigalgs) + 6) return NULL; @@ -645,6 +641,7 @@ unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *p, unsigned cha } #endif +#ifndef OPENSSL_NO_SRTP if(SSL_get_srtp_profiles(s)) { int el; @@ -663,6 +660,37 @@ unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *p, unsigned cha } ret += el; } +#endif + +#ifdef TLSEXT_TYPE_padding + /* 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. + */ + { + 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; @@ -777,6 +805,7 @@ unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *p, unsigned cha } #endif +#ifndef OPENSSL_NO_SRTP if(s->srtp_profile) { int el; @@ -795,6 +824,7 @@ unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *p, unsigned cha } ret+=el; } +#endif if (((s->s3->tmp.new_cipher->id & 0xFFFF)==0x80 || (s->s3->tmp.new_cipher->id & 0xFFFF)==0x81) && (SSL_get_options(s) & SSL_OP_CRYPTOPRO_TLSEXT_BUG)) @@ -825,6 +855,7 @@ unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *p, unsigned cha *(ret++) = SSL_TLSEXT_HB_DONT_SEND_REQUESTS; else *(ret++) = SSL_TLSEXT_HB_ENABLED; + } #endif @@ -857,6 +888,89 @@ unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *p, unsigned cha return ret; } +#ifndef OPENSSL_NO_EC +/* ssl_check_for_safari attempts to fingerprint Safari using OS X + * SecureTransport using the TLS extension block in |d|, of length |n|. + * Safari, since 10.6, sends exactly these extensions, in this order: + * SNI, + * elliptic_curves + * ec_point_formats + * + * We wish to fingerprint Safari because they broke ECDHE-ECDSA support in 10.8, + * but they advertise support. So enabling ECDHE-ECDSA ciphers breaks them. + * Sadly we cannot differentiate 10.6, 10.7 and 10.8.4 (which work), from + * 10.8..10.8.3 (which don't work). + */ +static void ssl_check_for_safari(SSL *s, const unsigned char *data, const unsigned char *d, int n) { + unsigned short type, size; + static const unsigned char kSafariExtensionsBlock[] = { + 0x00, 0x0a, /* elliptic_curves extension */ + 0x00, 0x08, /* 8 bytes */ + 0x00, 0x06, /* 6 bytes of curve ids */ + 0x00, 0x17, /* P-256 */ + 0x00, 0x18, /* P-384 */ + 0x00, 0x19, /* P-521 */ + + 0x00, 0x0b, /* ec_point_formats */ + 0x00, 0x02, /* 2 bytes */ + 0x01, /* 1 point format */ + 0x00, /* uncompressed */ + }; + + /* The following is only present in TLS 1.2 */ + static const unsigned char kSafariTLS12ExtensionsBlock[] = { + 0x00, 0x0d, /* signature_algorithms */ + 0x00, 0x0c, /* 12 bytes */ + 0x00, 0x0a, /* 10 bytes */ + 0x05, 0x01, /* SHA-384/RSA */ + 0x04, 0x01, /* SHA-256/RSA */ + 0x02, 0x01, /* SHA-1/RSA */ + 0x04, 0x03, /* SHA-256/ECDSA */ + 0x02, 0x03, /* SHA-1/ECDSA */ + }; + + if (data >= (d+n-2)) + return; + data += 2; + + if (data > (d+n-4)) + return; + n2s(data,type); + n2s(data,size); + + if (type != TLSEXT_TYPE_server_name) + return; + + if (data+size > d+n) + return; + data += size; + + if (TLS1_get_client_version(s) >= TLS1_2_VERSION) + { + const size_t len1 = sizeof(kSafariExtensionsBlock); + const size_t len2 = sizeof(kSafariTLS12ExtensionsBlock); + + if (data + len1 + len2 != d+n) + return; + if (memcmp(data, kSafariExtensionsBlock, len1) != 0) + return; + if (memcmp(data + len1, kSafariTLS12ExtensionsBlock, len2) != 0) + return; + } + else + { + const size_t len = sizeof(kSafariExtensionsBlock); + + if (data + len != d+n) + return; + if (memcmp(data, kSafariExtensionsBlock, len) != 0) + return; + } + + s->s3->is_probably_safari = 1; +} +#endif /* !OPENSSL_NO_EC */ + int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, int n, int *al) { unsigned short type; @@ -877,6 +991,11 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in 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 */ + if (data >= (d+n-2)) goto ri_check; n2s(data,len); @@ -1006,13 +1125,25 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in #ifndef OPENSSL_NO_SRP else if (type == TLSEXT_TYPE_srp) { - if (size > 0) + if (size <= 0 || ((len = data[0])) != (size -1)) { - len = data[0]; - if ((s->srp_ctx.login = OPENSSL_malloc(len+1)) == NULL) - return -1; - memcpy(s->srp_ctx.login, &data[1], len); - s->srp_ctx.login[len]='\0'; + *al = SSL_AD_DECODE_ERROR; + return 0; + } + if (s->srp_ctx.login != NULL) + { + *al = SSL_AD_DECODE_ERROR; + return 0; + } + if ((s->srp_ctx.login = OPENSSL_malloc(len+1)) == NULL) + return -1; + memcpy(s->srp_ctx.login, &data[1], len); + s->srp_ctx.login[len]='\0'; + + if (strlen(s->srp_ctx.login) != len) + { + *al = SSL_AD_DECODE_ERROR; + return 0; } } #endif @@ -1060,7 +1191,8 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in 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; @@ -1159,7 +1291,7 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in } } else if (type == TLSEXT_TYPE_status_request && - s->version != DTLS1_VERSION && s->ctx->tlsext_status_cb) + s->version != DTLS1_VERSION) { if (size < 5) @@ -1282,6 +1414,8 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in s->tlsext_heartbeat |= SSL_TLSEXT_HB_ENABLED; s->tlsext_heartbeat |= SSL_TLSEXT_HB_DONT_SEND_REQUESTS; break; + default: *al = SSL_AD_ILLEGAL_PARAMETER; + return 0; } } #endif @@ -1309,12 +1443,14 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in #endif /* session ticket processed earlier */ +#ifndef OPENSSL_NO_SRTP else if (type == TLSEXT_TYPE_use_srtp) - { + { if(ssl_parse_clienthello_use_srtp_ext(s, data, size, al)) return 0; - } + } +#endif data+=size; } @@ -1414,7 +1550,8 @@ int ssl_parse_serverhello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in 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; @@ -1508,7 +1645,7 @@ int ssl_parse_serverhello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in 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; @@ -1553,15 +1690,19 @@ int ssl_parse_serverhello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in s->tlsext_heartbeat |= SSL_TLSEXT_HB_ENABLED; s->tlsext_heartbeat |= SSL_TLSEXT_HB_DONT_SEND_REQUESTS; break; + default: *al = SSL_AD_ILLEGAL_PARAMETER; + return 0; } } #endif +#ifndef OPENSSL_NO_SRTP else if (type == TLSEXT_TYPE_use_srtp) - { + { if(ssl_parse_serverhello_use_srtp_ext(s, data, size, al)) return 0; - } + } +#endif data+=size; } @@ -1742,7 +1883,7 @@ int ssl_prepare_serverhello_tlsext(SSL *s) return 1; } -int ssl_check_clienthello_tlsext(SSL *s) +int ssl_check_clienthello_tlsext_early(SSL *s) { int ret=SSL_TLSEXT_ERR_NOACK; int al = SSL_AD_UNRECOGNIZED_NAME; @@ -1761,42 +1902,12 @@ 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; @@ -1848,8 +1959,8 @@ int ssl_check_clienthello_tlsext(SSL *s) } } -#endif err: +#endif switch (ret) { case SSL_TLSEXT_ERR_ALERT_FATAL: @@ -1867,6 +1978,71 @@ 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; @@ -2168,7 +2344,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 */ @@ -2240,7 +2416,7 @@ static tls12_lookup tls12_sig[] = { #ifndef OPENSSL_NO_RSA {EVP_PKEY_RSA, TLSEXT_signature_rsa}, #endif -#ifndef OPENSSL_NO_RSA +#ifndef OPENSSL_NO_DSA {EVP_PKEY_DSA, TLSEXT_signature_dsa}, #endif #ifndef OPENSSL_NO_ECDSA @@ -2274,6 +2450,8 @@ static int tls12_find_nid(int id, tls12_lookup *table, size_t tlen) int tls12_get_sigandhash(unsigned char *p, const EVP_PKEY *pk, const EVP_MD *md) { int sig_id, md_id; + if (!md) + return 0; md_id = tls12_find_id(EVP_MD_type(md), tls12_md, sizeof(tls12_md)/sizeof(tls12_lookup)); if (md_id == -1) @@ -2296,14 +2474,6 @@ const EVP_MD *tls12_get_hash(unsigned char hash_alg) { switch(hash_alg) { -#ifndef OPENSSL_NO_MD5 - case TLSEXT_hash_md5: -#ifdef OPENSSL_FIPS - if (FIPS_mode()) - return NULL; -#endif - return EVP_md5(); -#endif #ifndef OPENSSL_NO_SHA case TLSEXT_hash_sha1: return EVP_sha1(); @@ -2391,7 +2561,7 @@ int tls1_process_sigalgs(SSL *s, const unsigned char *data, int dsize) */ #ifndef OPENSSL_NO_DSA if (!c->pkeys[SSL_PKEY_DSA_SIGN].digest) - c->pkeys[SSL_PKEY_DSA_SIGN].digest = EVP_dss1(); + c->pkeys[SSL_PKEY_DSA_SIGN].digest = EVP_sha1(); #endif #ifndef OPENSSL_NO_RSA if (!c->pkeys[SSL_PKEY_RSA_SIGN].digest) @@ -2402,7 +2572,7 @@ int tls1_process_sigalgs(SSL *s, const unsigned char *data, int dsize) #endif #ifndef OPENSSL_NO_ECDSA if (!c->pkeys[SSL_PKEY_ECC].digest) - c->pkeys[SSL_PKEY_ECC].digest = EVP_ecdsa(); + c->pkeys[SSL_PKEY_ECC].digest = EVP_sha1(); #endif return 1; } @@ -2418,16 +2588,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; @@ -2444,7 +2618,10 @@ tls1_process_heartbeat(SSL *s) *bp++ = TLS1_HB_RESPONSE; s2n(payload, bp); memcpy(bp, pl, payload); - + bp += payload; + /* Random padding */ + RAND_pseudo_bytes(bp, padding); + r = ssl3_write_bytes(s, TLS1_RT_HEARTBEAT, buffer, 3 + payload + padding); if (r >= 0 && s->msg_callback)