X-Git-Url: https://git.openssl.org/?p=openssl.git;a=blobdiff_plain;f=ssl%2Fstatem%2Fstatem_srvr.c;h=a6841c3b4b6fe4b41f7603571dd914a0d86f0933;hp=bdeaf7e0e047a4251f2856e96c90c223676cc9cd;hb=cb21df32296a57150341aaa24131dfc668122df8;hpb=aa430c7467bcb7aa0a88fac45369e3dea7e13a23 diff --git a/ssl/statem/statem_srvr.c b/ssl/statem/statem_srvr.c index bdeaf7e0e0..a6841c3b4b 100644 --- a/ssl/statem/statem_srvr.c +++ b/ssl/statem/statem_srvr.c @@ -1,4 +1,3 @@ -/* ssl/statem/statem_srvr.c -*- mode:C; c-file-style: "eay" -*- */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -159,9 +158,7 @@ #include #include #include -#ifndef OPENSSL_NO_DH -# include -#endif +#include #include #include @@ -215,7 +212,7 @@ int ossl_statem_server_read_transition(SSL *s, int mt) if (mt == SSL3_MT_CERTIFICATE) { st->hand_state = TLS_ST_SR_CERT; return 1; - } + } } break; @@ -315,24 +312,14 @@ static int send_server_key_exchange(SSL *s) unsigned long alg_k = s->s3->tmp.new_cipher->algorithm_mkey; /* - * only send a ServerKeyExchange if DH, fortezza or RSA but we have a + * only send a ServerKeyExchange if DH or fortezza but we have a * sign only certificate PSK: may send PSK identity hints For * ECC ciphersuites, we send a serverKeyExchange message only if * the cipher suite is either ECDH-anon or ECDHE. In other cases, * the server certificate contains the server's public key for * key exchange. */ - if ( (alg_k & SSL_kDHE) - || (alg_k & SSL_kECDHE) - || ((alg_k & SSL_kRSA) - && (s->cert->pkeys[SSL_PKEY_RSA_ENC].privatekey == NULL - || (SSL_C_IS_EXPORT(s->s3->tmp.new_cipher) - && EVP_PKEY_size(s->cert->pkeys - [SSL_PKEY_RSA_ENC].privatekey) * - 8 > SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher) - ) - ) - ) + if (alg_k & (SSL_kDHE|SSL_kECDHE) /* * PSK: send ServerKeyExchange if PSK identity hint if * provided @@ -959,7 +946,7 @@ int dtls_construct_hello_verify_request(SSL *s) len = dtls_raw_hello_verify_request(&buf[DTLS1_HM_HEADER_LENGTH], s->d1->cookie, s->d1->cookie_len); - dtls1_set_message_header(s, buf, DTLS1_MT_HELLO_VERIFY_REQUEST, len, 0, + dtls1_set_message_header(s, DTLS1_MT_HELLO_VERIFY_REQUEST, len, 0, len); len += DTLS1_HM_HEADER_LENGTH; @@ -975,15 +962,16 @@ MSG_PROCESS_RETURN tls_process_client_hello(SSL *s, PACKET *pkt) int i, al = SSL_AD_INTERNAL_ERROR; unsigned int j, complen = 0; unsigned long id; - SSL_CIPHER *c; + const SSL_CIPHER *c; #ifndef OPENSSL_NO_COMP SSL_COMP *comp = NULL; #endif STACK_OF(SSL_CIPHER) *ciphers = NULL; - int protverr = 1; + int protverr; /* |cookie| will only be initialized for DTLS. */ PACKET session_id, cipher_suites, compression, extensions, cookie; int is_v2_record; + static unsigned char null_compression = 0; is_v2_record = RECORD_LAYER_is_sslv2_record(&s->rlayer); @@ -1047,63 +1035,21 @@ MSG_PROCESS_RETURN tls_process_client_hello(SSL *s, PACKET *pkt) } } - /* Do SSL/TLS version negotiation if applicable */ + /* + * Do SSL/TLS version negotiation if applicable. For DTLS we just check + * versions are potentially compatible. Version negotiation comes later. + */ if (!SSL_IS_DTLS(s)) { - if (s->version != TLS_ANY_VERSION) { - if (s->client_version >= s->version) { - protverr = 0; - } - } else if (s->client_version >= SSL3_VERSION) { - switch(s->client_version) { - default: - case TLS1_2_VERSION: - if(!(s->options & SSL_OP_NO_TLSv1_2)) { - s->version = TLS1_2_VERSION; - s->method = TLSv1_2_server_method(); - protverr = 0; - break; - } - /* Deliberately fall through */ - case TLS1_1_VERSION: - if(!(s->options & SSL_OP_NO_TLSv1_1)) { - s->version = TLS1_1_VERSION; - s->method = TLSv1_1_server_method(); - protverr = 0; - break; - } - /* Deliberately fall through */ - case TLS1_VERSION: - if(!(s->options & SSL_OP_NO_TLSv1)) { - s->version = TLS1_VERSION; - s->method = TLSv1_server_method(); - protverr = 0; - break; - } - /* Deliberately fall through */ - case SSL3_VERSION: -#ifndef OPENSSL_NO_SSL3 - if(!(s->options & SSL_OP_NO_SSLv3)) { - s->version = SSL3_VERSION; - s->method = SSLv3_server_method(); - protverr = 0; - break; - } -#else - break; -#endif - } - } - } else if (s->client_version <= s->version - || s->method->version == DTLS_ANY_VERSION) { - /* - * For DTLS we just check versions are potentially compatible. Version - * negotiation comes later. - */ + protverr = ssl_choose_server_version(s); + } else if (s->method->version != DTLS_ANY_VERSION && + DTLS_VERSION_LT(s->client_version, s->version)) { + protverr = SSL_R_VERSION_TOO_LOW; + } else { protverr = 0; } if (protverr) { - SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, SSL_R_UNKNOWN_PROTOCOL); + SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, protverr); if ((!s->enc_write_ctx && !s->write_hash)) { /* * similar to ssl3_get_record, send alert using remote version @@ -1134,6 +1080,12 @@ MSG_PROCESS_RETURN tls_process_client_hello(SSL *s, PACKET *pkt) goto f_err; } + if (session_id_len > SSL_MAX_SSL_SESSION_ID_LENGTH) { + al = SSL_AD_DECODE_ERROR; + SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, SSL_R_LENGTH_MISMATCH); + goto f_err; + } + if (!PACKET_get_sub_packet(pkt, &cipher_suites, cipher_len) || !PACKET_get_sub_packet(pkt, &session_id, session_id_len) || !PACKET_get_sub_packet(pkt, &challenge, challenge_len) @@ -1145,19 +1097,20 @@ MSG_PROCESS_RETURN tls_process_client_hello(SSL *s, PACKET *pkt) goto f_err; } - /* Load the client random */ + /* Load the client random and compression list. */ challenge_len = challenge_len > SSL3_RANDOM_SIZE ? SSL3_RANDOM_SIZE : challenge_len; memset(s->s3->client_random, 0, SSL3_RANDOM_SIZE); if (!PACKET_copy_bytes(&challenge, s->s3->client_random + SSL3_RANDOM_SIZE - - challenge_len, challenge_len)) { + challenge_len, challenge_len) + /* Advertise only null compression. */ + || !PACKET_buf_init(&compression, &null_compression, 1)) { SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, ERR_R_INTERNAL_ERROR); al = SSL_AD_INTERNAL_ERROR; goto f_err; } - PACKET_null_init(&compression); PACKET_null_init(&extensions); } else { /* Regular ClientHello. */ @@ -1168,6 +1121,12 @@ MSG_PROCESS_RETURN tls_process_client_hello(SSL *s, PACKET *pkt) goto f_err; } + if (PACKET_remaining(&session_id) > SSL_MAX_SSL_SESSION_ID_LENGTH) { + al = SSL_AD_DECODE_ERROR; + SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, SSL_R_LENGTH_MISMATCH); + goto f_err; + } + if (SSL_IS_DTLS(s)) { if (!PACKET_get_length_prefixed_1(pkt, &cookie)) { al = SSL_AD_DECODE_ERROR; @@ -1195,6 +1154,38 @@ MSG_PROCESS_RETURN tls_process_client_hello(SSL *s, PACKET *pkt) extensions = *pkt; } + if (SSL_IS_DTLS(s)) { + /* Empty cookie was already handled above by returning early. */ + if (SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE) { + if (s->ctx->app_verify_cookie_cb != NULL) { + if (s->ctx->app_verify_cookie_cb(s, PACKET_data(&cookie), + PACKET_remaining(&cookie)) == 0) { + al = SSL_AD_HANDSHAKE_FAILURE; + SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, + SSL_R_COOKIE_MISMATCH); + goto f_err; + /* else cookie verification succeeded */ + } + /* default verification */ + } else if (!PACKET_equal(&cookie, s->d1->cookie, + s->d1->cookie_len)) { + al = SSL_AD_HANDSHAKE_FAILURE; + SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, SSL_R_COOKIE_MISMATCH); + goto f_err; + } + s->d1->cookie_verified = 1; + } + if (s->method->version == DTLS_ANY_VERSION) { + protverr = ssl_choose_server_version(s); + if (protverr != 0) { + SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, protverr); + s->version = s->client_version; + al = SSL_AD_PROTOCOL_VERSION; + goto f_err; + } + } + } + s->hit = 0; /* @@ -1241,54 +1232,6 @@ MSG_PROCESS_RETURN tls_process_client_hello(SSL *s, PACKET *pkt) } } - if (SSL_IS_DTLS(s)) { - /* Empty cookie was already handled above by returning early. */ - if (SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE) { - if (s->ctx->app_verify_cookie_cb != NULL) { - if (s->ctx->app_verify_cookie_cb(s, PACKET_data(&cookie), - PACKET_remaining(&cookie)) == 0) { - al = SSL_AD_HANDSHAKE_FAILURE; - SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, - SSL_R_COOKIE_MISMATCH); - goto f_err; - /* else cookie verification succeeded */ - } - /* default verification */ - } else if (!PACKET_equal(&cookie, s->d1->cookie, - s->d1->cookie_len)) { - al = SSL_AD_HANDSHAKE_FAILURE; - SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, SSL_R_COOKIE_MISMATCH); - goto f_err; - } - s->d1->cookie_verified = 1; - } - if (s->method->version == DTLS_ANY_VERSION) { - /* Select version to use */ - if (s->client_version <= DTLS1_2_VERSION && - !(s->options & SSL_OP_NO_DTLSv1_2)) { - s->version = DTLS1_2_VERSION; - s->method = DTLSv1_2_server_method(); - } else if (tls1_suiteb(s)) { - SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, - SSL_R_ONLY_DTLS_1_2_ALLOWED_IN_SUITEB_MODE); - s->version = s->client_version; - al = SSL_AD_PROTOCOL_VERSION; - goto f_err; - } else if (s->client_version <= DTLS1_VERSION && - !(s->options & SSL_OP_NO_DTLSv1)) { - s->version = DTLS1_VERSION; - s->method = DTLSv1_server_method(); - } else { - SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, - SSL_R_WRONG_VERSION_NUMBER); - s->version = s->client_version; - al = SSL_AD_PROTOCOL_VERSION; - goto f_err; - } - s->session->ssl_version = s->version; - } - } - if (ssl_bytes_to_cipher_list(s, &cipher_suites, &(ciphers), is_v2_record, &al) == NULL) { goto f_err; @@ -1338,7 +1281,7 @@ MSG_PROCESS_RETURN tls_process_client_hello(SSL *s, PACKET *pkt) SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, SSL_R_NO_COMPRESSION_SPECIFIED); goto f_err; } - + /* TLS extensions */ if (s->version >= SSL3_VERSION) { if (!ssl_parse_clienthello_tlsext(s, &extensions)) { @@ -1362,7 +1305,7 @@ MSG_PROCESS_RETURN tls_process_client_hello(SSL *s, PACKET *pkt) } if (!s->hit && s->version >= TLS1_VERSION && s->tls_session_secret_cb) { - SSL_CIPHER *pref_cipher = NULL; + const SSL_CIPHER *pref_cipher = NULL; s->session->master_key_length = sizeof(s->session->master_key); if (s->tls_session_secret_cb(s, s->session->master_key, @@ -1435,7 +1378,7 @@ MSG_PROCESS_RETURN tls_process_client_hello(SSL *s, PACKET *pkt) if (k >= complen) { al = SSL_AD_ILLEGAL_PARAMETER; SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, - SSL_R_REQUIRED_COMPRESSSION_ALGORITHM_MISSING); + SSL_R_REQUIRED_COMPRESSION_ALGORITHM_MISSING); goto f_err; } } else if (s->hit) @@ -1513,7 +1456,7 @@ MSG_PROCESS_RETURN tls_process_client_hello(SSL *s, PACKET *pkt) WORK_STATE tls_post_process_client_hello(SSL *s, WORK_STATE wst) { int al = SSL_AD_HANDSHAKE_FAILURE; - SSL_CIPHER *cipher; + const SSL_CIPHER *cipher; if (wst == WORK_MORE_A) { if (!s->hit) { @@ -1723,18 +1666,13 @@ int tls_construct_server_done(SSL *s) int tls_construct_server_key_exchange(SSL *s) { -#ifndef OPENSSL_NO_RSA - RSA *rsa; -#endif #ifndef OPENSSL_NO_DH - DH *dh = NULL, *dhp; + EVP_PKEY *pkdh = NULL; #endif #ifndef OPENSSL_NO_EC - EC_KEY *ecdh = NULL, *ecdhp; unsigned char *encodedPoint = NULL; int encodedlen = 0; int curve_id = 0; - BN_CTX *bn_ctx = NULL; #endif EVP_PKEY *pkey; const EVP_MD *md = NULL; @@ -1742,16 +1680,18 @@ int tls_construct_server_key_exchange(SSL *s) int al, i; unsigned long type; int n; - CERT *cert; BIGNUM *r[4]; int nr[4], kn; BUF_MEM *buf; - EVP_MD_CTX md_ctx; + EVP_MD_CTX *md_ctx = EVP_MD_CTX_new(); - EVP_MD_CTX_init(&md_ctx); + if (md_ctx == NULL) { + SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE); + al = SSL_AD_INTERNAL_ERROR; + goto f_err; + } type = s->s3->tmp.new_cipher->algorithm_mkey; - cert = s->cert; buf = s->init_buf; @@ -1770,216 +1710,114 @@ int tls_construct_server_key_exchange(SSL *s) if (type & (SSL_kPSK | SSL_kRSAPSK)) { } else #endif /* !OPENSSL_NO_PSK */ -#ifndef OPENSSL_NO_RSA - if (type & SSL_kRSA) { - rsa = cert->rsa_tmp; - if ((rsa == NULL) && (s->cert->rsa_tmp_cb != NULL)) { - rsa = s->cert->rsa_tmp_cb(s, - SSL_C_IS_EXPORT(s->s3-> - tmp.new_cipher), - SSL_C_EXPORT_PKEYLENGTH(s->s3-> - tmp.new_cipher)); - if (rsa == NULL) { - al = SSL_AD_HANDSHAKE_FAILURE; +#ifndef OPENSSL_NO_DH + if (type & (SSL_kDHE | SSL_kDHEPSK)) { + CERT *cert = s->cert; + + EVP_PKEY *pkdhp = NULL; + DH *dh; + + if (s->cert->dh_tmp_auto) { + DH *dhp = ssl_get_auto_dh(s); + pkdh = EVP_PKEY_new(); + if (pkdh == NULL || dhp == NULL) { + DH_free(dhp); + al = SSL_AD_INTERNAL_ERROR; SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, - SSL_R_ERROR_GENERATING_TMP_RSA_KEY); + ERR_R_INTERNAL_ERROR); goto f_err; } - RSA_up_ref(rsa); - cert->rsa_tmp = rsa; - } - if (rsa == NULL) { - al = SSL_AD_HANDSHAKE_FAILURE; - SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, - SSL_R_MISSING_TMP_RSA_KEY); - goto f_err; + EVP_PKEY_assign_DH(pkdh, dhp); + pkdhp = pkdh; + } else { + pkdhp = cert->dh_tmp; } - r[0] = rsa->n; - r[1] = rsa->e; - s->s3->tmp.use_rsa_tmp = 1; - } else -#endif -#ifndef OPENSSL_NO_DH - if (type & (SSL_kDHE | SSL_kDHEPSK)) { - if (s->cert->dh_tmp_auto) { - dhp = ssl_get_auto_dh(s); - if (dhp == NULL) { + if ((pkdhp == NULL) && (s->cert->dh_tmp_cb != NULL)) { + DH *dhp = s->cert->dh_tmp_cb(s, 0, 1024); + pkdh = ssl_dh_to_pkey(dhp); + if (pkdh == NULL) { al = SSL_AD_INTERNAL_ERROR; SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR); goto f_err; } - } else - dhp = cert->dh_tmp; - if ((dhp == NULL) && (s->cert->dh_tmp_cb != NULL)) - dhp = s->cert->dh_tmp_cb(s, - SSL_C_IS_EXPORT(s->s3-> - tmp.new_cipher), - SSL_C_EXPORT_PKEYLENGTH(s->s3-> - tmp.new_cipher)); - if (dhp == NULL) { + pkdhp = pkdh; + } + if (pkdhp == NULL) { al = SSL_AD_HANDSHAKE_FAILURE; SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, SSL_R_MISSING_TMP_DH_KEY); goto f_err; } if (!ssl_security(s, SSL_SECOP_TMP_DH, - DH_security_bits(dhp), 0, dhp)) { + EVP_PKEY_security_bits(pkdhp), 0, pkdhp)) { al = SSL_AD_HANDSHAKE_FAILURE; SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, SSL_R_DH_KEY_TOO_SMALL); goto f_err; } - if (s->s3->tmp.dh != NULL) { + if (s->s3->tmp.pkey != NULL) { SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR); goto err; } - if (s->cert->dh_tmp_auto) - dh = dhp; - else if ((dh = DHparams_dup(dhp)) == NULL) { - SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, ERR_R_DH_LIB); + s->s3->tmp.pkey = ssl_generate_pkey(pkdhp, NID_undef); + + if (s->s3->tmp.pkey == NULL) { + SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, ERR_R_EVP_LIB); goto err; } - s->s3->tmp.dh = dh; - if ((dhp->pub_key == NULL || - dhp->priv_key == NULL || - (s->options & SSL_OP_SINGLE_DH_USE))) { - if (!DH_generate_key(dh)) { - SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, ERR_R_DH_LIB); - goto err; - } - } else { - dh->pub_key = BN_dup(dhp->pub_key); - dh->priv_key = BN_dup(dhp->priv_key); - if ((dh->pub_key == NULL) || (dh->priv_key == NULL)) { - SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, ERR_R_DH_LIB); - goto err; - } - } - r[0] = dh->p; - r[1] = dh->g; - r[2] = dh->pub_key; + dh = EVP_PKEY_get0_DH(s->s3->tmp.pkey); + + EVP_PKEY_free(pkdh); + pkdh = NULL; + + DH_get0_pqg(dh, &r[0], NULL, &r[1]); + DH_get0_key(dh, &r[2], NULL); } else #endif #ifndef OPENSSL_NO_EC if (type & (SSL_kECDHE | SSL_kECDHEPSK)) { - const EC_GROUP *group; - - ecdhp = cert->ecdh_tmp; - if (s->cert->ecdh_tmp_auto) { - /* Get NID of appropriate shared curve */ - int nid = tls1_shared_curve(s, -2); - if (nid != NID_undef) - ecdhp = EC_KEY_new_by_curve_name(nid); - } else if ((ecdhp == NULL) && s->cert->ecdh_tmp_cb) { - ecdhp = s->cert->ecdh_tmp_cb(s, - SSL_C_IS_EXPORT(s->s3-> - tmp.new_cipher), - SSL_C_EXPORT_PKEYLENGTH(s-> - s3->tmp.new_cipher)); - } - if (ecdhp == NULL) { - al = SSL_AD_HANDSHAKE_FAILURE; - SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, - SSL_R_MISSING_TMP_ECDH_KEY); - goto f_err; - } + int nid; - if (s->s3->tmp.ecdh != NULL) { + if (s->s3->tmp.pkey != NULL) { SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR); goto err; } - /* Duplicate the ECDH structure. */ - if (ecdhp == NULL) { - SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, ERR_R_ECDH_LIB); - goto err; - } - if (s->cert->ecdh_tmp_auto) - ecdh = ecdhp; - else if ((ecdh = EC_KEY_dup(ecdhp)) == NULL) { - SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, ERR_R_ECDH_LIB); - goto err; - } - - s->s3->tmp.ecdh = ecdh; - if ((EC_KEY_get0_public_key(ecdh) == NULL) || - (EC_KEY_get0_private_key(ecdh) == NULL) || - (s->options & SSL_OP_SINGLE_ECDH_USE)) { - if (!EC_KEY_generate_key(ecdh)) { - SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, - ERR_R_ECDH_LIB); - goto err; - } - } - - if (((group = EC_KEY_get0_group(ecdh)) == NULL) || - (EC_KEY_get0_public_key(ecdh) == NULL) || - (EC_KEY_get0_private_key(ecdh) == NULL)) { - SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, ERR_R_ECDH_LIB); - goto err; - } - - if (SSL_C_IS_EXPORT(s->s3->tmp.new_cipher) && - (EC_GROUP_get_degree(group) > 163)) { - SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, - SSL_R_ECGROUP_TOO_LARGE_FOR_CIPHER); - goto err; - } - - /* - * XXX: For now, we only support ephemeral ECDH keys over named - * (not generic) curves. For supported named curves, curve_id is - * non-zero. - */ - if ((curve_id = - tls1_ec_nid2curve_id(EC_GROUP_get_curve_name(group))) - == 0) { + /* Get NID of appropriate shared curve */ + nid = tls1_shared_curve(s, -2); + curve_id = tls1_ec_nid2curve_id(nid); + if (curve_id == 0) { SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, SSL_R_UNSUPPORTED_ELLIPTIC_CURVE); goto err; } - - /* - * Encode the public key. First check the size of encoding and - * allocate memory accordingly. - */ - encodedlen = EC_POINT_point2oct(group, - EC_KEY_get0_public_key(ecdh), - POINT_CONVERSION_UNCOMPRESSED, - NULL, 0, NULL); - - encodedPoint = (unsigned char *) - OPENSSL_malloc(encodedlen * sizeof(unsigned char)); - bn_ctx = BN_CTX_new(); - if ((encodedPoint == NULL) || (bn_ctx == NULL)) { - SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, - ERR_R_MALLOC_FAILURE); - goto err; + s->s3->tmp.pkey = ssl_generate_pkey(NULL, nid); + /* Generate a new key for this curve */ + if (s->s3->tmp.pkey == NULL) { + al = SSL_AD_INTERNAL_ERROR; + SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, ERR_R_EVP_LIB); + goto f_err; } - encodedlen = EC_POINT_point2oct(group, - EC_KEY_get0_public_key(ecdh), - POINT_CONVERSION_UNCOMPRESSED, - encodedPoint, encodedlen, bn_ctx); + /* Encode the public key. */ + encodedlen = EC_KEY_key2buf(EVP_PKEY_get0_EC_KEY(s->s3->tmp.pkey), + POINT_CONVERSION_UNCOMPRESSED, + &encodedPoint, NULL); if (encodedlen == 0) { - SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, ERR_R_ECDH_LIB); + SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, ERR_R_EC_LIB); goto err; } - BN_CTX_free(bn_ctx); - bn_ctx = NULL; - /* - * XXX: For now, we only support named (not generic) curves in - * ECDH ephemeral key exchanges. In this situation, we need four - * additional bytes to encode the entire ServerECDHParams - * structure. + * We only support named (not generic) curves in ECDH ephemeral key + * exchanges. In this situation, we need four additional bytes to + * encode the entire ServerECDHParams structure. */ n += 4 + encodedlen; @@ -2113,13 +1951,13 @@ int tls_construct_server_key_exchange(SSL *s) #ifdef SSL_DEBUG fprintf(stderr, "Using hash %s\n", EVP_MD_name(md)); #endif - if (EVP_SignInit_ex(&md_ctx, md, NULL) <= 0 - || EVP_SignUpdate(&md_ctx, &(s->s3->client_random[0]), + if (EVP_SignInit_ex(md_ctx, md, NULL) <= 0 + || EVP_SignUpdate(md_ctx, &(s->s3->client_random[0]), SSL3_RANDOM_SIZE) <= 0 - || EVP_SignUpdate(&md_ctx, &(s->s3->server_random[0]), + || EVP_SignUpdate(md_ctx, &(s->s3->server_random[0]), SSL3_RANDOM_SIZE) <= 0 - || EVP_SignUpdate(&md_ctx, d, n) <= 0 - || EVP_SignFinal(&md_ctx, &(p[2]), + || EVP_SignUpdate(md_ctx, d, n) <= 0 + || EVP_SignFinal(md_ctx, &(p[2]), (unsigned int *)&i, pkey) <= 0) { SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, ERR_LIB_EVP); al = SSL_AD_INTERNAL_ERROR; @@ -2144,16 +1982,18 @@ int tls_construct_server_key_exchange(SSL *s) goto f_err; } - EVP_MD_CTX_cleanup(&md_ctx); + EVP_MD_CTX_free(md_ctx); return 1; f_err: ssl3_send_alert(s, SSL3_AL_FATAL, al); err: +#ifndef OPENSSL_NO_DH + EVP_PKEY_free(pkdh); +#endif #ifndef OPENSSL_NO_EC OPENSSL_free(encodedPoint); - BN_CTX_free(bn_ctx); #endif - EVP_MD_CTX_cleanup(&md_ctx); + EVP_MD_CTX_free(md_ctx); ossl_statem_set_error(s); return 0; } @@ -2233,24 +2073,15 @@ int tls_construct_certificate_request(SSL *s) MSG_PROCESS_RETURN tls_process_client_key_exchange(SSL *s, PACKET *pkt) { int al; - unsigned int i; unsigned long alg_k; #ifndef OPENSSL_NO_RSA RSA *rsa = NULL; - EVP_PKEY *pkey = NULL; -#endif -#ifndef OPENSSL_NO_DH - BIGNUM *pub = NULL; - DH *dh_srvr, *dh_clnt = NULL; #endif -#ifndef OPENSSL_NO_EC - EC_KEY *srvr_ecdh = NULL; - EVP_PKEY *clnt_pub_pkey = NULL; - EC_POINT *clnt_ecpoint = NULL; - BN_CTX *bn_ctx = NULL; +#if !defined(OPENSSL_NO_EC) || !defined(OPENSSL_NO_DH) + EVP_PKEY *ckey = NULL; #endif PACKET enc_premaster; - unsigned char *data, *rsa_decrypt = NULL; + unsigned char *rsa_decrypt = NULL; alg_k = s->s3->tmp.new_cipher->algorithm_mkey; @@ -2303,7 +2134,7 @@ MSG_PROCESS_RETURN tls_process_client_key_exchange(SSL *s, PACKET *pkt) } OPENSSL_free(s->s3->tmp.psk); - s->s3->tmp.psk = BUF_memdup(psk, psklen); + s->s3->tmp.psk = OPENSSL_memdup(psk, psklen); OPENSSL_cleanse(psk, psklen); if (s->s3->tmp.psk == NULL) { @@ -2337,47 +2168,24 @@ MSG_PROCESS_RETURN tls_process_client_key_exchange(SSL *s, PACKET *pkt) size_t j; /* FIX THIS UP EAY EAY EAY EAY */ - if (s->s3->tmp.use_rsa_tmp) { - if ((s->cert != NULL) && (s->cert->rsa_tmp != NULL)) - rsa = s->cert->rsa_tmp; - /* - * Don't do a callback because rsa_tmp should be sent already - */ - if (rsa == NULL) { - al = SSL_AD_HANDSHAKE_FAILURE; - SSLerr(SSL_F_TLS_PROCESS_CLIENT_KEY_EXCHANGE, - SSL_R_MISSING_TMP_RSA_PKEY); - goto f_err; - - } - } else { - pkey = s->cert->pkeys[SSL_PKEY_RSA_ENC].privatekey; - if ((pkey == NULL) || - (pkey->type != EVP_PKEY_RSA) || (pkey->pkey.rsa == NULL)) { - al = SSL_AD_HANDSHAKE_FAILURE; - SSLerr(SSL_F_TLS_PROCESS_CLIENT_KEY_EXCHANGE, - SSL_R_MISSING_RSA_CERTIFICATE); - goto f_err; - } - rsa = pkey->pkey.rsa; + rsa = EVP_PKEY_get0_RSA(s->cert->pkeys[SSL_PKEY_RSA_ENC].privatekey); + if (rsa == NULL) { + al = SSL_AD_HANDSHAKE_FAILURE; + SSLerr(SSL_F_TLS_PROCESS_CLIENT_KEY_EXCHANGE, + SSL_R_MISSING_RSA_CERTIFICATE); + goto f_err; } /* SSLv3 and pre-standard DTLS omit the length bytes. */ if (s->version == SSL3_VERSION || s->version == DTLS1_BAD_VER) { enc_premaster = *pkt; } else { - PACKET orig = *pkt; if (!PACKET_get_length_prefixed_2(pkt, &enc_premaster) || PACKET_remaining(pkt) != 0) { - /* Try SSLv3 behaviour for TLS. */ - if (s->options & SSL_OP_TLS_D5_BUG) { - enc_premaster = orig; - } else { - al = SSL_AD_DECODE_ERROR; - SSLerr(SSL_F_TLS_PROCESS_CLIENT_KEY_EXCHANGE, - SSL_R_LENGTH_MISMATCH); - goto f_err; - } + al = SSL_AD_DECODE_ERROR; + SSLerr(SSL_F_TLS_PROCESS_CLIENT_KEY_EXCHANGE, + SSL_R_LENGTH_MISMATCH); + goto f_err; } } @@ -2489,11 +2297,12 @@ MSG_PROCESS_RETURN tls_process_client_key_exchange(SSL *s, PACKET *pkt) } else #endif #ifndef OPENSSL_NO_DH - if (alg_k & (SSL_kDHE | SSL_kDHr | SSL_kDHd | SSL_kDHEPSK)) { - int idx = -1; + if (alg_k & (SSL_kDHE | SSL_kDHEPSK)) { EVP_PKEY *skey = NULL; - PACKET bookmark = *pkt; - unsigned char shared[(OPENSSL_DH_MAX_MODULUS_BITS + 7) / 8]; + DH *cdh; + unsigned int i; + BIGNUM *pub_key; + const unsigned char *data; if (!PACKET_get_net_2(pkt, &i)) { if (alg_k & (SSL_kDHE | SSL_kDHEPSK)) { @@ -2505,177 +2314,78 @@ MSG_PROCESS_RETURN tls_process_client_key_exchange(SSL *s, PACKET *pkt) i = 0; } if (PACKET_remaining(pkt) != i) { - if (!(s->options & SSL_OP_SSLEAY_080_CLIENT_DH_BUG)) { - SSLerr(SSL_F_TLS_PROCESS_CLIENT_KEY_EXCHANGE, - SSL_R_DH_PUBLIC_VALUE_LENGTH_IS_WRONG); - goto err; - } else { - *pkt = bookmark; - i = PACKET_remaining(pkt); - } + SSLerr(SSL_F_TLS_PROCESS_CLIENT_KEY_EXCHANGE, + SSL_R_DH_PUBLIC_VALUE_LENGTH_IS_WRONG); + goto err; } - if (alg_k & SSL_kDHr) - idx = SSL_PKEY_DH_RSA; - else if (alg_k & SSL_kDHd) - idx = SSL_PKEY_DH_DSA; - if (idx >= 0) { - skey = s->cert->pkeys[idx].privatekey; - if ((skey == NULL) || - (skey->type != EVP_PKEY_DH) || (skey->pkey.dh == NULL)) { - al = SSL_AD_HANDSHAKE_FAILURE; - SSLerr(SSL_F_TLS_PROCESS_CLIENT_KEY_EXCHANGE, - SSL_R_MISSING_RSA_CERTIFICATE); - goto f_err; - } - dh_srvr = skey->pkey.dh; - } else if (s->s3->tmp.dh == NULL) { + skey = s->s3->tmp.pkey; + if (skey == NULL) { al = SSL_AD_HANDSHAKE_FAILURE; SSLerr(SSL_F_TLS_PROCESS_CLIENT_KEY_EXCHANGE, SSL_R_MISSING_TMP_DH_KEY); goto f_err; - } else - dh_srvr = s->s3->tmp.dh; + } if (PACKET_remaining(pkt) == 0L) { - /* Get pubkey from cert */ - EVP_PKEY *clkey = X509_get_pubkey(s->session->peer); - if (clkey) { - if (EVP_PKEY_cmp_parameters(clkey, skey) == 1) - dh_clnt = EVP_PKEY_get1_DH(clkey); - } - if (dh_clnt == NULL) { - al = SSL_AD_HANDSHAKE_FAILURE; - SSLerr(SSL_F_TLS_PROCESS_CLIENT_KEY_EXCHANGE, - SSL_R_MISSING_TMP_DH_KEY); - goto f_err; - } - EVP_PKEY_free(clkey); - pub = dh_clnt->pub_key; - } else { - if (!PACKET_get_bytes(pkt, &data, i)) { - /* We already checked we have enough data */ - al = SSL_AD_INTERNAL_ERROR; - SSLerr(SSL_F_TLS_PROCESS_CLIENT_KEY_EXCHANGE, - ERR_R_INTERNAL_ERROR); - goto f_err; - } - pub = BN_bin2bn(data, i, NULL); + al = SSL_AD_HANDSHAKE_FAILURE; + SSLerr(SSL_F_TLS_PROCESS_CLIENT_KEY_EXCHANGE, + SSL_R_MISSING_TMP_DH_KEY); + goto f_err; } - if (pub == NULL) { + if (!PACKET_get_bytes(pkt, &data, i)) { + /* We already checked we have enough data */ + al = SSL_AD_INTERNAL_ERROR; + SSLerr(SSL_F_TLS_PROCESS_CLIENT_KEY_EXCHANGE, + ERR_R_INTERNAL_ERROR); + goto f_err; + } + ckey = EVP_PKEY_new(); + if (ckey == NULL || EVP_PKEY_copy_parameters(ckey, skey) == 0) { SSLerr(SSL_F_TLS_PROCESS_CLIENT_KEY_EXCHANGE, SSL_R_BN_LIB); goto err; } + cdh = EVP_PKEY_get0_DH(ckey); + pub_key = BN_bin2bn(data, i, NULL); - i = DH_compute_key(shared, pub, dh_srvr); - - if (i <= 0) { - SSLerr(SSL_F_TLS_PROCESS_CLIENT_KEY_EXCHANGE, ERR_R_DH_LIB); - BN_clear_free(pub); + if (pub_key == NULL || !DH_set0_key(cdh, pub_key, NULL)) { + SSLerr(SSL_F_TLS_PROCESS_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR); + if (pub_key != NULL) + BN_free(pub_key); goto err; } - DH_free(s->s3->tmp.dh); - s->s3->tmp.dh = NULL; - if (dh_clnt) - DH_free(dh_clnt); - else - BN_clear_free(pub); - pub = NULL; - if (!ssl_generate_master_secret(s, shared, i, 0)) { + if (ssl_derive(s, skey, ckey) == 0) { al = SSL_AD_INTERNAL_ERROR; SSLerr(SSL_F_TLS_PROCESS_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR); goto f_err; } - if (dh_clnt) { - s->statem.no_cert_verify = 1; - return MSG_PROCESS_CONTINUE_PROCESSING; - } + + EVP_PKEY_free(ckey); + ckey = NULL; + EVP_PKEY_free(s->s3->tmp.pkey); + s->s3->tmp.pkey = NULL; + } else #endif #ifndef OPENSSL_NO_EC - if (alg_k & (SSL_kECDHE | SSL_kECDHr | SSL_kECDHe | SSL_kECDHEPSK)) { - int field_size = 0; - const EC_KEY *tkey; - const EC_GROUP *group; - const BIGNUM *priv_key; - unsigned char *shared; - - /* initialize structures for server's ECDH key pair */ - if ((srvr_ecdh = EC_KEY_new()) == NULL) { - SSLerr(SSL_F_TLS_PROCESS_CLIENT_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE); - goto err; - } - - /* Let's get server private key and group information */ - if (alg_k & (SSL_kECDHr | SSL_kECDHe)) { - /* use the certificate */ - tkey = s->cert->pkeys[SSL_PKEY_ECC].privatekey->pkey.ec; - } else { - /* - * use the ephermeral values we saved when generating the - * ServerKeyExchange msg. - */ - tkey = s->s3->tmp.ecdh; - } - - group = EC_KEY_get0_group(tkey); - priv_key = EC_KEY_get0_private_key(tkey); - - if (!EC_KEY_set_group(srvr_ecdh, group) || - !EC_KEY_set_private_key(srvr_ecdh, priv_key)) { - SSLerr(SSL_F_TLS_PROCESS_CLIENT_KEY_EXCHANGE, ERR_R_EC_LIB); - goto err; - } - - /* Let's get client's public key */ - if ((clnt_ecpoint = EC_POINT_new(group)) == NULL) { - SSLerr(SSL_F_TLS_PROCESS_CLIENT_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE); - goto err; - } + if (alg_k & (SSL_kECDHE | SSL_kECDHEPSK)) { + EVP_PKEY *skey = s->s3->tmp.pkey; if (PACKET_remaining(pkt) == 0L) { - /* Client Publickey was in Client Certificate */ - - if (alg_k & (SSL_kECDHE | SSL_kECDHEPSK)) { - al = SSL_AD_HANDSHAKE_FAILURE; - SSLerr(SSL_F_TLS_PROCESS_CLIENT_KEY_EXCHANGE, - SSL_R_MISSING_TMP_ECDH_KEY); - goto f_err; - } - if (((clnt_pub_pkey = X509_get_pubkey(s->session->peer)) - == NULL) || (clnt_pub_pkey->type != EVP_PKEY_EC)) { - /* - * XXX: For now, we do not support client authentication - * using ECDH certificates so this branch (n == 0L) of the - * code is never executed. When that support is added, we - * ought to ensure the key received in the certificate is - * authorized for key agreement. ECDH_compute_key implicitly - * checks that the two ECDH shares are for the same group. - */ - al = SSL_AD_HANDSHAKE_FAILURE; - SSLerr(SSL_F_TLS_PROCESS_CLIENT_KEY_EXCHANGE, - SSL_R_UNABLE_TO_DECODE_ECDH_CERTS); - goto f_err; - } - - if (EC_POINT_copy(clnt_ecpoint, - EC_KEY_get0_public_key(clnt_pub_pkey-> - pkey.ec)) == 0) { - SSLerr(SSL_F_TLS_PROCESS_CLIENT_KEY_EXCHANGE, ERR_R_EC_LIB); - goto err; - } - s->statem.no_cert_verify = 1; + /* We don't support ECDH client auth */ + al = SSL_AD_HANDSHAKE_FAILURE; + SSLerr(SSL_F_TLS_PROCESS_CLIENT_KEY_EXCHANGE, + SSL_R_MISSING_TMP_ECDH_KEY); + goto f_err; } else { + unsigned int i; + const unsigned char *data; + /* * Get client's public key from encoded point in the * ClientKeyExchange message. */ - if ((bn_ctx = BN_CTX_new()) == NULL) { - SSLerr(SSL_F_TLS_PROCESS_CLIENT_KEY_EXCHANGE, - ERR_R_MALLOC_FAILURE); - goto err; - } /* Get encoded point length */ if (!PACKET_get_1(pkt, &i)) { @@ -2689,48 +2399,37 @@ MSG_PROCESS_RETURN tls_process_client_key_exchange(SSL *s, PACKET *pkt) SSLerr(SSL_F_TLS_PROCESS_CLIENT_KEY_EXCHANGE, ERR_R_EC_LIB); goto err; } - if (EC_POINT_oct2point(group, clnt_ecpoint, data, i, bn_ctx) == 0) { + ckey = EVP_PKEY_new(); + if (ckey == NULL || EVP_PKEY_copy_parameters(ckey, skey) <= 0) { + SSLerr(SSL_F_TLS_PROCESS_CLIENT_KEY_EXCHANGE, ERR_R_EVP_LIB); + goto err; + } + if (EC_KEY_oct2key(EVP_PKEY_get0_EC_KEY(ckey), data, i, + NULL) == 0) { SSLerr(SSL_F_TLS_PROCESS_CLIENT_KEY_EXCHANGE, ERR_R_EC_LIB); goto err; } } - /* Compute the shared pre-master secret */ - field_size = EC_GROUP_get_degree(group); - if (field_size <= 0) { - SSLerr(SSL_F_TLS_PROCESS_CLIENT_KEY_EXCHANGE, ERR_R_ECDH_LIB); - goto err; - } - shared = OPENSSL_malloc((field_size + 7) / 8); - if (shared == NULL) { - SSLerr(SSL_F_TLS_PROCESS_CLIENT_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE); - goto err; - } - i = ECDH_compute_key(shared, (field_size + 7) / 8, clnt_ecpoint, - srvr_ecdh, NULL); - if (i <= 0) { - SSLerr(SSL_F_TLS_PROCESS_CLIENT_KEY_EXCHANGE, ERR_R_ECDH_LIB); - OPENSSL_free(shared); - goto err; - } - - EVP_PKEY_free(clnt_pub_pkey); - EC_POINT_free(clnt_ecpoint); - EC_KEY_free(srvr_ecdh); - BN_CTX_free(bn_ctx); - EC_KEY_free(s->s3->tmp.ecdh); - s->s3->tmp.ecdh = NULL; - - if (!ssl_generate_master_secret(s, shared, i, 1)) { + if (ssl_derive(s, skey, ckey) == 0) { al = SSL_AD_INTERNAL_ERROR; SSLerr(SSL_F_TLS_PROCESS_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR); goto f_err; } + + EVP_PKEY_free(ckey); + ckey = NULL; + EVP_PKEY_free(s->s3->tmp.pkey); + s->s3->tmp.pkey = NULL; + return MSG_PROCESS_CONTINUE_PROCESSING; } else #endif #ifndef OPENSSL_NO_SRP if (alg_k & SSL_kSRP) { + unsigned int i; + const unsigned char *data; + if (!PACKET_get_net_2(pkt, &i) || !PACKET_get_bytes(pkt, &data, i)) { al = SSL_AD_DECODE_ERROR; @@ -2749,7 +2448,7 @@ MSG_PROCESS_RETURN tls_process_client_key_exchange(SSL *s, PACKET *pkt) goto f_err; } OPENSSL_free(s->session->srp_username); - s->session->srp_username = BUF_strdup(s->srp_ctx.login); + s->session->srp_username = OPENSSL_strdup(s->srp_ctx.login); if (s->session->srp_username == NULL) { SSLerr(SSL_F_TLS_PROCESS_CLIENT_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE); goto err; @@ -2765,12 +2464,14 @@ MSG_PROCESS_RETURN tls_process_client_key_exchange(SSL *s, PACKET *pkt) if (alg_k & SSL_kGOST) { EVP_PKEY_CTX *pkey_ctx; EVP_PKEY *client_pub_pkey = NULL, *pk = NULL; - unsigned char premaster_secret[32], *start; + unsigned char premaster_secret[32]; + const unsigned char *start; size_t outlen = 32, inlen; unsigned long alg_a; int Ttag, Tclass; long Tlen; long sess_key_len; + const unsigned char *data; /* Get our certificate private key */ alg_a = s->s3->tmp.new_cipher->algorithm_auth; @@ -2806,7 +2507,7 @@ MSG_PROCESS_RETURN tls_process_client_key_exchange(SSL *s, PACKET *pkt) * EVP_PKEY_derive_set_peer, because it is completely valid to use a * client certificate for authorization only. */ - client_pub_pkey = X509_get_pubkey(s->session->peer); + client_pub_pkey = X509_get0_pubkey(s->session->peer); if (client_pub_pkey) { if (EVP_PKEY_derive_set_peer(pkey_ctx, client_pub_pkey) <= 0) ERR_clear_error(); @@ -2848,11 +2549,9 @@ MSG_PROCESS_RETURN tls_process_client_key_exchange(SSL *s, PACKET *pkt) (pkey_ctx, -1, -1, EVP_PKEY_CTRL_PEER_KEY, 2, NULL) > 0) s->statem.no_cert_verify = 1; - EVP_PKEY_free(client_pub_pkey); EVP_PKEY_CTX_free(pkey_ctx); return MSG_PROCESS_CONTINUE_PROCESSING; gerr: - EVP_PKEY_free(client_pub_pkey); EVP_PKEY_CTX_free(pkey_ctx); goto f_err; } else @@ -2869,13 +2568,10 @@ MSG_PROCESS_RETURN tls_process_client_key_exchange(SSL *s, PACKET *pkt) #if !defined(OPENSSL_NO_DH) || !defined(OPENSSL_NO_RSA) || !defined(OPENSSL_NO_EC) || defined(OPENSSL_NO_SRP) err: #endif -#ifndef OPENSSL_NO_EC - EVP_PKEY_free(clnt_pub_pkey); - EC_POINT_free(clnt_ecpoint); - EC_KEY_free(srvr_ecdh); - BN_CTX_free(bn_ctx); - OPENSSL_free(rsa_decrypt); +#if !defined(OPENSSL_NO_EC) || !defined(OPENSSL_NO_DH) + EVP_PKEY_free(ckey); #endif + OPENSSL_free(rsa_decrypt); #ifndef OPENSSL_NO_PSK OPENSSL_clear_free(s->s3->tmp.psk, s->s3->tmp.psklen); s->s3->tmp.psk = NULL; @@ -2963,7 +2659,10 @@ WORK_STATE tls_post_process_client_key_exchange(SSL *s, WORK_STATE wst) MSG_PROCESS_RETURN tls_process_cert_verify(SSL *s, PACKET *pkt) { EVP_PKEY *pkey = NULL; - unsigned char *sig, *data; + const unsigned char *sig, *data; +#ifndef OPENSSL_NO_GOST + unsigned char *gost_data = NULL; +#endif int al, ret = MSG_PROCESS_ERROR; int type = 0, j; unsigned int len; @@ -2972,11 +2671,16 @@ MSG_PROCESS_RETURN tls_process_cert_verify(SSL *s, PACKET *pkt) long hdatalen = 0; void *hdata; - EVP_MD_CTX mctx; - EVP_MD_CTX_init(&mctx); + EVP_MD_CTX *mctx = EVP_MD_CTX_new(); + + if (mctx == NULL) { + SSLerr(SSL_F_TLS_PROCESS_CERT_VERIFY, ERR_R_MALLOC_FAILURE); + al = SSL_AD_INTERNAL_ERROR; + goto f_err; + } peer = s->session->peer; - pkey = X509_get_pubkey(peer); + pkey = X509_get0_pubkey(peer); type = X509_certificate_type(peer, pkey); if (!(type & EVP_PKT_SIGN)) { @@ -2992,7 +2696,8 @@ MSG_PROCESS_RETURN tls_process_cert_verify(SSL *s, PACKET *pkt) * length field (CryptoPro implementations at least till CSP 4.0) */ #ifndef OPENSSL_NO_GOST - if (PACKET_remaining(pkt) == 64 && pkey->type == NID_id_GostR3410_2001) { + if (PACKET_remaining(pkt) == 64 + && EVP_PKEY_id(pkey) == NID_id_GostR3410_2001) { len = 64; } else #endif @@ -3054,23 +2759,32 @@ MSG_PROCESS_RETURN tls_process_cert_verify(SSL *s, PACKET *pkt) #ifdef SSL_DEBUG fprintf(stderr, "Using client verify alg %s\n", EVP_MD_name(md)); #endif - if (!EVP_VerifyInit_ex(&mctx, md, NULL) - || !EVP_VerifyUpdate(&mctx, hdata, hdatalen)) { + if (!EVP_VerifyInit_ex(mctx, md, NULL) + || !EVP_VerifyUpdate(mctx, hdata, hdatalen)) { SSLerr(SSL_F_TLS_PROCESS_CERT_VERIFY, ERR_R_EVP_LIB); al = SSL_AD_INTERNAL_ERROR; goto f_err; } #ifndef OPENSSL_NO_GOST - if (pkey->type == NID_id_GostR3410_2001 - || pkey->type == NID_id_GostR3410_2012_256 - || pkey->type == NID_id_GostR3410_2012_512) { - BUF_reverse(data, NULL, len); + { + int pktype = EVP_PKEY_id(pkey); + if (pktype == NID_id_GostR3410_2001 + || pktype == NID_id_GostR3410_2012_256 + || pktype == NID_id_GostR3410_2012_512) { + if ((gost_data = OPENSSL_malloc(len)) == NULL) { + SSLerr(SSL_F_TLS_PROCESS_CERT_VERIFY, ERR_R_MALLOC_FAILURE); + al = SSL_AD_INTERNAL_ERROR; + goto f_err; + } + BUF_reverse(gost_data, data, len); + data = gost_data; + } } #endif if (s->version == SSL3_VERSION - && !EVP_MD_CTX_ctrl(&mctx, EVP_CTRL_SSL3_MASTER_SECRET, + && !EVP_MD_CTX_ctrl(mctx, EVP_CTRL_SSL3_MASTER_SECRET, s->session->master_key_length, s->session->master_key)) { SSLerr(SSL_F_TLS_PROCESS_CERT_VERIFY, ERR_R_EVP_LIB); @@ -3078,7 +2792,7 @@ MSG_PROCESS_RETURN tls_process_cert_verify(SSL *s, PACKET *pkt) goto f_err; } - if (EVP_VerifyFinal(&mctx, data, len, pkey) <= 0) { + if (EVP_VerifyFinal(mctx, data, len, pkey) <= 0) { al = SSL_AD_DECRYPT_ERROR; SSLerr(SSL_F_TLS_PROCESS_CERT_VERIFY, SSL_R_BAD_SIGNATURE); goto f_err; @@ -3092,8 +2806,10 @@ MSG_PROCESS_RETURN tls_process_cert_verify(SSL *s, PACKET *pkt) } BIO_free(s->s3->handshake_buffer); s->s3->handshake_buffer = NULL; - EVP_MD_CTX_cleanup(&mctx); - EVP_PKEY_free(pkey); + EVP_MD_CTX_free(mctx); +#ifndef OPENSSL_NO_GOST + OPENSSL_free(gost_data); +#endif return ret; } @@ -3102,8 +2818,7 @@ MSG_PROCESS_RETURN tls_process_client_certificate(SSL *s, PACKET *pkt) int i, al = SSL_AD_INTERNAL_ERROR, ret = MSG_PROCESS_ERROR; X509 *x = NULL; unsigned long l, llen; - const unsigned char *certstart; - unsigned char *certbytes; + const unsigned char *certstart, *certbytes; STACK_OF(X509) *sk = NULL; PACKET spkt; @@ -3182,14 +2897,13 @@ MSG_PROCESS_RETURN tls_process_client_certificate(SSL *s, PACKET *pkt) al = SSL_AD_HANDSHAKE_FAILURE; goto f_err; } - pkey = X509_get_pubkey(sk_X509_value(sk, 0)); + pkey = X509_get0_pubkey(sk_X509_value(sk, 0)); if (pkey == NULL) { al = SSL3_AD_HANDSHAKE_FAILURE; SSLerr(SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE, SSL_R_UNKNOWN_CERTIFICATE_TYPE); goto f_err; } - EVP_PKEY_free(pkey); } X509_free(s->session->peer); @@ -3238,8 +2952,8 @@ int tls_construct_server_certificate(SSL *s) int tls_construct_new_session_ticket(SSL *s) { unsigned char *senc = NULL; - EVP_CIPHER_CTX ctx; - HMAC_CTX hctx; + EVP_CIPHER_CTX *ctx; + HMAC_CTX *hctx = NULL; unsigned char *p, *macstart; const unsigned char *const_p; int len, slen_full, slen; @@ -3265,8 +2979,8 @@ int tls_construct_new_session_ticket(SSL *s) return 0; } - EVP_CIPHER_CTX_init(&ctx); - HMAC_CTX_init(&hctx); + ctx = EVP_CIPHER_CTX_new(); + hctx = HMAC_CTX_new(); p = senc; if (!i2d_SSL_SESSION(s->session, &p)) @@ -3312,16 +3026,15 @@ int tls_construct_new_session_ticket(SSL *s) * all the work otherwise use generated values from parent ctx. */ if (tctx->tlsext_ticket_key_cb) { - if (tctx->tlsext_ticket_key_cb(s, key_name, iv, &ctx, - &hctx, 1) < 0) + if (tctx->tlsext_ticket_key_cb(s, key_name, iv, ctx, hctx, 1) < 0) goto err; } else { if (RAND_bytes(iv, 16) <= 0) goto err; - if (!EVP_EncryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL, + if (!EVP_EncryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, tctx->tlsext_tick_aes_key, iv)) goto err; - if (!HMAC_Init_ex(&hctx, tctx->tlsext_tick_hmac_key, 16, + if (!HMAC_Init_ex(hctx, tctx->tlsext_tick_hmac_key, 16, EVP_sha256(), NULL)) goto err; memcpy(key_name, tctx->tlsext_tick_key_name, 16); @@ -3341,23 +3054,25 @@ int tls_construct_new_session_ticket(SSL *s) memcpy(p, key_name, 16); p += 16; /* output IV */ - memcpy(p, iv, EVP_CIPHER_CTX_iv_length(&ctx)); - p += EVP_CIPHER_CTX_iv_length(&ctx); + memcpy(p, iv, EVP_CIPHER_CTX_iv_length(ctx)); + p += EVP_CIPHER_CTX_iv_length(ctx); /* Encrypt session data */ - if (!EVP_EncryptUpdate(&ctx, p, &len, senc, slen)) + if (!EVP_EncryptUpdate(ctx, p, &len, senc, slen)) goto err; p += len; - if (!EVP_EncryptFinal(&ctx, p, &len)) + if (!EVP_EncryptFinal(ctx, p, &len)) goto err; p += len; - if (!HMAC_Update(&hctx, macstart, p - macstart)) + if (!HMAC_Update(hctx, macstart, p - macstart)) goto err; - if (!HMAC_Final(&hctx, p, &hlen)) + if (!HMAC_Final(hctx, p, &hlen)) goto err; - EVP_CIPHER_CTX_cleanup(&ctx); - HMAC_CTX_cleanup(&hctx); + EVP_CIPHER_CTX_free(ctx); + HMAC_CTX_free(hctx); + ctx = NULL; + hctx = NULL; p += hlen; /* Now write out lengths: p points to end of data written */ @@ -3373,8 +3088,8 @@ int tls_construct_new_session_ticket(SSL *s) return 1; err: OPENSSL_free(senc); - EVP_CIPHER_CTX_cleanup(&ctx); - HMAC_CTX_cleanup(&hctx); + EVP_CIPHER_CTX_free(ctx); + HMAC_CTX_free(hctx); ossl_statem_set_error(s); return 0; } @@ -3520,9 +3235,6 @@ STACK_OF(SSL_CIPHER) *ssl_bytes_to_cipher_list(SSL *s, goto err; } s->s3->send_connection_binding = 1; -#ifdef OPENSSL_RI_DEBUG - fprintf(stderr, "SCSV received by server\n"); -#endif continue; } @@ -3534,7 +3246,7 @@ STACK_OF(SSL_CIPHER) *ssl_bytes_to_cipher_list(SSL *s, * version. Fail if the current version is an unexpected * downgrade. */ - if (!SSL_ctrl(s, SSL_CTRL_CHECK_PROTO_VERSION, 0, NULL)) { + if (!ssl_check_version_downgrade(s)) { SSLerr(SSL_F_SSL_BYTES_TO_CIPHER_LIST, SSL_R_INAPPROPRIATE_FALLBACK); *al = SSL_AD_INAPPROPRIATE_FALLBACK;