X-Git-Url: https://git.openssl.org/?p=openssl.git;a=blobdiff_plain;f=ssl%2Fs3_clnt.c;h=6b4c860350ff2573ce5a28d98c62c91734eaada3;hp=ea4503fbcb19725343f8e10ba9633b642605fdff;hb=389ebcecae2575188a4ff9566389ce694352be43;hpb=16f8d4ebf0fd4847fa83d9c61f4150273cb4f533 diff --git a/ssl/s3_clnt.c b/ssl/s3_clnt.c index ea4503fbcb..6b4c860350 100644 --- a/ssl/s3_clnt.c +++ b/ssl/s3_clnt.c @@ -150,7 +150,6 @@ #include #include "ssl_locl.h" -#include "kssl_lcl.h" #include #include #include @@ -164,24 +163,15 @@ # include #endif +static int ssl_set_version(SSL *s); static int ca_dn_cmp(const X509_NAME *const *a, const X509_NAME *const *b); -#ifndef OPENSSL_NO_TLSEXT static int ssl3_check_finished(SSL *s); -#endif +static int ssl_cipher_list_to_bytes(SSL *s, STACK_OF(SSL_CIPHER) *sk, + unsigned char *p, + int (*put_cb) (const SSL_CIPHER *, + unsigned char *)); -#ifndef OPENSSL_NO_SSL3_METHOD -static const SSL_METHOD *ssl3_get_client_method(int ver) -{ - if (ver == SSL3_VERSION) - return (SSLv3_client_method()); - else - return (NULL); -} -IMPLEMENT_ssl3_meth_func(SSLv3_client_method, - ssl_undefined_function, - ssl3_connect, ssl3_get_client_method) -#endif int ssl3_connect(SSL *s) { BUF_MEM *buf = NULL; @@ -235,14 +225,16 @@ int ssl3_connect(SSL *s) if (cb != NULL) cb(s, SSL_CB_HANDSHAKE_START, 1); - if ((s->version & 0xff00) != 0x0300) { + if ((s->version >> 8) != SSL3_VERSION_MAJOR + && s->version != TLS_ANY_VERSION) { SSLerr(SSL_F_SSL3_CONNECT, ERR_R_INTERNAL_ERROR); s->state = SSL_ST_ERR; ret = -1; goto end; } - if (!ssl_security(s, SSL_SECOP_VERSION, 0, s->version, NULL)) { + if (s->version != TLS_ANY_VERSION && + !ssl_security(s, SSL_SECOP_VERSION, 0, s->version, NULL)) { SSLerr(SSL_F_SSL3_CONNECT, SSL_R_VERSION_TOO_LOW); return -1; } @@ -315,12 +307,10 @@ int ssl3_connect(SSL *s) if (s->hit) { s->state = SSL3_ST_CR_FINISHED_A; -#ifndef OPENSSL_NO_TLSEXT if (s->tlsext_ticket_expected) { /* receive renewed session ticket */ s->state = SSL3_ST_CR_SESSION_TICKET_A; } -#endif } else { s->state = SSL3_ST_CR_CERT_A; } @@ -328,7 +318,6 @@ int ssl3_connect(SSL *s) break; case SSL3_ST_CR_CERT_A: case SSL3_ST_CR_CERT_B: -#ifndef OPENSSL_NO_TLSEXT /* Noop (ret = 0) for everything but EAP-FAST. */ ret = ssl3_check_finished(s); if (ret < 0) @@ -339,17 +328,17 @@ int ssl3_connect(SSL *s) s->init_num = 0; break; } -#endif + /* Check if it is anon DH/ECDH, SRP auth */ /* or PSK */ if (! (s->s3->tmp. new_cipher->algorithm_auth & (SSL_aNULL | SSL_aSRP)) -&& !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK)) { + && !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK)) { ret = ssl3_get_server_certificate(s); if (ret <= 0) goto end; -#ifndef OPENSSL_NO_TLSEXT + if (s->tlsext_status_expected) s->state = SSL3_ST_CR_CERT_STATUS_A; else @@ -358,12 +347,7 @@ int ssl3_connect(SSL *s) skip = 1; s->state = SSL3_ST_CR_KEY_EXCH_A; } -#else - } else - skip = 1; - s->state = SSL3_ST_CR_KEY_EXCH_A; -#endif s->init_num = 0; break; @@ -476,7 +460,7 @@ int ssl3_connect(SSL *s) if (ret <= 0) goto end; -#if defined(OPENSSL_NO_TLSEXT) || defined(OPENSSL_NO_NEXTPROTONEG) +#if defined(OPENSSL_NO_NEXTPROTONEG) s->state = SSL3_ST_CW_FINISHED_A; #else if (s->s3->next_proto_neg_seen) @@ -511,7 +495,7 @@ int ssl3_connect(SSL *s) break; -#if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG) +#if !defined(OPENSSL_NO_NEXTPROTONEG) case SSL3_ST_CW_NEXT_PROTO_A: case SSL3_ST_CW_NEXT_PROTO_B: ret = ssl3_send_next_proto(s); @@ -544,21 +528,17 @@ int ssl3_connect(SSL *s) s->s3->delay_buf_pop_ret = 0; } } else { -#ifndef OPENSSL_NO_TLSEXT /* * Allow NewSessionTicket if ticket expected */ if (s->tlsext_ticket_expected) s->s3->tmp.next_state = SSL3_ST_CR_SESSION_TICKET_A; else -#endif - s->s3->tmp.next_state = SSL3_ST_CR_FINISHED_A; } s->init_num = 0; break; -#ifndef OPENSSL_NO_TLSEXT case SSL3_ST_CR_SESSION_TICKET_A: case SSL3_ST_CR_SESSION_TICKET_B: ret = ssl3_get_new_session_ticket(s); @@ -576,7 +556,6 @@ int ssl3_connect(SSL *s) s->state = SSL3_ST_CR_KEY_EXCH_A; s->init_num = 0; break; -#endif case SSL3_ST_CR_FINISHED_A: case SSL3_ST_CR_FINISHED_B: @@ -669,6 +648,105 @@ int ssl3_connect(SSL *s) return (ret); } +/* + * Work out what version we should be using for the initial ClientHello if + * the version is currently set to (D)TLS_ANY_VERSION. + * Returns 1 on success + * Returns 0 on error + */ +static int ssl_set_version(SSL *s) +{ + unsigned long mask, options = s->options; + + if (s->method->version == TLS_ANY_VERSION) { + /* + * SSL_OP_NO_X disables all protocols above X *if* there are + * some protocols below X enabled. This is required in order + * to maintain "version capability" vector contiguous. So + * that if application wants to disable TLS1.0 in favour of + * TLS1>=1, it would be insufficient to pass SSL_NO_TLSv1, the + * answer is SSL_OP_NO_TLSv1|SSL_OP_NO_SSLv3. + */ + mask = SSL_OP_NO_TLSv1_1 | SSL_OP_NO_TLSv1 +#if !defined(OPENSSL_NO_SSL3) + | SSL_OP_NO_SSLv3 +#endif + ; +#if !defined(OPENSSL_NO_TLS1_2_CLIENT) + if (options & SSL_OP_NO_TLSv1_2) { + if ((options & mask) != mask) { + s->version = TLS1_1_VERSION; + } else { + SSLerr(SSL_F_SSL_SET_VERSION, SSL_R_NO_PROTOCOLS_AVAILABLE); + return 0; + } + } else { + s->version = TLS1_2_VERSION; + } +#else + if ((options & mask) == mask) { + SSLerr(SSL_F_SSL_SET_VERSION, SSL_R_NO_PROTOCOLS_AVAILABLE); + return 0; + } + s->version = TLS1_1_VERSION; +#endif + + mask &= ~SSL_OP_NO_TLSv1_1; + if ((options & SSL_OP_NO_TLSv1_1) && (options & mask) != mask) + s->version = TLS1_VERSION; + mask &= ~SSL_OP_NO_TLSv1; +#if !defined(OPENSSL_NO_SSL3) + if ((options & SSL_OP_NO_TLSv1) && (options & mask) != mask) + s->version = SSL3_VERSION; +#endif + + if (s->version != TLS1_2_VERSION && tls1_suiteb(s)) { + SSLerr(SSL_F_SSL_SET_VERSION, + SSL_R_ONLY_TLS_1_2_ALLOWED_IN_SUITEB_MODE); + return 0; + } + + if (s->version == SSL3_VERSION && FIPS_mode()) { + SSLerr(SSL_F_SSL_SET_VERSION, SSL_R_ONLY_TLS_ALLOWED_IN_FIPS_MODE); + return 0; + } + + } else if (s->method->version == DTLS_ANY_VERSION) { + /* Determine which DTLS version to use */ + /* If DTLS 1.2 disabled correct the version number */ + if (options & SSL_OP_NO_DTLSv1_2) { + if (tls1_suiteb(s)) { + SSLerr(SSL_F_SSL_SET_VERSION, + SSL_R_ONLY_DTLS_1_2_ALLOWED_IN_SUITEB_MODE); + return 0; + } + /* + * Disabling all versions is silly: return an error. + */ + if (options & SSL_OP_NO_DTLSv1) { + SSLerr(SSL_F_SSL_SET_VERSION, SSL_R_WRONG_SSL_VERSION); + return 0; + } + /* + * Update method so we don't use any DTLS 1.2 features. + */ + s->method = DTLSv1_client_method(); + s->version = DTLS1_VERSION; + } else { + /* + * We only support one version: update method + */ + if (options & SSL_OP_NO_DTLSv1) + s->method = DTLSv1_2_client_method(); + s->version = DTLS1_2_VERSION; + } + } + + s->client_version = s->version; + + return 1; +} + int ssl3_client_hello(SSL *s) { unsigned char *buf; @@ -684,52 +762,21 @@ int ssl3_client_hello(SSL *s) buf = (unsigned char *)s->init_buf->data; if (s->state == SSL3_ST_CW_CLNT_HELLO_A) { SSL_SESSION *sess = s->session; + + /* Work out what SSL/TLS/DTLS version to use */ + if (ssl_set_version(s) == 0) + goto err; + if ((sess == NULL) || (sess->ssl_version != s->version) || -#ifdef OPENSSL_NO_TLSEXT - !sess->session_id_length || -#else /* * In the case of EAP-FAST, we can have a pre-shared * "ticket" without a session ID. */ (!sess->session_id_length && !sess->tlsext_tick) || -#endif (sess->not_resumable)) { if (!ssl_get_new_session(s, 0)) goto err; } - if (s->method->version == DTLS_ANY_VERSION) { - /* Determine which DTLS version to use */ - int options = s->options; - /* If DTLS 1.2 disabled correct the version number */ - if (options & SSL_OP_NO_DTLSv1_2) { - if (tls1_suiteb(s)) { - SSLerr(SSL_F_SSL3_CLIENT_HELLO, - SSL_R_ONLY_DTLS_1_2_ALLOWED_IN_SUITEB_MODE); - goto err; - } - /* - * Disabling all versions is silly: return an error. - */ - if (options & SSL_OP_NO_DTLSv1) { - SSLerr(SSL_F_SSL3_CLIENT_HELLO, SSL_R_WRONG_SSL_VERSION); - goto err; - } - /* - * Update method so we don't use any DTLS 1.2 features. - */ - s->method = DTLSv1_client_method(); - s->version = DTLS1_VERSION; - } else { - /* - * We only support one version: update method - */ - if (options & SSL_OP_NO_DTLSv1) - s->method = DTLSv1_2_client_method(); - s->version = DTLS1_2_VERSION; - } - s->client_version = s->version; - } /* else use the pre-loaded session */ p = s->s3->client_random; @@ -856,7 +903,6 @@ int ssl3_client_hello(SSL *s) #endif *(p++) = 0; /* Add the NULL method */ -#ifndef OPENSSL_NO_TLSEXT /* TLS extensions */ if (ssl_prepare_clienthello_tlsext(s) <= 0) { SSLerr(SSL_F_SSL3_CLIENT_HELLO, SSL_R_CLIENTHELLO_TLSEXT); @@ -869,7 +915,6 @@ int ssl3_client_hello(SSL *s) SSLerr(SSL_F_SSL3_CLIENT_HELLO, ERR_R_INTERNAL_ERROR); goto err; } -#endif l = p - d; if (!ssl_set_handshake_header(s, SSL3_MT_CLIENT_HELLO, l)) { @@ -891,7 +936,6 @@ int ssl3_get_server_hello(SSL *s) { STACK_OF(SSL_CIPHER) *sk; const SSL_CIPHER *c; - CERT *ct = s->cert; unsigned char *p, *d; int i, al = SSL_AD_INTERNAL_ERROR, ok; unsigned int j; @@ -903,8 +947,7 @@ int ssl3_get_server_hello(SSL *s) * Hello verify request and/or server hello version may not match so set * first packet if we're negotiating version. */ - if (SSL_IS_DTLS(s)) - s->first_packet = 1; + s->first_packet = 1; n = s->method->ssl_get_message(s, SSL3_ST_CR_SRVR_HELLO_A, @@ -913,8 +956,8 @@ int ssl3_get_server_hello(SSL *s) if (!ok) return ((int)n); + s->first_packet = 0; if (SSL_IS_DTLS(s)) { - s->first_packet = 0; if (s->s3->tmp.message_type == DTLS1_MT_HELLO_VERIFY_REQUEST) { if (s->d1->send_cookie == 0) { s->s3->tmp.reuse_message = 1; @@ -935,7 +978,45 @@ int ssl3_get_server_hello(SSL *s) } d = p = (unsigned char *)s->init_msg; - if (s->method->version == DTLS_ANY_VERSION) { + + if (s->method->version == TLS_ANY_VERSION) { + int sversion = (p[0] << 8) | p[1]; + +#if TLS_MAX_VERSION != TLS1_2_VERSION +#error Code needs updating for new TLS version +#endif +#ifndef OPENSSL_NO_SSL3 + if ((sversion == SSL3_VERSION) && !(s->options & SSL_OP_NO_SSLv3)) { + if (FIPS_mode()) { + SSLerr(SSL_F_SSL3_GET_SERVER_HELLO, + SSL_R_ONLY_TLS_ALLOWED_IN_FIPS_MODE); + al = SSL_AD_PROTOCOL_VERSION; + goto f_err; + } + s->method = SSLv3_client_method(); + } else +#endif + if ((sversion == TLS1_VERSION) && !(s->options & SSL_OP_NO_TLSv1)) { + s->method = TLSv1_client_method(); + } else if ((sversion == TLS1_1_VERSION) && + !(s->options & SSL_OP_NO_TLSv1_1)) { + s->method = TLSv1_1_client_method(); + } else if ((sversion == TLS1_2_VERSION) && + !(s->options & SSL_OP_NO_TLSv1_2)) { + s->method = TLSv1_2_client_method(); + } else { + SSLerr(SSL_F_SSL3_GET_SERVER_HELLO, SSL_R_UNSUPPORTED_PROTOCOL); + al = SSL_AD_PROTOCOL_VERSION; + goto f_err; + } + s->session->ssl_version = s->version = s->method->version; + + if (!ssl_security(s, SSL_SECOP_VERSION, 0, s->version, NULL)) { + SSLerr(SSL_F_SSL3_GET_SERVER_HELLO, SSL_R_VERSION_TOO_LOW); + al = SSL_AD_PROTOCOL_VERSION; + goto f_err; + } + } else if (s->method->version == DTLS_ANY_VERSION) { /* Work out correct protocol version to use */ int hversion = (p[0] << 8) | p[1]; int options = s->options; @@ -955,10 +1036,8 @@ int ssl3_get_server_hello(SSL *s) al = SSL_AD_PROTOCOL_VERSION; goto f_err; } - s->version = s->method->version; - } - - if ((p[0] != (s->version >> 8)) || (p[1] != (s->version & 0xff))) { + s->session->ssl_version = s->version = s->method->version; + } else if ((p[0] != (s->version >> 8)) || (p[1] != (s->version & 0xff))) { SSLerr(SSL_F_SSL3_GET_SERVER_HELLO, SSL_R_WRONG_SSL_VERSION); s->version = (s->version & 0xff00) | p[1]; al = SSL_AD_PROTOCOL_VERSION; @@ -981,7 +1060,7 @@ int ssl3_get_server_hello(SSL *s) SSLerr(SSL_F_SSL3_GET_SERVER_HELLO, SSL_R_SSL3_SESSION_ID_TOO_LONG); goto f_err; } -#ifndef OPENSSL_NO_TLSEXT + /* * Check if we can resume the session based on external pre-shared secret. * EAP-FAST (RFC 4851) supports two types of session resumption. @@ -1010,7 +1089,6 @@ int ssl3_get_server_hello(SSL *s) goto f_err; } } -#endif /* OPENSSL_NO_TLSEXT */ if (j != 0 && j == s->session->session_id_length && memcmp(p, s->session->session_id, j) == 0) { @@ -1049,9 +1127,9 @@ int ssl3_get_server_hello(SSL *s) } /* Set version disabled mask now we know version */ if (!SSL_USE_TLS1_2_CIPHERS(s)) - ct->mask_ssl = SSL_TLSV1_2; + s->s3->tmp.mask_ssl = SSL_TLSV1_2; else - ct->mask_ssl = 0; + s->s3->tmp.mask_ssl = 0; /* * If it is a disabled cipher we didn't send it in client hello, so * return an error. @@ -1136,13 +1214,11 @@ int ssl3_get_server_hello(SSL *s) } #endif -#ifndef OPENSSL_NO_TLSEXT /* TLS extensions */ if (!ssl_parse_serverhello_tlsext(s, &p, d, n)) { SSLerr(SSL_F_SSL3_GET_SERVER_HELLO, SSL_R_PARSE_TLSEXT); goto err; } -#endif if (p != (d + n)) { /* wrong packet length */ @@ -1161,16 +1237,13 @@ int ssl3_get_server_hello(SSL *s) int ssl3_get_server_certificate(SSL *s) { - int al, i, ok, ret = -1; + int al, i, ok, ret = -1, exp_idx; unsigned long n, nc, llen, l; X509 *x = NULL; const unsigned char *q, *p; unsigned char *d; STACK_OF(X509) *sk = NULL; - SESS_CERT *sc; EVP_PKEY *pkey = NULL; - int need_cert = 1; /* VRS: 0=> will allow null cert if auth == - * KRB5 */ n = s->method->ssl_get_message(s, SSL3_ST_CR_CERT_A, @@ -1180,9 +1253,7 @@ int ssl3_get_server_certificate(SSL *s) if (!ok) return ((int)n); - if ((s->s3->tmp.message_type == SSL3_MT_SERVER_KEY_EXCHANGE) || - ((s->s3->tmp.new_cipher->algorithm_auth & SSL_aKRB5) && - (s->s3->tmp.message_type == SSL3_MT_SERVER_DONE))) { + if (s->s3->tmp.message_type == SSL3_MT_SERVER_KEY_EXCHANGE) { s->s3->tmp.reuse_message = 1; return (1); } @@ -1237,12 +1308,7 @@ int ssl3_get_server_certificate(SSL *s) } i = ssl_verify_cert_chain(s, sk); - if ((s->verify_mode != SSL_VERIFY_NONE) && (i <= 0) -#ifndef OPENSSL_NO_KRB5 - && !((s->s3->tmp.new_cipher->algorithm_mkey & SSL_kKRB5) && - (s->s3->tmp.new_cipher->algorithm_auth & SSL_aKRB5)) -#endif /* OPENSSL_NO_KRB5 */ - ) { + if (s->verify_mode != SSL_VERIFY_NONE && i <= 0) { al = ssl_verify_alarm_type(s->verify_result); SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE, SSL_R_CERTIFICATE_VERIFY_FAILED); @@ -1255,14 +1321,7 @@ int ssl3_get_server_certificate(SSL *s) goto f_err; } - sc = ssl_sess_cert_new(); - if (sc == NULL) - goto err; - - ssl_sess_cert_free(s->session->sess_cert); - s->session->sess_cert = sc; - - sc->cert_chain = sk; + s->session->peer_chain = sk; /* * Inconsistency alert: cert_chain does include the peer's certificate, * which we don't include in s3_srvr.c @@ -1275,21 +1334,7 @@ int ssl3_get_server_certificate(SSL *s) pkey = X509_get_pubkey(x); - /* VRS: allow null cert if auth == KRB5 */ - need_cert = ((s->s3->tmp.new_cipher->algorithm_mkey & SSL_kKRB5) && - (s->s3->tmp.new_cipher->algorithm_auth & SSL_aKRB5)) - ? 0 : 1; - -#ifdef KSSL_DEBUG - fprintf(stderr, "pkey,x = %p, %p\n", pkey, x); - fprintf(stderr, "ssl_cert_type(x,pkey) = %d\n", ssl_cert_type(x, pkey)); - fprintf(stderr, "cipher, alg, nc = %s, %lx, %lx, %d\n", - s->s3->tmp.new_cipher->name, - s->s3->tmp.new_cipher->algorithm_mkey, - s->s3->tmp.new_cipher->algorithm_auth, need_cert); -#endif /* KSSL_DEBUG */ - - if (need_cert && ((pkey == NULL) || EVP_PKEY_missing_parameters(pkey))) { + if (pkey == NULL || EVP_PKEY_missing_parameters(pkey)) { x = NULL; al = SSL3_AL_FATAL; SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE, @@ -1298,7 +1343,7 @@ int ssl3_get_server_certificate(SSL *s) } i = ssl_cert_type(x, pkey); - if (need_cert && i < 0) { + if (i < 0) { x = NULL; al = SSL3_AL_FATAL; SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE, @@ -1306,35 +1351,19 @@ int ssl3_get_server_certificate(SSL *s) goto f_err; } - if (need_cert) { - int exp_idx = ssl_cipher_get_cert_index(s->s3->tmp.new_cipher); - if (exp_idx >= 0 && i != exp_idx) { - x = NULL; - al = SSL_AD_ILLEGAL_PARAMETER; - SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE, - SSL_R_WRONG_CERTIFICATE_TYPE); - goto f_err; - } - sc->peer_cert_type = i; - CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509); - /* - * Why would the following ever happen? We just created sc a couple - * of lines ago. - */ - X509_free(sc->peer_pkeys[i].x509); - sc->peer_pkeys[i].x509 = x; - sc->peer_key = &(sc->peer_pkeys[i]); - - X509_free(s->session->peer); - CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509); - s->session->peer = x; - } else { - sc->peer_cert_type = i; - sc->peer_key = NULL; - - X509_free(s->session->peer); - s->session->peer = NULL; + exp_idx = ssl_cipher_get_cert_index(s->s3->tmp.new_cipher); + if (exp_idx >= 0 && i != exp_idx) { + x = NULL; + al = SSL_AD_ILLEGAL_PARAMETER; + SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE, + SSL_R_WRONG_CERTIFICATE_TYPE); + goto f_err; } + s->session->peer_type = i; + + X509_free(s->session->peer); + CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509); + s->session->peer = x; s->session->verify_result = s->verify_result; x = NULL; @@ -1409,7 +1438,6 @@ int ssl3_get_key_exchange(SSL *s) * problems later. */ if (alg_k & SSL_kPSK) { - s->session->sess_cert = ssl_sess_cert_new(); OPENSSL_free(s->ctx->psk_identity_hint); s->ctx->psk_identity_hint = NULL; } @@ -1419,22 +1447,19 @@ int ssl3_get_key_exchange(SSL *s) } param = p = (unsigned char *)s->init_msg; - if (s->session->sess_cert != NULL) { + #ifndef OPENSSL_NO_RSA - RSA_free(s->session->sess_cert->peer_rsa_tmp); - s->session->sess_cert->peer_rsa_tmp = NULL; + RSA_free(s->s3->peer_rsa_tmp); + s->s3->peer_rsa_tmp = NULL; #endif #ifndef OPENSSL_NO_DH - DH_free(s->session->sess_cert->peer_dh_tmp); - s->session->sess_cert->peer_dh_tmp = NULL; + DH_free(s->s3->peer_dh_tmp); + s->s3->peer_dh_tmp = NULL; #endif #ifndef OPENSSL_NO_EC - EC_KEY_free(s->session->sess_cert->peer_ecdh_tmp); - s->session->sess_cert->peer_ecdh_tmp = NULL; + EC_KEY_free(s->s3->peer_ecdh_tmp); + s->s3->peer_ecdh_tmp = NULL; #endif - } else { - s->session->sess_cert = ssl_sess_cert_new(); - } /* Total length of the parameters including the length prefix */ param_len = 0; @@ -1506,7 +1531,7 @@ int ssl3_get_key_exchange(SSL *s) } param_len += i; - if (!(s->srp_ctx.N = BN_bin2bn(p, i, NULL))) { + if ((s->srp_ctx.N = BN_bin2bn(p, i, NULL)) == NULL) { SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_BN_LIB); goto err; } @@ -1526,7 +1551,7 @@ int ssl3_get_key_exchange(SSL *s) } param_len += i; - if (!(s->srp_ctx.g = BN_bin2bn(p, i, NULL))) { + if ((s->srp_ctx.g = BN_bin2bn(p, i, NULL)) == NULL) { SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_BN_LIB); goto err; } @@ -1547,7 +1572,7 @@ int ssl3_get_key_exchange(SSL *s) } param_len += i; - if (!(s->srp_ctx.s = BN_bin2bn(p, i, NULL))) { + if ((s->srp_ctx.s = BN_bin2bn(p, i, NULL)) == NULL) { SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_BN_LIB); goto err; } @@ -1567,7 +1592,7 @@ int ssl3_get_key_exchange(SSL *s) } param_len += i; - if (!(s->srp_ctx.B = BN_bin2bn(p, i, NULL))) { + if ((s->srp_ctx.B = BN_bin2bn(p, i, NULL)) == NULL) { SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_BN_LIB); goto err; } @@ -1580,21 +1605,8 @@ int ssl3_get_key_exchange(SSL *s) } /* We must check if there is a certificate */ -# ifndef OPENSSL_NO_RSA - if (alg_a & SSL_aRSA) - pkey = - X509_get_pubkey(s->session-> - sess_cert->peer_pkeys[SSL_PKEY_RSA_ENC].x509); -# else - if (0) ; -# endif -# ifndef OPENSSL_NO_DSA - else if (alg_a & SSL_aDSS) - pkey = - X509_get_pubkey(s->session-> - sess_cert->peer_pkeys[SSL_PKEY_DSA_SIGN]. - x509); -# endif + if (alg_a & (SSL_aRSA|SSL_aDSS)) + pkey = X509_get_pubkey(s->session->peer); } else #endif /* !OPENSSL_NO_SRP */ #ifndef OPENSSL_NO_RSA @@ -1623,7 +1635,7 @@ int ssl3_get_key_exchange(SSL *s) } param_len += i; - if (!(rsa->n = BN_bin2bn(p, i, rsa->n))) { + if ((rsa->n = BN_bin2bn(p, i, rsa->n)) == NULL) { SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_BN_LIB); goto err; } @@ -1643,7 +1655,7 @@ int ssl3_get_key_exchange(SSL *s) } param_len += i; - if (!(rsa->e = BN_bin2bn(p, i, rsa->e))) { + if ((rsa->e = BN_bin2bn(p, i, rsa->e)) == NULL) { SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_BN_LIB); goto err; } @@ -1652,14 +1664,19 @@ int ssl3_get_key_exchange(SSL *s) /* this should be because we are using an export cipher */ if (alg_a & SSL_aRSA) - pkey = - X509_get_pubkey(s->session-> - sess_cert->peer_pkeys[SSL_PKEY_RSA_ENC].x509); + pkey = X509_get_pubkey(s->session->peer); else { SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR); goto err; } - s->session->sess_cert->peer_rsa_tmp = rsa; + + if (EVP_PKEY_bits(pkey) <= SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher)) { + al = SSL_AD_UNEXPECTED_MESSAGE; + SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_UNEXPECTED_MESSAGE); + goto f_err; + } + + s->s3->peer_rsa_tmp = rsa; rsa = NULL; } #else /* OPENSSL_NO_RSA */ @@ -1685,7 +1702,7 @@ int ssl3_get_key_exchange(SSL *s) } param_len += i; - if (!(dh->p = BN_bin2bn(p, i, NULL))) { + if ((dh->p = BN_bin2bn(p, i, NULL)) == NULL) { SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_BN_LIB); goto err; } @@ -1705,7 +1722,7 @@ int ssl3_get_key_exchange(SSL *s) } param_len += i; - if (!(dh->g = BN_bin2bn(p, i, NULL))) { + if ((dh->g = BN_bin2bn(p, i, NULL)) == NULL) { SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_BN_LIB); goto err; } @@ -1725,7 +1742,7 @@ int ssl3_get_key_exchange(SSL *s) } param_len += i; - if (!(dh->pub_key = BN_bin2bn(p, i, NULL))) { + if ((dh->pub_key = BN_bin2bn(p, i, NULL)) == NULL) { SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_BN_LIB); goto err; } @@ -1737,24 +1754,11 @@ int ssl3_get_key_exchange(SSL *s) SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_DH_KEY_TOO_SMALL); goto f_err; } -# ifndef OPENSSL_NO_RSA - if (alg_a & SSL_aRSA) - pkey = - X509_get_pubkey(s->session-> - sess_cert->peer_pkeys[SSL_PKEY_RSA_ENC].x509); -# else - if (0) ; -# endif -# ifndef OPENSSL_NO_DSA - else if (alg_a & SSL_aDSS) - pkey = - X509_get_pubkey(s->session-> - sess_cert->peer_pkeys[SSL_PKEY_DSA_SIGN]. - x509); -# endif + if (alg_a & (SSL_aRSA|SSL_aDSS)) + pkey = X509_get_pubkey(s->session->peer); /* else anonymous DH, so no certificate or pkey. */ - s->session->sess_cert->peer_dh_tmp = dh; + s->s3->peer_dh_tmp = dh; dh = NULL; } #endif /* !OPENSSL_NO_DH */ @@ -1853,19 +1857,15 @@ int ssl3_get_key_exchange(SSL *s) if (0) ; # ifndef OPENSSL_NO_RSA else if (alg_a & SSL_aRSA) - pkey = - X509_get_pubkey(s->session-> - sess_cert->peer_pkeys[SSL_PKEY_RSA_ENC].x509); + pkey = X509_get_pubkey(s->session->peer); # endif # ifndef OPENSSL_NO_EC else if (alg_a & SSL_aECDSA) - pkey = - X509_get_pubkey(s->session-> - sess_cert->peer_pkeys[SSL_PKEY_ECC].x509); + pkey = X509_get_pubkey(s->session->peer); # endif /* else anonymous ECDH, so no certificate or pkey. */ EC_KEY_set_public_key(ecdh, srvr_ecpoint); - s->session->sess_cert->peer_ecdh_tmp = ecdh; + s->s3->peer_ecdh_tmp = ecdh; ecdh = NULL; BN_CTX_free(bn_ctx); bn_ctx = NULL; @@ -2092,8 +2092,8 @@ int ssl3_get_certificate_request(SSL *s) } /* 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; + s->s3->tmp.md[i] = NULL; + s->s3->tmp.valid_flags[i] = 0; } if ((llen & 1) || !tls1_save_sigalgs(s, p, llen)) { ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); @@ -2170,7 +2170,6 @@ static int ca_dn_cmp(const X509_NAME *const *a, const X509_NAME *const *b) return (X509_NAME_cmp(*a, *b)); } -#ifndef OPENSSL_NO_TLSEXT int ssl3_get_new_session_ticket(SSL *s) { int ok, al, ret = 0, ticklen; @@ -2194,6 +2193,38 @@ int ssl3_get_new_session_ticket(SSL *s) } p = d = (unsigned char *)s->init_msg; + + if (s->session->session_id_length > 0) { + int i = s->session_ctx->session_cache_mode; + SSL_SESSION *new_sess; + /* + * We reused an existing session, so we need to replace it with a new + * one + */ + if (i & SSL_SESS_CACHE_CLIENT) { + /* + * Remove the old session from the cache + */ + if (i & SSL_SESS_CACHE_NO_INTERNAL_STORE) { + if (s->session_ctx->remove_session_cb != NULL) + s->session_ctx->remove_session_cb(s->session_ctx, + s->session); + } else { + /* We carry on if this fails */ + SSL_CTX_remove_session(s->session_ctx, s->session); + } + } + + if ((new_sess = ssl_session_dup(s->session, 0)) == 0) { + al = SSL_AD_INTERNAL_ERROR; + SSLerr(SSL_F_SSL3_GET_NEW_SESSION_TICKET, ERR_R_MALLOC_FAILURE); + goto f_err; + } + + SSL_SESSION_free(s->session); + s->session = new_sess; + } + n2l(p, s->session->tlsext_tick_lifetime_hint); n2s(p, ticklen); /* ticket_lifetime_hint + ticket_length + ticket */ @@ -2293,7 +2324,6 @@ int ssl3_get_cert_status(SSL *s) s->state = SSL_ST_ERR; return (-1); } -#endif int ssl3_get_server_done(SSL *s) { @@ -2328,9 +2358,6 @@ int ssl3_send_client_key_exchange(SSL *s) unsigned char *q; EVP_PKEY *pkey = NULL; #endif -#ifndef OPENSSL_NO_KRB5 - KSSL_ERR kssl_err; -#endif /* OPENSSL_NO_KRB5 */ #ifndef OPENSSL_NO_EC EC_KEY *clnt_ecdh = NULL; const EC_POINT *srvr_ecpoint = NULL; @@ -2358,7 +2385,7 @@ int ssl3_send_client_key_exchange(SSL *s) if (!pms) goto memerr; - if (s->session->sess_cert == NULL) { + if (s->session->peer == NULL) { /* * We should always have a server certificate with SSL_kRSA. */ @@ -2367,13 +2394,10 @@ int ssl3_send_client_key_exchange(SSL *s) goto err; } - if (s->session->sess_cert->peer_rsa_tmp != NULL) - rsa = s->session->sess_cert->peer_rsa_tmp; + if (s->s3->peer_rsa_tmp != NULL) + rsa = s->s3->peer_rsa_tmp; else { - pkey = - X509_get_pubkey(s->session-> - sess_cert->peer_pkeys[SSL_PKEY_RSA_ENC]. - x509); + pkey = X509_get_pubkey(s->session->peer); if ((pkey == NULL) || (pkey->type != EVP_PKEY_RSA) || (pkey->pkey.rsa == NULL)) { SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, @@ -2413,152 +2437,16 @@ int ssl3_send_client_key_exchange(SSL *s) } } #endif -#ifndef OPENSSL_NO_KRB5 - else if (alg_k & SSL_kKRB5) { - krb5_error_code krb5rc; - KSSL_CTX *kssl_ctx = s->kssl_ctx; - /* krb5_data krb5_ap_req; */ - krb5_data *enc_ticket; - krb5_data authenticator, *authp = NULL; - EVP_CIPHER_CTX ciph_ctx; - const EVP_CIPHER *enc = NULL; - unsigned char iv[EVP_MAX_IV_LENGTH]; - unsigned char tmp_buf[SSL_MAX_MASTER_KEY_LENGTH]; - unsigned char epms[SSL_MAX_MASTER_KEY_LENGTH + EVP_MAX_IV_LENGTH]; - int padl, outl = sizeof(epms); - - EVP_CIPHER_CTX_init(&ciph_ctx); - -# ifdef KSSL_DEBUG - fprintf(stderr, "ssl3_send_client_key_exchange(%lx & %lx)\n", - alg_k, SSL_kKRB5); -# endif /* KSSL_DEBUG */ - - authp = NULL; -# ifdef KRB5SENDAUTH - if (KRB5SENDAUTH) - authp = &authenticator; -# endif /* KRB5SENDAUTH */ - - krb5rc = kssl_cget_tkt(kssl_ctx, &enc_ticket, authp, &kssl_err); - enc = kssl_map_enc(kssl_ctx->enctype); - if (enc == NULL) - goto err; -# ifdef KSSL_DEBUG - { - fprintf(stderr, "kssl_cget_tkt rtn %d\n", krb5rc); - if (krb5rc && kssl_err.text) - fprintf(stderr, "kssl_cget_tkt kssl_err=%s\n", - kssl_err.text); - } -# endif /* KSSL_DEBUG */ - - if (krb5rc) { - ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE); - SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, kssl_err.reason); - goto err; - } - - /*- - * 20010406 VRS - Earlier versions used KRB5 AP_REQ - * in place of RFC 2712 KerberosWrapper, as in: - * - * Send ticket (copy to *p, set n = length) - * n = krb5_ap_req.length; - * memcpy(p, krb5_ap_req.data, krb5_ap_req.length); - * if (krb5_ap_req.data) - * kssl_krb5_free_data_contents(NULL,&krb5_ap_req); - * - * Now using real RFC 2712 KerberosWrapper - * (Thanks to Simon Wilkinson ) - * Note: 2712 "opaque" types are here replaced - * with a 2-byte length followed by the value. - * Example: - * KerberosWrapper= xx xx asn1ticket 0 0 xx xx encpms - * Where "xx xx" = length bytes. Shown here with - * optional authenticator omitted. - */ - - /* KerberosWrapper.Ticket */ - s2n(enc_ticket->length, p); - memcpy(p, enc_ticket->data, enc_ticket->length); - p += enc_ticket->length; - n = enc_ticket->length + 2; - - /* KerberosWrapper.Authenticator */ - if (authp && authp->length) { - s2n(authp->length, p); - memcpy(p, authp->data, authp->length); - p += authp->length; - n += authp->length + 2; - - free(authp->data); - authp->data = NULL; - authp->length = 0; - } else { - s2n(0, p); /* null authenticator length */ - n += 2; - } - - pmslen = SSL_MAX_MASTER_KEY_LENGTH; - pms = OPENSSL_malloc(pmslen); - if (!pms) - goto memerr; - - pms[0] = s->client_version >> 8; - pms[1] = s->client_version & 0xff; - if (RAND_bytes(pms + 2, pmslen - 2) <= 0) - goto err; - - /*- - * 20010420 VRS. Tried it this way; failed. - * EVP_EncryptInit_ex(&ciph_ctx,enc, NULL,NULL); - * EVP_CIPHER_CTX_set_key_length(&ciph_ctx, - * kssl_ctx->length); - * EVP_EncryptInit_ex(&ciph_ctx,NULL, key,iv); - */ - - memset(iv, 0, sizeof(iv)); /* per RFC 1510 */ - EVP_EncryptInit_ex(&ciph_ctx, enc, NULL, kssl_ctx->key, iv); - EVP_EncryptUpdate(&ciph_ctx, epms, &outl, pms, pmslen); - EVP_EncryptFinal_ex(&ciph_ctx, &(epms[outl]), &padl); - outl += padl; - if (outl > (int)sizeof epms) { - SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, - ERR_R_INTERNAL_ERROR); - goto err; - } - EVP_CIPHER_CTX_cleanup(&ciph_ctx); - - /* KerberosWrapper.EncryptedPreMasterSecret */ - s2n(outl, p); - memcpy(p, epms, outl); - p += outl; - n += outl + 2; - OPENSSL_cleanse(epms, outl); - } -#endif #ifndef OPENSSL_NO_DH else if (alg_k & (SSL_kDHE | SSL_kDHr | SSL_kDHd)) { DH *dh_srvr, *dh_clnt; - SESS_CERT *scert = s->session->sess_cert; - - if (scert == NULL) { - ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE); - SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, - SSL_R_UNEXPECTED_MESSAGE); - goto err; - } - - if (scert->peer_dh_tmp != NULL) - dh_srvr = scert->peer_dh_tmp; + if (s->s3->peer_dh_tmp != NULL) + dh_srvr = s->s3->peer_dh_tmp; else { /* we get them from the cert */ - int idx = scert->peer_cert_type; EVP_PKEY *spkey = NULL; dh_srvr = NULL; - if (idx >= 0) - spkey = X509_get_pubkey(scert->peer_pkeys[idx].x509); + spkey = X509_get_pubkey(s->session->peer); if (spkey) { dh_srvr = EVP_PKEY_get1_DH(spkey); EVP_PKEY_free(spkey); @@ -2604,7 +2492,7 @@ int ssl3_send_client_key_exchange(SSL *s) */ n = DH_compute_key(pms, dh_srvr->pub_key, dh_clnt); - if (scert->peer_dh_tmp == NULL) + if (s->s3->peer_dh_tmp == NULL) DH_free(dh_srvr); if (n <= 0) { @@ -2625,8 +2513,6 @@ int ssl3_send_client_key_exchange(SSL *s) } DH_free(dh_clnt); - - /* perhaps clean things up a bit EAY EAY EAY EAY */ } #endif @@ -2636,14 +2522,6 @@ int ssl3_send_client_key_exchange(SSL *s) EC_KEY *tkey; int ecdh_clnt_cert = 0; int field_size = 0; - - if (s->session->sess_cert == NULL) { - ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE); - SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, - SSL_R_UNEXPECTED_MESSAGE); - goto err; - } - /* * Did we send out the client's ECDH share for use in premaster * computation as part of client certificate? If so, set @@ -2672,13 +2550,11 @@ int ssl3_send_client_key_exchange(SSL *s) */ } - if (s->session->sess_cert->peer_ecdh_tmp != NULL) { - tkey = s->session->sess_cert->peer_ecdh_tmp; + if (s->s3->peer_ecdh_tmp != NULL) { + tkey = s->s3->peer_ecdh_tmp; } else { /* Get the Server Public Key from Cert */ - srvr_pub_pkey = - X509_get_pubkey(s->session-> - sess_cert->peer_pkeys[SSL_PKEY_ECC].x509); + srvr_pub_pkey = X509_get_pubkey(s->session->peer); if ((srvr_pub_pkey == NULL) || (srvr_pub_pkey->type != EVP_PKEY_EC) || (srvr_pub_pkey->pkey.ec == NULL)) { @@ -2806,7 +2682,6 @@ int ssl3_send_client_key_exchange(SSL *s) X509 *peer_cert; size_t msglen; unsigned int md_len; - int keytype; unsigned char shared_ukm[32], tmp[256]; EVP_MD_CTX *ukm_hash; EVP_PKEY *pub_key; @@ -2819,13 +2694,7 @@ int ssl3_send_client_key_exchange(SSL *s) /* * Get server sertificate PKEY and create ctx from it */ - peer_cert = - s->session-> - sess_cert->peer_pkeys[(keytype = SSL_PKEY_GOST01)].x509; - if (!peer_cert) - peer_cert = - s->session-> - sess_cert->peer_pkeys[(keytype = SSL_PKEY_GOST94)].x509; + peer_cert = s->session->peer; if (!peer_cert) { SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, SSL_R_NO_GOST_CERTIFICATE_SENT_BY_PEER); @@ -3060,13 +2929,13 @@ int ssl3_send_client_key_exchange(SSL *s) #endif /* If we haven't written everything save PMS */ if (n <= 0) { - s->cert->pms = pms; - s->cert->pmslen = pmslen; + s->s3->tmp.pms = pms; + s->s3->tmp.pmslen = pmslen; } else { /* If we don't have a PMS restore */ if (pms == NULL) { - pms = s->cert->pms; - pmslen = s->cert->pmslen; + pms = s->s3->tmp.pms; + pmslen = s->s3->tmp.pmslen; } if (pms == NULL) { ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR); @@ -3079,7 +2948,7 @@ int ssl3_send_client_key_exchange(SSL *s) session->master_key, pms, pmslen); OPENSSL_clear_free(pms, pmslen); - s->cert->pms = NULL; + s->s3->tmp.pms = NULL; if (s->session->master_key_length < 0) { ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR); SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR); @@ -3092,7 +2961,7 @@ int ssl3_send_client_key_exchange(SSL *s) SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE); err: OPENSSL_clear_free(pms, pmslen); - s->cert->pms = NULL; + s->s3->tmp.pms = NULL; #ifndef OPENSSL_NO_EC BN_CTX_free(bn_ctx); OPENSSL_free(encodedPoint); @@ -3138,7 +3007,7 @@ int ssl3_send_client_verify(SSL *s) if (SSL_USE_SIGALGS(s)) { long hdatalen = 0; void *hdata; - const EVP_MD *md = s->cert->key->digest; + const EVP_MD *md = s->s3->tmp.md[s->cert->key - s->cert->pkeys]; hdatalen = BIO_get_mem_data(s->s3->handshake_buffer, &hdata); if (hdatalen <= 0 || !tls12_get_sigandhash(p, pkey, md)) { SSLerr(SSL_F_SSL3_SEND_CLIENT_VERIFY, ERR_R_INTERNAL_ERROR); @@ -3254,7 +3123,7 @@ static int ssl3_check_client_certificate(SSL *s) if (!s->cert || !s->cert->key->x509 || !s->cert->key->privatekey) return 0; /* If no suitable signature algorithm can't use certificate */ - if (SSL_USE_SIGALGS(s) && !s->cert->key->digest) + if (SSL_USE_SIGALGS(s) && !s->s3->tmp.md[s->cert->key - s->cert->pkeys]) return 0; /* * If strict mode check suitability of chain before using it. This also @@ -3266,15 +3135,14 @@ static int ssl3_check_client_certificate(SSL *s) alg_k = s->s3->tmp.new_cipher->algorithm_mkey; /* See if we can use client certificate for fixed DH */ if (alg_k & (SSL_kDHr | SSL_kDHd)) { - SESS_CERT *scert = s->session->sess_cert; - int i = scert->peer_cert_type; + int i = s->session->peer_type; EVP_PKEY *clkey = NULL, *spkey = NULL; clkey = s->cert->key->privatekey; /* If client key not DH assume it can be used */ if (EVP_PKEY_id(clkey) != EVP_PKEY_DH) return 1; if (i >= 0) - spkey = X509_get_pubkey(scert->peer_pkeys[i].x509); + spkey = X509_get_pubkey(s->session->peer); if (spkey) { /* Compare server and client parameters */ i = EVP_PKEY_cmp_parameters(clkey, spkey); @@ -3348,6 +3216,11 @@ int ssl3_send_client_certificate(SSL *s) return (1); } else { s->s3->tmp.cert_req = 2; + if (s->s3->handshake_buffer && !ssl3_digest_cached_records(s)) { + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR); + s->state = SSL_ST_ERR; + return 0; + } } } @@ -3377,39 +3250,34 @@ int ssl3_check_cert_and_algorithm(SSL *s) int i, idx; long alg_k, alg_a; EVP_PKEY *pkey = NULL; - SESS_CERT *sc; + int pkey_bits; #ifndef OPENSSL_NO_RSA RSA *rsa; #endif #ifndef OPENSSL_NO_DH DH *dh; #endif + int al = SSL_AD_HANDSHAKE_FAILURE; alg_k = s->s3->tmp.new_cipher->algorithm_mkey; alg_a = s->s3->tmp.new_cipher->algorithm_auth; /* we don't have a certificate */ - if ((alg_a & (SSL_aNULL | SSL_aKRB5)) || (alg_k & SSL_kPSK)) + if ((alg_a & SSL_aNULL) || (alg_k & SSL_kPSK)) return (1); - - sc = s->session->sess_cert; - if (sc == NULL) { - SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM, ERR_R_INTERNAL_ERROR); - goto err; - } #ifndef OPENSSL_NO_RSA - rsa = s->session->sess_cert->peer_rsa_tmp; + rsa = s->s3->peer_rsa_tmp; #endif #ifndef OPENSSL_NO_DH - dh = s->session->sess_cert->peer_dh_tmp; + dh = s->s3->peer_dh_tmp; #endif /* This is the passed certificate */ - idx = sc->peer_cert_type; + idx = s->session->peer_type; #ifndef OPENSSL_NO_EC if (idx == SSL_PKEY_ECC) { - if (ssl_check_srvr_ecc_cert_and_alg(sc->peer_pkeys[idx].x509, s) == 0) { + if (ssl_check_srvr_ecc_cert_and_alg(s->session->peer, s) == 0) { /* check failed */ SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM, SSL_R_BAD_ECC_CERT); goto f_err; @@ -3425,8 +3293,9 @@ int ssl3_check_cert_and_algorithm(SSL *s) goto f_err; } #endif - pkey = X509_get_pubkey(sc->peer_pkeys[idx].x509); - i = X509_certificate_type(sc->peer_pkeys[idx].x509, pkey); + pkey = X509_get_pubkey(s->session->peer); + pkey_bits = EVP_PKEY_bits(pkey); + i = X509_certificate_type(s->session->peer, pkey); EVP_PKEY_free(pkey); /* Check that we have a certificate if we require one */ @@ -3443,17 +3312,33 @@ int ssl3_check_cert_and_algorithm(SSL *s) } #endif #ifndef OPENSSL_NO_RSA - if ((alg_k & SSL_kRSA) && - !(has_bits(i, EVP_PK_RSA | EVP_PKT_ENC) || (rsa != NULL))) { - SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM, - SSL_R_MISSING_RSA_ENCRYPTING_CERT); - goto f_err; + if (alg_k & SSL_kRSA) { + if (!SSL_C_IS_EXPORT(s->s3->tmp.new_cipher) && + !has_bits(i, EVP_PK_RSA | EVP_PKT_ENC)) { + SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM, + SSL_R_MISSING_RSA_ENCRYPTING_CERT); + goto f_err; + } else if (SSL_C_IS_EXPORT(s->s3->tmp.new_cipher)) { + if (pkey_bits <= SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher)) { + if (!has_bits(i, EVP_PK_RSA | EVP_PKT_ENC)) { + SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM, + SSL_R_MISSING_RSA_ENCRYPTING_CERT); + goto f_err; + } + if (rsa != NULL) { + /* server key exchange is not allowed. */ + al = SSL_AD_INTERNAL_ERROR; + SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM, ERR_R_INTERNAL_ERROR); + goto f_err; + } + } + } } #endif #ifndef OPENSSL_NO_DH - if ((alg_k & SSL_kDHE) && - !(has_bits(i, EVP_PK_DH | EVP_PKT_EXCH) || (dh != NULL))) { - SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM, SSL_R_MISSING_DH_KEY); + if ((alg_k & SSL_kDHE) && (dh == NULL)) { + al = SSL_AD_INTERNAL_ERROR; + SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM, ERR_R_INTERNAL_ERROR); goto f_err; } else if ((alg_k & SSL_kDHr) && !SSL_USE_SIGALGS(s) && !has_bits(i, EVP_PK_DH | EVP_PKS_RSA)) { @@ -3471,12 +3356,18 @@ int ssl3_check_cert_and_algorithm(SSL *s) # endif #endif - if (SSL_C_IS_EXPORT(s->s3->tmp.new_cipher) && !has_bits(i, EVP_PKT_EXP)) { + if (SSL_C_IS_EXPORT(s->s3->tmp.new_cipher) && + pkey_bits > SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher)) { #ifndef OPENSSL_NO_RSA if (alg_k & SSL_kRSA) { - if (rsa == NULL - || RSA_size(rsa) * 8 > + if (rsa == NULL) { + SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM, + SSL_R_MISSING_EXPORT_TMP_RSA_KEY); + goto f_err; + } else if (RSA_bits(rsa) > SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher)) { + /* We have a temporary RSA key but it's too large. */ + al = SSL_AD_EXPORT_RESTRICTION; SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM, SSL_R_MISSING_EXPORT_TMP_RSA_KEY); goto f_err; @@ -3484,14 +3375,21 @@ int ssl3_check_cert_and_algorithm(SSL *s) } else #endif #ifndef OPENSSL_NO_DH - if (alg_k & (SSL_kDHE | SSL_kDHr | SSL_kDHd)) { - if (dh == NULL - || DH_size(dh) * 8 > + if (alg_k & SSL_kDHE) { + if (DH_bits(dh) > SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher)) { + /* We have a temporary DH key but it's too large. */ + al = SSL_AD_EXPORT_RESTRICTION; SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM, SSL_R_MISSING_EXPORT_TMP_DH_KEY); goto f_err; } + } else if (alg_k & (SSL_kDHr | SSL_kDHd)) { + /* The cert should have had an export DH key. */ + al = SSL_AD_EXPORT_RESTRICTION; + SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM, + SSL_R_MISSING_EXPORT_TMP_DH_KEY); + goto f_err; } else #endif { @@ -3502,12 +3400,10 @@ int ssl3_check_cert_and_algorithm(SSL *s) } return (1); f_err: - ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE); - err: + ssl3_send_alert(s, SSL3_AL_FATAL, al); return (0); } -#ifndef OPENSSL_NO_TLSEXT /* * Normally, we can tell if the server is resuming the session from * the session ID. EAP-FAST (RFC 4851), however, relies on the next server @@ -3557,7 +3453,7 @@ static int ssl3_check_finished(SSL *s) return 0; } -# ifndef OPENSSL_NO_NEXTPROTONEG +#ifndef OPENSSL_NO_NEXTPROTONEG int ssl3_send_next_proto(SSL *s) { unsigned int len, padding_len; @@ -3580,7 +3476,6 @@ int ssl3_send_next_proto(SSL *s) return ssl3_do_write(s, SSL3_RT_HANDSHAKE); } -# endif #endif int ssl_do_client_cert_cb(SSL *s, X509 **px509, EVP_PKEY **ppkey) @@ -3599,3 +3494,65 @@ int ssl_do_client_cert_cb(SSL *s, X509 **px509, EVP_PKEY **ppkey) i = s->ctx->client_cert_cb(s, px509, ppkey); return i; } + +int ssl_cipher_list_to_bytes(SSL *s, STACK_OF(SSL_CIPHER) *sk, + unsigned char *p, + int (*put_cb) (const SSL_CIPHER *, + unsigned char *)) +{ + int i, j = 0; + SSL_CIPHER *c; + unsigned char *q; + int empty_reneg_info_scsv = !s->renegotiate; + /* Set disabled masks for this session */ + ssl_set_client_disabled(s); + + if (sk == NULL) + return (0); + q = p; + if (put_cb == NULL) + put_cb = s->method->put_cipher_by_char; + + for (i = 0; i < sk_SSL_CIPHER_num(sk); i++) { + c = sk_SSL_CIPHER_value(sk, i); + /* Skip disabled ciphers */ + if (ssl_cipher_disabled(s, c, SSL_SECOP_CIPHER_SUPPORTED)) + continue; +#ifdef OPENSSL_SSL_DEBUG_BROKEN_PROTOCOL + if (c->id == SSL3_CK_SCSV) { + if (!empty_reneg_info_scsv) + continue; + else + empty_reneg_info_scsv = 0; + } +#endif + j = put_cb(c, p); + p += j; + } + /* + * If p == q, no ciphers; caller indicates an error. Otherwise, add + * applicable SCSVs. + */ + if (p != q) { + if (empty_reneg_info_scsv) { + static SSL_CIPHER scsv = { + 0, NULL, SSL3_CK_SCSV, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; + j = put_cb(&scsv, p); + p += j; +#ifdef OPENSSL_RI_DEBUG + fprintf(stderr, + "TLS_EMPTY_RENEGOTIATION_INFO_SCSV sent by client\n"); +#endif + } + if (s->mode & SSL_MODE_SEND_FALLBACK_SCSV) { + static SSL_CIPHER scsv = { + 0, NULL, SSL3_CK_FALLBACK_SCSV, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; + j = put_cb(&scsv, p); + p += j; + } + } + + return (p - q); +}