diff options
Diffstat (limited to 'app/openssl/ssl/t1_lib.c')
-rw-r--r-- | app/openssl/ssl/t1_lib.c | 1267 |
1 files changed, 1166 insertions, 101 deletions
diff --git a/app/openssl/ssl/t1_lib.c b/app/openssl/ssl/t1_lib.c index bbab4675..369e09f4 100644 --- a/app/openssl/ssl/t1_lib.c +++ b/app/openssl/ssl/t1_lib.c @@ -114,6 +114,7 @@ #include <openssl/evp.h> #include <openssl/hmac.h> #include <openssl/ocsp.h> +#include <openssl/rand.h> #include "ssl_locl.h" const char tls1_version_str[]="TLSv1" OPENSSL_VERSION_PTEXT; @@ -136,6 +137,7 @@ SSL3_ENC_METHOD TLSv1_enc_data={ 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, }; long tls1_default_timeout(void) @@ -166,10 +168,11 @@ void tls1_free(SSL *s) void tls1_clear(SSL *s) { ssl3_clear(s); - s->version=TLS1_VERSION; + s->version = s->method->version; } #ifndef OPENSSL_NO_EC + static int nid_list[] = { NID_sect163k1, /* sect163k1 (1) */ @@ -198,7 +201,36 @@ static int nid_list[] = NID_secp384r1, /* secp384r1 (24) */ NID_secp521r1 /* secp521r1 (25) */ }; - + +static int pref_list[] = + { + NID_sect571r1, /* sect571r1 (14) */ + NID_sect571k1, /* sect571k1 (13) */ + NID_secp521r1, /* secp521r1 (25) */ + NID_sect409k1, /* sect409k1 (11) */ + NID_sect409r1, /* sect409r1 (12) */ + NID_secp384r1, /* secp384r1 (24) */ + NID_sect283k1, /* sect283k1 (9) */ + NID_sect283r1, /* sect283r1 (10) */ + NID_secp256k1, /* secp256k1 (22) */ + NID_X9_62_prime256v1, /* secp256r1 (23) */ + NID_sect239k1, /* sect239k1 (8) */ + NID_sect233k1, /* sect233k1 (6) */ + NID_sect233r1, /* sect233r1 (7) */ + NID_secp224k1, /* secp224k1 (20) */ + NID_secp224r1, /* secp224r1 (21) */ + NID_sect193r1, /* sect193r1 (4) */ + NID_sect193r2, /* sect193r2 (5) */ + NID_secp192k1, /* secp192k1 (18) */ + NID_X9_62_prime192v1, /* secp192r1 (19) */ + NID_sect163k1, /* sect163k1 (1) */ + NID_sect163r1, /* sect163r1 (2) */ + NID_sect163r2, /* sect163r2 (3) */ + NID_secp160k1, /* secp160k1 (15) */ + NID_secp160r1, /* secp160r1 (16) */ + NID_secp160r2, /* secp160r2 (17) */ + }; + int tls1_ec_curve_id2nid(int curve_id) { /* ECC curves from draft-ietf-tls-ecc-12.txt (Oct. 17, 2005) */ @@ -270,6 +302,56 @@ int tls1_ec_nid2curve_id(int nid) #endif /* OPENSSL_NO_EC */ #ifndef OPENSSL_NO_TLSEXT + +/* List of supported signature algorithms and hashes. Should make this + * customisable at some point, for now include everything we support. + */ + +#ifdef OPENSSL_NO_RSA +#define tlsext_sigalg_rsa(md) /* */ +#else +#define tlsext_sigalg_rsa(md) md, TLSEXT_signature_rsa, +#endif + +#ifdef OPENSSL_NO_DSA +#define tlsext_sigalg_dsa(md) /* */ +#else +#define tlsext_sigalg_dsa(md) md, TLSEXT_signature_dsa, +#endif + +#ifdef OPENSSL_NO_ECDSA +#define tlsext_sigalg_ecdsa(md) /* */ +#else +#define tlsext_sigalg_ecdsa(md) md, TLSEXT_signature_ecdsa, +#endif + +#define tlsext_sigalg(md) \ + tlsext_sigalg_rsa(md) \ + tlsext_sigalg_dsa(md) \ + tlsext_sigalg_ecdsa(md) + +static unsigned char tls12_sigalgs[] = { +#ifndef OPENSSL_NO_SHA512 + tlsext_sigalg(TLSEXT_hash_sha512) + tlsext_sigalg(TLSEXT_hash_sha384) +#endif +#ifndef OPENSSL_NO_SHA256 + tlsext_sigalg(TLSEXT_hash_sha256) + tlsext_sigalg(TLSEXT_hash_sha224) +#endif +#ifndef OPENSSL_NO_SHA + tlsext_sigalg(TLSEXT_hash_sha1) +#endif +}; + +int tls12_get_req_sig_algs(SSL *s, unsigned char *p) + { + size_t slen = sizeof(tls12_sigalgs); + if (p) + memcpy(p, tls12_sigalgs, slen); + return (int)slen; + } + unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *p, unsigned char *limit) { int extdatalen=0; @@ -317,7 +399,7 @@ unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *p, unsigned cha } /* Add RI if renegotiating */ - if (s->new_session) + if (s->renegotiate) { int el; @@ -341,6 +423,34 @@ unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *p, unsigned cha ret += el; } +#ifndef OPENSSL_NO_SRP + /* 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 = 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) login_len; + memcpy(ret, s->srp_ctx.login, login_len); + ret+=login_len; + } +#endif + #ifndef OPENSSL_NO_EC if (s->tlsext_ecpointformatlist != NULL && s->version != DTLS1_VERSION) @@ -426,6 +536,17 @@ 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 ((size_t)(limit - ret) < sizeof(tls12_sigalgs) + 6) + return NULL; + s2n(TLSEXT_TYPE_signature_algorithms,ret); + s2n(sizeof(tls12_sigalgs) + 2, ret); + s2n(sizeof(tls12_sigalgs), ret); + memcpy(ret, tls12_sigalgs, sizeof(tls12_sigalgs)); + ret += sizeof(tls12_sigalgs); + } + #ifdef TLSEXT_TYPE_opaque_prf_input if (s->s3->client_opaque_prf_input != NULL && s->version != DTLS1_VERSION) @@ -494,6 +615,20 @@ unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *p, unsigned cha i2d_X509_EXTENSIONS(s->tlsext_ocsp_exts, &ret); } +#ifndef OPENSSL_NO_HEARTBEATS + /* Add Heartbeat extension */ + s2n(TLSEXT_TYPE_heartbeat,ret); + s2n(1,ret); + /* Set mode: + * 1: peer may send requests + * 2: peer not allowed to send requests + */ + if (s->tlsext_heartbeat & SSL_TLSEXT_HB_DONT_RECV_REQUESTS) + *(ret++) = SSL_TLSEXT_HB_DONT_SEND_REQUESTS; + else + *(ret++) = SSL_TLSEXT_HB_ENABLED; +#endif + #ifndef OPENSSL_NO_NEXTPROTONEG if (s->ctx->next_proto_select_cb && !s->s3->tmp.finish_md_len) { @@ -506,6 +641,79 @@ unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *p, unsigned cha } #endif + if (s->tlsext_channel_id_enabled) + { + /* The client advertises an emtpy extension to indicate its + * support for Channel ID. */ + if (limit - ret - 4 < 0) + return NULL; + s2n(TLSEXT_TYPE_channel_id,ret); + s2n(0,ret); + } + + 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; + } + +#ifndef OPENSSL_NO_SRTP + if(SSL_get_srtp_profiles(s)) + { + int el; + + ssl_add_clienthello_use_srtp_ext(s, 0, &el, 0); + + if((limit - p - 4 - el) < 0) return NULL; + + s2n(TLSEXT_TYPE_use_srtp,ret); + s2n(el,ret); + + if(ssl_add_clienthello_use_srtp_ext(s, ret, &el, el)) + { + SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR); + return NULL; + } + 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; @@ -618,6 +826,28 @@ unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *p, unsigned cha ret += sol; } #endif + +#ifndef OPENSSL_NO_SRTP + if(s->srtp_profile) + { + int el; + + ssl_add_serverhello_use_srtp_ext(s, 0, &el, 0); + + if((limit - p - 4 - el) < 0) return NULL; + + s2n(TLSEXT_TYPE_use_srtp,ret); + s2n(el,ret); + + if(ssl_add_serverhello_use_srtp_ext(s, ret, &el, el)) + { + SSLerr(SSL_F_SSL_ADD_SERVERHELLO_TLSEXT, ERR_R_INTERNAL_ERROR); + return NULL; + } + 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)) { const unsigned char cryptopro_ext[36] = { @@ -633,6 +863,24 @@ unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *p, unsigned cha } +#ifndef OPENSSL_NO_HEARTBEATS + /* Add Heartbeat extension if we've received one */ + if (s->tlsext_heartbeat & SSL_TLSEXT_HB_ENABLED) + { + s2n(TLSEXT_TYPE_heartbeat,ret); + s2n(1,ret); + /* Set mode: + * 1: peer may send requests + * 2: peer not allowed to send requests + */ + if (s->tlsext_heartbeat & SSL_TLSEXT_HB_DONT_RECV_REQUESTS) + *(ret++) = SSL_TLSEXT_HB_DONT_SEND_REQUESTS; + else + *(ret++) = SSL_TLSEXT_HB_ENABLED; + + } +#endif + #ifndef OPENSSL_NO_NEXTPROTONEG next_proto_neg_seen = s->s3->next_proto_neg_seen; s->s3->next_proto_neg_seen = 0; @@ -655,6 +903,31 @@ unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *p, unsigned cha } #endif + /* If the client advertised support for Channel ID, and we have it + * enabled, then we want to echo it back. */ + if (s->s3->tlsext_channel_id_valid) + { + if (limit - ret - 4 < 0) + return NULL; + s2n(TLSEXT_TYPE_channel_id,ret); + s2n(0,ret); + } + + 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; @@ -662,6 +935,159 @@ 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 */ + +/* 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; + } + int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, int n, int *al) { unsigned short type; @@ -669,10 +1095,37 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in unsigned short len; unsigned char *data = *p; int renegotiate_seen = 0; + int sigalg_seen = 0; s->servername_done = 0; s->tlsext_status_type = -1; + /* Reset TLS 1.2 digest functions to defaults because they don't carry + * over to a renegotiation. */ + s->s3->digest_rsa = NULL; + s->s3->digest_dsa = NULL; + s->s3->digest_ecdsa = NULL; + +#ifndef OPENSSL_NO_NEXTPROTONEG + 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 */ + if (data >= (d+n-2)) goto ri_check; n2s(data,len); @@ -799,6 +1252,31 @@ 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 || ((len = data[0])) != (size -1)) + { + *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 #ifndef OPENSSL_NO_EC else if (type == TLSEXT_TYPE_ec_point_formats && @@ -843,7 +1321,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; @@ -919,8 +1398,26 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in return 0; renegotiate_seen = 1; } + else if (type == TLSEXT_TYPE_signature_algorithms) + { + int dsize; + if (sigalg_seen || size < 2) + { + *al = SSL_AD_DECODE_ERROR; + return 0; + } + sigalg_seen = 1; + n2s(data,dsize); + size -= 2; + if (dsize != size || dsize & 1) + { + *al = SSL_AD_DECODE_ERROR; + return 0; + } + tls1_process_sigalgs(s, data, dsize); + } else if (type == TLSEXT_TYPE_status_request && - s->version != DTLS1_VERSION && s->ctx->tlsext_status_cb) + s->version != DTLS1_VERSION) { if (size < 5) @@ -1008,6 +1505,12 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in sdata = data; if (dsize > 0) { + if (s->tlsext_ocsp_exts) + { + sk_X509_EXTENSION_pop_free(s->tlsext_ocsp_exts, + X509_EXTENSION_free); + } + s->tlsext_ocsp_exts = d2i_X509_EXTENSIONS(NULL, &sdata, dsize); @@ -1025,9 +1528,27 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in else s->tlsext_status_type = -1; } +#ifndef OPENSSL_NO_HEARTBEATS + else if (type == TLSEXT_TYPE_heartbeat) + { + switch(data[0]) + { + case 0x01: /* Client allows us to send HB requests */ + s->tlsext_heartbeat |= SSL_TLSEXT_HB_ENABLED; + break; + case 0x02: /* Client doesn't accept HB requests */ + 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_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. @@ -1048,7 +1569,29 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in } #endif + else if (type == TLSEXT_TYPE_channel_id && s->tlsext_channel_id_enabled) + s->s3->tlsext_channel_id_valid = 1; + + 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; + /* ALPN takes precedence over NPN. */ + s->s3->next_proto_neg_seen = 0; + } + /* 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; } @@ -1058,7 +1601,7 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in /* Need RI if renegotiating */ - if (!renegotiate_seen && s->new_session && + if (!renegotiate_seen && s->renegotiate && !(s->options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION)) { *al = SSL_AD_HANDSHAKE_FAILURE; @@ -1074,7 +1617,7 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in /* ssl_next_proto_validate validates a Next Protocol Negotiation block. No * elements of zero length are allowed and the set of elements must exactly fill * the length of the block. */ -static int ssl_next_proto_validate(unsigned char *d, unsigned len) +static char ssl_next_proto_validate(unsigned char *d, unsigned len) { unsigned int off = 0; @@ -1099,6 +1642,21 @@ int ssl_parse_serverhello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in int tlsext_servername = 0; int renegotiate_seen = 0; +#ifndef OPENSSL_NO_NEXTPROTONEG + 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 + if (data >= (d+n-2)) goto ri_check; @@ -1138,7 +1696,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; @@ -1225,13 +1784,14 @@ int ssl_parse_serverhello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in s->tlsext_status_expected = 1; } #ifndef OPENSSL_NO_NEXTPROTONEG - else if (type == TLSEXT_TYPE_next_proto_neg) + else if (type == TLSEXT_TYPE_next_proto_neg && + s->s3->tmp.finish_md_len == 0) { unsigned char *selected; 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; @@ -1255,14 +1815,89 @@ int ssl_parse_serverhello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in } 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_channel_id) + s->s3->tlsext_channel_id_valid = 1; + + 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)) return 0; renegotiate_seen = 1; } +#ifndef OPENSSL_NO_HEARTBEATS + else if (type == TLSEXT_TYPE_heartbeat) + { + switch(data[0]) + { + case 0x01: /* Server allows us to send HB requests */ + s->tlsext_heartbeat |= SSL_TLSEXT_HB_ENABLED; + break; + case 0x02: /* Server doesn't accept HB requests */ + 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; } @@ -1342,7 +1977,7 @@ int ssl_prepare_clienthello_tlsext(SSL *s) break; } } - using_ecc = using_ecc && (s->version == TLS1_VERSION); + using_ecc = using_ecc && (s->version >= TLS1_VERSION); if (using_ecc) { if (s->tlsext_ecpointformatlist != NULL) OPENSSL_free(s->tlsext_ecpointformatlist); @@ -1358,16 +1993,19 @@ int ssl_prepare_clienthello_tlsext(SSL *s) /* we support all named elliptic curves in draft-ietf-tls-ecc-12 */ if (s->tlsext_ellipticcurvelist != NULL) OPENSSL_free(s->tlsext_ellipticcurvelist); - s->tlsext_ellipticcurvelist_length = sizeof(nid_list)/sizeof(nid_list[0]) * 2; + s->tlsext_ellipticcurvelist_length = sizeof(pref_list)/sizeof(pref_list[0]) * 2; if ((s->tlsext_ellipticcurvelist = OPENSSL_malloc(s->tlsext_ellipticcurvelist_length)) == NULL) { s->tlsext_ellipticcurvelist_length = 0; SSLerr(SSL_F_SSL_PREPARE_CLIENTHELLO_TLSEXT,ERR_R_MALLOC_FAILURE); return -1; } - for (i = 1, j = s->tlsext_ellipticcurvelist; (unsigned int)i <= - sizeof(nid_list)/sizeof(nid_list[0]); i++) - s2n(i,j); + for (i = 0, j = s->tlsext_ellipticcurvelist; (unsigned int)i < + sizeof(pref_list)/sizeof(pref_list[0]); i++) + { + int id = tls1_ec_nid2curve_id(pref_list[i]); + s2n(id,j); + } } #endif /* OPENSSL_NO_EC */ @@ -1439,7 +2077,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; @@ -1458,42 +2096,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; @@ -1545,8 +2153,8 @@ int ssl_check_clienthello_tlsext(SSL *s) } } -#endif err: +#endif switch (ret) { case SSL_TLSEXT_ERR_ALERT_FATAL: @@ -1564,6 +2172,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; @@ -1676,26 +2349,56 @@ int ssl_check_serverhello_tlsext(SSL *s) } } -/* Since the server cache lookup is done early on in the processing of client - * hello and other operations depend on the result we need to handle any TLS - * session ticket extension at the same time. +/* Since the server cache lookup is done early on in the processing of the + * ClientHello, and other operations depend on the result, we need to handle + * any TLS session ticket extension at the same time. + * + * session_id: points at the session ID in the ClientHello. This code will + * read past the end of this in order to parse out the session ticket + * extension, if any. + * len: the length of the session ID. + * limit: a pointer to the first byte after the ClientHello. + * ret: (output) on return, if a ticket was decrypted, then this is set to + * point to the resulting session. + * + * If s->tls_session_secret_cb is set then we are expecting a pre-shared key + * ciphersuite, in which case we have no use for session tickets and one will + * never be decrypted, nor will s->tlsext_ticket_expected be set to 1. + * + * Returns: + * -1: fatal error, either from parsing or decrypting the ticket. + * 0: no ticket was found (or was ignored, based on settings). + * 1: a zero length extension was found, indicating that the client supports + * session tickets but doesn't currently have one to offer. + * 2: either s->tls_session_secret_cb was set, or a ticket was offered but + * couldn't be decrypted because of a non-fatal error. + * 3: a ticket was successfully decrypted and *ret was set. + * + * Side effects: + * Sets s->tlsext_ticket_expected to 1 if the server will have to issue + * a new session ticket to the client because the client indicated support + * (and s->tls_session_secret_cb is NULL) but the client either doesn't have + * a session ticket or we couldn't use the one it gave us, or if + * s->ctx->tlsext_ticket_key_cb asked to renew the client's ticket. + * Otherwise, s->tlsext_ticket_expected is set to 0. */ - int tls1_process_ticket(SSL *s, unsigned char *session_id, int len, - const unsigned char *limit, SSL_SESSION **ret) + const unsigned char *limit, SSL_SESSION **ret) { /* Point after session ID in client hello */ const unsigned char *p = session_id + len; unsigned short i; + *ret = NULL; + s->tlsext_ticket_expected = 0; + /* If tickets disabled behave as if no ticket present - * to permit stateful resumption. - */ + * to permit stateful resumption. + */ if (SSL_get_options(s) & SSL_OP_NO_TICKET) - return 1; - + return 0; if ((s->version <= SSL3_VERSION) || !limit) - return 1; + return 0; if (p >= limit) return -1; /* Skip past DTLS cookie */ @@ -1718,7 +2421,7 @@ int tls1_process_ticket(SSL *s, unsigned char *session_id, int len, return -1; /* Now at start of extensions */ if ((p + 2) >= limit) - return 1; + return 0; n2s(p, i); while ((p + 4) <= limit) { @@ -1726,39 +2429,61 @@ int tls1_process_ticket(SSL *s, unsigned char *session_id, int len, n2s(p, type); n2s(p, size); if (p + size > limit) - return 1; + return 0; if (type == TLSEXT_TYPE_session_ticket) { - /* If tickets disabled indicate cache miss which will - * trigger a full handshake - */ - if (SSL_get_options(s) & SSL_OP_NO_TICKET) - return 1; - /* If zero length note client will accept a ticket - * and indicate cache miss to trigger full handshake - */ + int r; if (size == 0) { + /* The client will accept a ticket but doesn't + * currently have one. */ s->tlsext_ticket_expected = 1; - return 0; /* Cache miss */ + return 1; } if (s->tls_session_secret_cb) { - /* Indicate cache miss here and instead of - * generating the session from ticket now, - * trigger abbreviated handshake based on - * external mechanism to calculate the master - * secret later. */ - return 0; + /* Indicate that the ticket couldn't be + * decrypted rather than generating the session + * from ticket now, trigger abbreviated + * handshake based on external mechanism to + * calculate the master secret later. */ + return 2; + } + r = tls_decrypt_ticket(s, p, size, session_id, len, ret); + switch (r) + { + case 2: /* ticket couldn't be decrypted */ + s->tlsext_ticket_expected = 1; + return 2; + case 3: /* ticket was decrypted */ + return r; + case 4: /* ticket decrypted but need to renew */ + s->tlsext_ticket_expected = 1; + return 3; + default: /* fatal error */ + return -1; } - return tls_decrypt_ticket(s, p, size, session_id, len, - ret); } p += size; } - return 1; + return 0; } +/* tls_decrypt_ticket attempts to decrypt a session ticket. + * + * etick: points to the body of the session ticket extension. + * eticklen: the length of the session tickets extenion. + * sess_id: points at the session ID. + * sesslen: the length of the session ID. + * psess: (output) on return, if a ticket was decrypted, then this is set to + * point to the resulting session. + * + * Returns: + * -1: fatal error, either from parsing or decrypting the ticket. + * 2: the ticket couldn't be decrypted. + * 3: a ticket was successfully decrypted and *psess was set. + * 4: same as 3, but the ticket needs to be renewed. + */ static int tls_decrypt_ticket(SSL *s, const unsigned char *etick, int eticklen, const unsigned char *sess_id, int sesslen, SSL_SESSION **psess) @@ -1773,7 +2498,7 @@ static int tls_decrypt_ticket(SSL *s, const unsigned char *etick, int eticklen, SSL_CTX *tctx = s->initial_ctx; /* Need at least keyname + iv + some encrypted data */ if (eticklen < 48) - goto tickerr; + return 2; /* Initialize session ticket encryption and HMAC contexts */ HMAC_CTX_init(&hctx); EVP_CIPHER_CTX_init(&ctx); @@ -1785,7 +2510,7 @@ static int tls_decrypt_ticket(SSL *s, const unsigned char *etick, int eticklen, if (rv < 0) return -1; if (rv == 0) - goto tickerr; + return 2; if (rv == 2) renew_ticket = 1; } @@ -1793,15 +2518,15 @@ static int tls_decrypt_ticket(SSL *s, const unsigned char *etick, int eticklen, { /* Check key name matches */ if (memcmp(etick, tctx->tlsext_tick_key_name, 16)) - goto tickerr; + return 2; HMAC_Init_ex(&hctx, tctx->tlsext_tick_hmac_key, 16, tlsext_tick_md(), NULL); EVP_DecryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL, tctx->tlsext_tick_aes_key, etick + 16); } /* Attempt to process session ticket, first conduct sanity and - * integrity checks on ticket. - */ + * integrity checks on ticket. + */ mlen = HMAC_size(&hctx); if (mlen < 0) { @@ -1813,8 +2538,8 @@ 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)) - goto tickerr; + 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 */ p = etick + 16 + EVP_CIPHER_CTX_iv_length(&ctx); @@ -1827,33 +2552,373 @@ 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) - goto tickerr; + return 2; slen += mlen; EVP_CIPHER_CTX_cleanup(&ctx); p = sdec; - + sess = d2i_SSL_SESSION(NULL, &p, slen); OPENSSL_free(sdec); if (sess) { - /* The session ID if non-empty is used by some clients to - * detect that the ticket has been accepted. So we copy it to - * the session structure. If it is empty set length to zero - * as required by standard. - */ + /* The session ID, if non-empty, is used by some clients to + * detect that the ticket has been accepted. So we copy it to + * the session structure. If it is empty set length to zero + * as required by standard. + */ if (sesslen) memcpy(sess->session_id, sess_id, sesslen); sess->session_id_length = sesslen; *psess = sess; - s->tlsext_ticket_expected = renew_ticket; - return 1; + if (renew_ticket) + return 4; + else + return 3; } - /* If session decrypt failure indicate a cache miss and set state to - * send a new ticket - */ - tickerr: - s->tlsext_ticket_expected = 1; + ERR_clear_error(); + /* For session parse failure, indicate that we need to send a new + * ticket. */ + return 2; + } + +/* Tables to translate from NIDs to TLS v1.2 ids */ + +typedef struct + { + int nid; + int id; + } tls12_lookup; + +static tls12_lookup tls12_md[] = { +#ifndef OPENSSL_NO_MD5 + {NID_md5, TLSEXT_hash_md5}, +#endif +#ifndef OPENSSL_NO_SHA + {NID_sha1, TLSEXT_hash_sha1}, +#endif +#ifndef OPENSSL_NO_SHA256 + {NID_sha224, TLSEXT_hash_sha224}, + {NID_sha256, TLSEXT_hash_sha256}, +#endif +#ifndef OPENSSL_NO_SHA512 + {NID_sha384, TLSEXT_hash_sha384}, + {NID_sha512, TLSEXT_hash_sha512} +#endif +}; + +static tls12_lookup tls12_sig[] = { +#ifndef OPENSSL_NO_RSA + {EVP_PKEY_RSA, TLSEXT_signature_rsa}, +#endif +#ifndef OPENSSL_NO_DSA + {EVP_PKEY_DSA, TLSEXT_signature_dsa}, +#endif +#ifndef OPENSSL_NO_ECDSA + {EVP_PKEY_EC, TLSEXT_signature_ecdsa} +#endif +}; + +static int tls12_find_id(int nid, tls12_lookup *table, size_t tlen) + { + size_t i; + for (i = 0; i < tlen; i++) + { + if (table[i].nid == nid) + return table[i].id; + } + return -1; + } + +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) + return 0; + sig_id = tls12_get_sigid(pk); + if (sig_id == -1) + return 0; + p[0] = (unsigned char)md_id; + p[1] = (unsigned char)sig_id; + return 1; + } + +/* tls12_get_sigid returns the TLS 1.2 SignatureAlgorithm value corresponding + * to the given public key, or -1 if not known. */ +int tls12_get_sigid(const EVP_PKEY *pk) + { + return tls12_find_id(pk->type, tls12_sig, + sizeof(tls12_sig)/sizeof(tls12_lookup)); + } + +const EVP_MD *tls12_get_hash(unsigned char hash_alg) + { + switch(hash_alg) + { +#ifndef OPENSSL_NO_SHA + case TLSEXT_hash_sha1: + return EVP_sha1(); +#endif +#ifndef OPENSSL_NO_SHA256 + case TLSEXT_hash_sha224: + return EVP_sha224(); + + case TLSEXT_hash_sha256: + return EVP_sha256(); +#endif +#ifndef OPENSSL_NO_SHA512 + case TLSEXT_hash_sha384: + return EVP_sha384(); + + case TLSEXT_hash_sha512: + return EVP_sha512(); +#endif + default: + return NULL; + + } + } + +/* tls1_process_sigalgs processes a signature_algorithms extension and sets the + * digest functions accordingly for each key type. + * + * See RFC 5246, section 7.4.1.4.1. + * + * data: points to the content of the extension, not including type and length + * headers. + * dsize: the number of bytes of |data|. Must be even. + */ +void tls1_process_sigalgs(SSL *s, const unsigned char *data, int dsize) + { + int i; + const EVP_MD *md, **digest_ptr; + /* Extension ignored for TLS versions below 1.2 */ + if (TLS1_get_version(s) < TLS1_2_VERSION) + return; + + s->s3->digest_rsa = NULL; + s->s3->digest_dsa = NULL; + s->s3->digest_ecdsa = NULL; + + for (i = 0; i < dsize; i += 2) + { + unsigned char hash_alg = data[i], sig_alg = data[i+1]; + + switch(sig_alg) + { +#ifndef OPENSSL_NO_RSA + case TLSEXT_signature_rsa: + digest_ptr = &s->s3->digest_rsa; + break; +#endif +#ifndef OPENSSL_NO_DSA + case TLSEXT_signature_dsa: + digest_ptr = &s->s3->digest_dsa; + break; +#endif +#ifndef OPENSSL_NO_ECDSA + case TLSEXT_signature_ecdsa: + digest_ptr = &s->s3->digest_ecdsa; + break; +#endif + default: + continue; + } + + if (*digest_ptr == NULL) + { + md = tls12_get_hash(hash_alg); + if (md) + *digest_ptr = md; + } + + } + } + +#endif + +#ifndef OPENSSL_NO_HEARTBEATS +int +tls1_process_heartbeat(SSL *s) + { + unsigned char *p = &s->s3->rrec.data[0], *pl; + unsigned short hbtype; + unsigned int payload; + unsigned int padding = 16; /* Use minimum padding */ + + 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; + int r; + + /* Allocate memory for the response, size is 1 bytes + * message type, plus 2 bytes payload length, plus + * payload, plus padding + */ + buffer = OPENSSL_malloc(1 + 2 + payload + padding); + bp = buffer; + + /* Enter response type, length and copy payload */ + *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) + s->msg_callback(1, s->version, TLS1_RT_HEARTBEAT, + buffer, 3 + payload + padding, + s, s->msg_callback_arg); + + OPENSSL_free(buffer); + + if (r < 0) + return r; + } + else if (hbtype == TLS1_HB_RESPONSE) + { + unsigned int seq; + + /* We only send sequence numbers (2 bytes unsigned int), + * and 16 random bytes, so we just try to read the + * sequence number */ + n2s(pl, seq); + + if (payload == 18 && seq == s->tlsext_hb_seq) + { + s->tlsext_hb_seq++; + s->tlsext_hb_pending = 0; + } + } + return 0; } +int +tls1_heartbeat(SSL *s) + { + unsigned char *buf, *p; + int ret; + unsigned int payload = 18; /* Sequence number + random bytes */ + unsigned int padding = 16; /* Use minimum padding */ + + /* Only send if peer supports and accepts HB requests... */ + if (!(s->tlsext_heartbeat & SSL_TLSEXT_HB_ENABLED) || + s->tlsext_heartbeat & SSL_TLSEXT_HB_DONT_SEND_REQUESTS) + { + SSLerr(SSL_F_TLS1_HEARTBEAT,SSL_R_TLS_HEARTBEAT_PEER_DOESNT_ACCEPT); + return -1; + } + + /* ...and there is none in flight yet... */ + if (s->tlsext_hb_pending) + { + SSLerr(SSL_F_TLS1_HEARTBEAT,SSL_R_TLS_HEARTBEAT_PENDING); + return -1; + } + + /* ...and no handshake in progress. */ + if (SSL_in_init(s) || s->in_handshake) + { + SSLerr(SSL_F_TLS1_HEARTBEAT,SSL_R_UNEXPECTED_MESSAGE); + return -1; + } + + /* Check if padding is too long, payload and padding + * must not exceed 2^14 - 3 = 16381 bytes in total. + */ + OPENSSL_assert(payload + padding <= 16381); + + /* Create HeartBeat message, we just use a sequence number + * as payload to distuingish different messages and add + * some random stuff. + * - Message Type, 1 byte + * - Payload Length, 2 bytes (unsigned int) + * - Payload, the sequence number (2 bytes uint) + * - Payload, random bytes (16 bytes uint) + * - Padding + */ + buf = OPENSSL_malloc(1 + 2 + payload + padding); + p = buf; + /* Message Type */ + *p++ = TLS1_HB_REQUEST; + /* Payload length (18 bytes here) */ + s2n(payload, p); + /* Sequence number */ + s2n(s->tlsext_hb_seq, p); + /* 16 random bytes */ + RAND_pseudo_bytes(p, 16); + p += 16; + /* Random padding */ + RAND_pseudo_bytes(p, padding); + + ret = ssl3_write_bytes(s, TLS1_RT_HEARTBEAT, buf, 3 + payload + padding); + if (ret >= 0) + { + if (s->msg_callback) + s->msg_callback(1, s->version, TLS1_RT_HEARTBEAT, + buf, 3 + payload + padding, + s, s->msg_callback_arg); + + s->tlsext_hb_pending = 1; + } + + OPENSSL_free(buf); + + return ret; + } +#endif + +#if !defined(OPENSSL_NO_TLSEXT) +/* tls1_channel_id_hash calculates the signed data for a Channel ID on the given + * SSL connection and writes it to |md|. + */ +int +tls1_channel_id_hash(EVP_MD_CTX *md, SSL *s) + { + EVP_MD_CTX ctx; + unsigned char temp_digest[EVP_MAX_MD_SIZE]; + unsigned temp_digest_len; + int i; + static const char kClientIDMagic[] = "TLS Channel ID signature"; + + if (s->s3->handshake_buffer) + if (!ssl3_digest_cached_records(s)) + return 0; + + EVP_DigestUpdate(md, kClientIDMagic, sizeof(kClientIDMagic)); + + EVP_MD_CTX_init(&ctx); + for (i = 0; i < SSL_MAX_DIGEST; i++) + { + if (s->s3->handshake_dgst[i] == NULL) + continue; + EVP_MD_CTX_copy_ex(&ctx, s->s3->handshake_dgst[i]); + EVP_DigestFinal_ex(&ctx, temp_digest, &temp_digest_len); + EVP_DigestUpdate(md, temp_digest, temp_digest_len); + } + EVP_MD_CTX_cleanup(&ctx); + + return 1; + } #endif |