X-Git-Url: https://git.openssl.org/?p=openssl.git;a=blobdiff_plain;f=ssl%2Ft1_lib.c;h=a4cd23ab3939fcd2ca4e39fa73006b3bb84f734a;hp=f068a2008a3bcaae90cc323e9ddfdae23bcbcbe2;hb=0aeddcfa61250a6c474c4f8b3533772a63192f1b;hpb=ddb4c0477af623fcad3e6709640729e82693a4c9 diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c index f068a2008a..a4cd23ab39 100644 --- a/ssl/t1_lib.c +++ b/ssl/t1_lib.c @@ -115,11 +115,10 @@ #include #include #include -#ifndef OPENSSL_NO_DH -# include -# include -#endif +#include +#include #include "ssl_locl.h" +#include static int tls_decrypt_ticket(SSL *s, const unsigned char *tick, int ticklen, const unsigned char *sess_id, int sesslen, @@ -979,24 +978,21 @@ int tls12_check_peer_sigalg(const EVP_MD **pmd, SSL *s, } /* - * 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 session and not global - * settings. + * Set a mask of disabled algorithms: an algorithm is disabled if it isn't + * supported, doesn't appear in supported signature algorithms, isn't supported + * by the enabled protocol versions or by the security level. + * + * This function should only be used for checking which ciphers are supported + * by the client. + * + * Call ssl_cipher_disabled() to check that it's enabled or not. */ void ssl_set_client_disabled(SSL *s) { s->s3->tmp.mask_a = 0; s->s3->tmp.mask_k = 0; - /* Don't allow TLS 1.2 only ciphers if we don't suppport them */ - if (!SSL_CLIENT_USE_TLS1_2_CIPHERS(s)) - s->s3->tmp.mask_ssl = SSL_TLSV1_2; - else - s->s3->tmp.mask_ssl = 0; - /* Disable TLS 1.0 ciphers if using SSL v3 */ - if (s->client_version == SSL3_VERSION) - s->s3->tmp.mask_ssl |= SSL_TLSV1; ssl_set_sig_mask(&s->s3->tmp.mask_a, s, SSL_SECOP_SIGALG_MASK); + ssl_get_client_min_max_version(s, &s->s3->tmp.min_ver, &s->s3->tmp.max_ver); # ifndef OPENSSL_NO_PSK /* with PSK there must be client callback set */ if (!s->psk_client_callback) { @@ -1012,12 +1008,28 @@ void ssl_set_client_disabled(SSL *s) #endif } +/* + * ssl_cipher_disabled - check that a cipher is disabled or not + * @s: SSL connection that you want to use the cipher on + * @c: cipher to check + * @op: Security check that you want to do + * + * Returns 1 when it's disabled, 0 when enabled. + */ int ssl_cipher_disabled(SSL *s, const SSL_CIPHER *c, int op) { - if (c->algorithm_ssl & s->s3->tmp.mask_ssl - || c->algorithm_mkey & s->s3->tmp.mask_k + if (c->algorithm_mkey & s->s3->tmp.mask_k || c->algorithm_auth & s->s3->tmp.mask_a) return 1; + if (s->s3->tmp.max_ver == 0) + return 1; + if (!SSL_IS_DTLS(s) && ((c->min_tls > s->s3->tmp.max_ver) + || (c->max_tls < s->s3->tmp.min_ver))) + return 1; + if (SSL_IS_DTLS(s) && (DTLS_VERSION_GT(c->min_dtls, s->s3->tmp.max_ver) + || DTLS_VERSION_LT(c->max_dtls, s->s3->tmp.min_ver))) + return 1; + return !ssl_security(s, op, c->strength_bits, 0, (void *)c); } @@ -1335,6 +1347,7 @@ unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *buf, ret += salglen; } +#ifndef OPENSSL_NO_OCSP if (s->tlsext_status_type == TLSEXT_STATUSTYPE_ocsp) { int i; long extlen, idlen, itmp; @@ -1378,6 +1391,7 @@ unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *buf, if (extlen > 0) i2d_X509_EXTENSIONS(s->tlsext_ocsp_exts, &ret); } +#endif #ifndef OPENSSL_NO_HEARTBEATS if (SSL_IS_DTLS(s)) { /* Add Heartbeat extension */ @@ -1410,6 +1424,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; @@ -1418,6 +1437,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)) { @@ -1449,6 +1469,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); @@ -1692,9 +1718,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; @@ -1716,16 +1742,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; @@ -1744,25 +1767,51 @@ 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; + + 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); - 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 (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; +#ifndef OPENSSL_NO_NEXTPROTONEG + /* ALPN takes precedence over NPN. */ + s->s3->next_proto_neg_seen = 0; +#endif + } 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; @@ -1859,6 +1908,10 @@ static int ssl_scan_clienthello_tlsext(SSL *s, PACKET *pkt, int *al) OPENSSL_free(s->s3->alpn_selected); s->s3->alpn_selected = NULL; + s->s3->alpn_selected_len = 0; + OPENSSL_free(s->s3->alpn_proposed); + s->s3->alpn_proposed = NULL; + s->s3->alpn_proposed_len = 0; #ifndef OPENSSL_NO_HEARTBEATS s->tlsext_heartbeat &= ~(SSL_DTLSEXT_HB_ENABLED | SSL_DTLSEXT_HB_DONT_SEND_REQUESTS); @@ -2077,14 +2130,14 @@ static int ssl_scan_clienthello_tlsext(SSL *s, PACKET *pkt, int *al) } } } else if (type == TLSEXT_TYPE_status_request) { - const unsigned char *ext_data; - if (!PACKET_get_1(&extension, (unsigned int *)&s->tlsext_status_type)) { return 0; } +#ifndef OPENSSL_NO_OCSP if (s->tlsext_status_type == TLSEXT_STATUSTYPE_ocsp) { + const unsigned char *ext_data; PACKET responder_id_list, exts; if (!PACKET_get_length_prefixed_2(&extension, &responder_id_list)) return 0; @@ -2141,10 +2194,12 @@ static int ssl_scan_clienthello_tlsext(SSL *s, PACKET *pkt, int *al) return 0; } } - /* - * We don't know what to do with any other type * so ignore it. - */ - } else { + } else +#endif + { + /* + * We don't know what to do with any other type so ignore it. + */ s->tlsext_status_type = -1; } } @@ -2173,8 +2228,7 @@ static int ssl_scan_clienthello_tlsext(SSL *s, PACKET *pkt, int *al) #endif #ifndef OPENSSL_NO_NEXTPROTONEG else if (type == TLSEXT_TYPE_next_proto_neg && - s->s3->tmp.finish_md_len == 0 && - s->s3->alpn_selected == NULL) { + s->s3->tmp.finish_md_len == 0) { /*- * We shouldn't accept this extension on a * renegotiation. @@ -2200,10 +2254,6 @@ static int ssl_scan_clienthello_tlsext(SSL *s, PACKET *pkt, int *al) s->s3->tmp.finish_md_len == 0) { if (!tls1_alpn_handle_client_hello(s, &extension, al)) return 0; -#ifndef OPENSSL_NO_NEXTPROTONEG - /* ALPN takes precedence over NPN. */ - s->s3->next_proto_neg_seen = 0; -#endif } /* session ticket processed earlier */ @@ -2414,6 +2464,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) { @@ -2451,7 +2525,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; } @@ -2584,7 +2658,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; } @@ -2743,6 +2817,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: @@ -3087,6 +3165,7 @@ static int tls_decrypt_ticket(SSL *s, const unsigned char *etick, if (sdec == NULL || EVP_DecryptUpdate(ctx, sdec, &slen, p, eticklen) <= 0) { EVP_CIPHER_CTX_free(ctx); + OPENSSL_free(sdec); return -1; } if (EVP_DecryptFinal(ctx, sdec + slen, &mlen) <= 0) { @@ -4012,17 +4091,20 @@ DH *ssl_get_auto_dh(SSL *s) if (dh_secbits >= 128) { DH *dhp = DH_new(); + BIGNUM *p, *g; if (dhp == NULL) return NULL; - dhp->g = BN_new(); - if (dhp->g != NULL) - BN_set_word(dhp->g, 2); + g = BN_new(); + if (g != NULL) + BN_set_word(g, 2); if (dh_secbits >= 192) - dhp->p = get_rfc3526_prime_8192(NULL); + p = get_rfc3526_prime_8192(NULL); else - dhp->p = get_rfc3526_prime_3072(NULL); - if (dhp->p == NULL || dhp->g == NULL) { + p = get_rfc3526_prime_3072(NULL); + if (p == NULL || g == NULL || !DH_set0_pqg(dhp, p, NULL, g)) { DH_free(dhp); + BN_free(p); + BN_free(g); return NULL; } return dhp;