X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=blobdiff_plain;f=ssl%2Ft1_lib.c;h=2161d155e87f0fedd16ece298816d60620a6d76d;hp=3aa01db7e57e20c0f503c989acaa60639f2afe53;hb=b7aacc3ac33c9c239e8187a3ad595afb8e49ce79;hpb=062178678f5374b09f00d70796f6e692e8775aca diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c index 3aa01db7e5..2161d155e8 100644 --- a/ssl/t1_lib.c +++ b/ssl/t1_lib.c @@ -120,6 +120,9 @@ # include #endif #include "ssl_locl.h" +#ifndef OPENSSL_NO_CT +# include +#endif static int tls_decrypt_ticket(SSL *s, const unsigned char *tick, int ticklen, const unsigned char *sess_id, int sesslen, @@ -230,10 +233,9 @@ typedef struct { /* * Table of curve information. - * NB: do not delete entries or reorder this array. It is used as a lookup + * Do not delete entries or reorder this array! It is used as a lookup * table: the index of each entry is one less than the TLS curve id. */ - static const tls_curve_info nid_list[] = { {NID_sect163k1, 80, TLS_CURVE_CHAR2}, /* sect163k1 (1) */ {NID_sect163r1, 80, TLS_CURVE_CHAR2}, /* sect163r1 (2) */ @@ -276,46 +278,31 @@ static const unsigned char ecformats_default[] = { /* The default curves */ static const unsigned char eccurves_default[] = { 0, 29, /* X25519 (29) */ - /* Prefer P-256 which has the fastest and most secure implementations. */ 0, 23, /* secp256r1 (23) */ - /* Other >= 256-bit prime curves. */ 0, 25, /* secp521r1 (25) */ - 0, 28, /* brainpool512r1 (28) */ - 0, 27, /* brainpoolP384r1 (27) */ 0, 24, /* secp384r1 (24) */ - 0, 26, /* brainpoolP256r1 (26) */ - 0, 22, /* secp256k1 (22) */ - /* >= 256-bit binary curves. */ - 0, 14, /* sect571r1 (14) */ - 0, 13, /* sect571k1 (13) */ - 0, 11, /* sect409k1 (11) */ - 0, 12, /* sect409r1 (12) */ - 0, 9, /* sect283k1 (9) */ - 0, 10, /* sect283r1 (10) */ }; static const unsigned char eccurves_all[] = { 0, 29, /* X25519 (29) */ - /* Prefer P-256 which has the fastest and most secure implementations. */ 0, 23, /* secp256r1 (23) */ - /* Other >= 256-bit prime curves. */ 0, 25, /* secp521r1 (25) */ - 0, 28, /* brainpool512r1 (28) */ - 0, 27, /* brainpoolP384r1 (27) */ 0, 24, /* secp384r1 (24) */ 0, 26, /* brainpoolP256r1 (26) */ + 0, 27, /* brainpoolP384r1 (27) */ + 0, 28, /* brainpool512r1 (28) */ + + /* + * Remaining curves disabled by default but still permitted if set + * via an explicit callback or parameters. + */ 0, 22, /* secp256k1 (22) */ - /* >= 256-bit binary curves. */ 0, 14, /* sect571r1 (14) */ 0, 13, /* sect571k1 (13) */ 0, 11, /* sect409k1 (11) */ 0, 12, /* sect409r1 (12) */ 0, 9, /* sect283k1 (9) */ 0, 10, /* sect283r1 (10) */ - /* - * Remaining curves disabled by default but still permitted if set - * via an explicit callback or parameters. - */ 0, 20, /* secp224k1 (20) */ 0, 21, /* secp224r1 (21) */ 0, 18, /* secp192k1 (18) */ @@ -1426,6 +1413,11 @@ unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *buf, } #endif + /* + * finish_md_len is non-zero during a renegotiation, so + * this avoids sending ALPN during the renegotiation + * (see longer comment below) + */ 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; @@ -1434,6 +1426,7 @@ unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *buf, 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; + s->s3->alpn_sent = 1; } #ifndef OPENSSL_NO_SRTP if (SSL_IS_DTLS(s) && SSL_get_srtp_profiles(s)) { @@ -1465,6 +1458,12 @@ unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *buf, #ifdef TLSEXT_TYPE_encrypt_then_mac s2n(TLSEXT_TYPE_encrypt_then_mac, ret); s2n(0, ret); +#endif +#ifndef OPENSSL_NO_CT + if (s->ct_validation_callback != NULL) { + s2n(TLSEXT_TYPE_signed_certificate_timestamp, ret); + s2n(0, ret); + } #endif s2n(TLSEXT_TYPE_extended_master_secret, ret); s2n(0, ret); @@ -1708,9 +1707,9 @@ unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *buf, s2n(0, ret); } - if (s->s3->alpn_selected) { + if (s->s3->alpn_selected != NULL) { const unsigned char *selected = s->s3->alpn_selected; - unsigned len = s->s3->alpn_selected_len; + unsigned int len = s->s3->alpn_selected_len; if ((long)(limit - ret - 4 - 2 - 1 - len) < 0) return NULL; @@ -1732,16 +1731,13 @@ unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *buf, } /* - * Process the ALPN extension in a ClientHello. + * Save the ALPN extension in a ClientHello. * pkt: the contents of the ALPN extension, not including type and length. * al: a pointer to the alert value to send in the event of a failure. * returns: 1 on success, 0 on error. */ static int tls1_alpn_handle_client_hello(SSL *s, PACKET *pkt, int *al) { - const unsigned char *selected; - unsigned char selected_len; - int r; PACKET protocol_list, save_protocol_list, protocol; *al = SSL_AD_DECODE_ERROR; @@ -1760,25 +1756,47 @@ static int tls1_alpn_handle_client_hello(SSL *s, PACKET *pkt, int *al) } } while (PACKET_remaining(&protocol_list) != 0); - if (s->ctx->alpn_select_cb == NULL) - return 1; + if (!PACKET_memdup(&save_protocol_list, + &s->s3->alpn_proposed, + &s->s3->alpn_proposed_len)) { + *al = TLS1_AD_INTERNAL_ERROR; + return 0; + } + + return 1; +} + +/* + * Process the ALPN extension in a ClientHello. + * ret: a pointer to the TLSEXT return value: SSL_TLSEXT_ERR_* + * al: a pointer to the alert value to send in the event of a failure. + * returns 1 on success, 0 + */ +static int tls1_alpn_handle_client_hello_late(SSL *s, int *ret, int *al) +{ + const unsigned char *selected = NULL; + unsigned char selected_len = 0; - r = s->ctx->alpn_select_cb(s, &selected, &selected_len, - PACKET_data(&save_protocol_list), - PACKET_remaining(&save_protocol_list), - s->ctx->alpn_select_cb_arg); - if (r == SSL_TLSEXT_ERR_OK) { - OPENSSL_free(s->s3->alpn_selected); - s->s3->alpn_selected = OPENSSL_malloc(selected_len); - if (s->s3->alpn_selected == NULL) { - *al = SSL_AD_INTERNAL_ERROR; + if (s->ctx->alpn_select_cb != NULL && s->s3->alpn_proposed != NULL) { + int r = s->ctx->alpn_select_cb(s, &selected, &selected_len, + s->s3->alpn_proposed, + s->s3->alpn_proposed_len, + s->ctx->alpn_select_cb_arg); + + if (r == SSL_TLSEXT_ERR_OK) { + OPENSSL_free(s->s3->alpn_selected); + s->s3->alpn_selected = OPENSSL_memdup(selected, selected_len); + if (s->s3->alpn_selected == NULL) { + *al = SSL_AD_INTERNAL_ERROR; + *ret = SSL_TLSEXT_ERR_ALERT_FATAL; + return 0; + } + s->s3->alpn_selected_len = selected_len; + } else { + *al = SSL_AD_NO_APPLICATION_PROTOCOL; + *ret = SSL_TLSEXT_ERR_ALERT_FATAL; return 0; } - memcpy(s->s3->alpn_selected, selected, selected_len); - s->s3->alpn_selected_len = selected_len; - } else { - *al = SSL_AD_NO_APPLICATION_PROTOCOL; - return 0; } return 1; @@ -2430,6 +2448,30 @@ static int ssl_scan_serverhello_tlsext(SSL *s, PACKET *pkt, int *al) /* Set flag to expect CertificateStatus message */ s->tlsext_status_expected = 1; } +#ifndef OPENSSL_NO_CT + /* + * Only take it if we asked for it - i.e if there is no CT validation + * callback set, then a custom extension MAY be processing it, so we + * need to let control continue to flow to that. + */ + else if (type == TLSEXT_TYPE_signed_certificate_timestamp && + s->ct_validation_callback != NULL) { + /* Simply copy it off for later processing */ + if (s->tlsext_scts != NULL) { + OPENSSL_free(s->tlsext_scts); + s->tlsext_scts = NULL; + } + s->tlsext_scts_len = size; + if (size > 0) { + s->tlsext_scts = OPENSSL_malloc(size); + if (s->tlsext_scts == NULL) { + *al = TLS1_AD_INTERNAL_ERROR; + return 0; + } + memcpy(s->tlsext_scts, data, size); + } + } +#endif #ifndef OPENSSL_NO_NEXTPROTONEG else if (type == TLSEXT_TYPE_next_proto_neg && s->s3->tmp.finish_md_len == 0) { @@ -2467,7 +2509,7 @@ static int ssl_scan_serverhello_tlsext(SSL *s, PACKET *pkt, int *al) else if (type == TLSEXT_TYPE_application_layer_protocol_negotiation) { unsigned len; /* We must have requested it. */ - if (s->alpn_client_proto_list == NULL) { + if (!s->s3->alpn_sent) { *al = TLS1_AD_UNSUPPORTED_EXTENSION; return 0; } @@ -2600,7 +2642,7 @@ static int ssl_scan_serverhello_tlsext(SSL *s, PACKET *pkt, int *al) int ssl_prepare_clienthello_tlsext(SSL *s) { - + s->s3->alpn_sent = 0; return 1; } @@ -2759,6 +2801,10 @@ int ssl_check_clienthello_tlsext_late(SSL *s) } else s->tlsext_status_expected = 0; + if (!tls1_alpn_handle_client_hello_late(s, &ret, &al)) { + goto err; + } + err: switch (ret) { case SSL_TLSEXT_ERR_ALERT_FATAL: