X-Git-Url: https://git.openssl.org/?p=openssl.git;a=blobdiff_plain;f=ssl%2Fs3_clnt.c;h=6da125897d35d97db970cf486b188c2fa6e209f6;hp=2713129f15b8c1a32655d6d4e5b80d88e837058e;hb=c99c4c11a202ed71d4c232075668a876f352d71a;hpb=0f113f3ee4d629ef9a4a30911b22b224772085e5 diff --git a/ssl/s3_clnt.c b/ssl/s3_clnt.c index 2713129f15..6da125897d 100644 --- a/ssl/s3_clnt.c +++ b/ssl/s3_clnt.c @@ -197,8 +197,10 @@ int ssl3_connect(SSL *s) cb = s->ctx->info_callback; s->in_handshake++; - if (!SSL_in_init(s) || SSL_in_before(s)) - SSL_clear(s); + if (!SSL_in_init(s) || SSL_in_before(s)) { + if(!SSL_clear(s)) + return -1; + } #ifndef OPENSSL_NO_HEARTBEATS /* @@ -719,50 +721,45 @@ int ssl3_client_hello(SSL *s) } else i = 1; - if (i) - ssl_fill_hello_random(s, 0, p, sizeof(s->s3->client_random)); + if (i && ssl_fill_hello_random(s, 0, p, + sizeof(s->s3->client_random)) <= 0) + goto err; /* Do the message type and length last */ d = p = ssl_handshake_start(s); - /*- - * version indicates the negotiated version: for example from - * an SSLv2/v3 compatible client hello). The client_version - * field is the maximum version we permit and it is also - * used in RSA encrypted premaster secrets. Some servers can - * choke if we initially report a higher version then - * renegotiate to a lower one in the premaster secret. This - * didn't happen with TLS 1.0 as most servers supported it - * but it can with TLS 1.1 or later if the server only supports - * 1.0. - * - * Possible scenario with previous logic: - * 1. Client hello indicates TLS 1.2 - * 2. Server hello says TLS 1.0 - * 3. RSA encrypted premaster secret uses 1.2. - * 4. Handhaked proceeds using TLS 1.0. - * 5. Server sends hello request to renegotiate. - * 6. Client hello indicates TLS v1.0 as we now - * know that is maximum server supports. - * 7. Server chokes on RSA encrypted premaster secret - * containing version 1.0. - * - * For interoperability it should be OK to always use the - * maximum version we support in client hello and then rely - * on the checking of version to ensure the servers isn't - * being inconsistent: for example initially negotiating with - * TLS 1.0 and renegotiating with TLS 1.2. We do this by using - * client_version in client hello and not resetting it to - * the negotiated version. - */ -#if 0 - *(p++) = s->version >> 8; - *(p++) = s->version & 0xff; - s->client_version = s->version; -#else + /*- + * version indicates the negotiated version: for example from + * an SSLv2/v3 compatible client hello). The client_version + * field is the maximum version we permit and it is also + * used in RSA encrypted premaster secrets. Some servers can + * choke if we initially report a higher version then + * renegotiate to a lower one in the premaster secret. This + * didn't happen with TLS 1.0 as most servers supported it + * but it can with TLS 1.1 or later if the server only supports + * 1.0. + * + * Possible scenario with previous logic: + * 1. Client hello indicates TLS 1.2 + * 2. Server hello says TLS 1.0 + * 3. RSA encrypted premaster secret uses 1.2. + * 4. Handhaked proceeds using TLS 1.0. + * 5. Server sends hello request to renegotiate. + * 6. Client hello indicates TLS v1.0 as we now + * know that is maximum server supports. + * 7. Server chokes on RSA encrypted premaster secret + * containing version 1.0. + * + * For interoperability it should be OK to always use the + * maximum version we support in client hello and then rely + * on the checking of version to ensure the servers isn't + * being inconsistent: for example initially negotiating with + * TLS 1.0 and renegotiating with TLS 1.2. We do this by using + * client_version in client hello and not resetting it to + * the negotiated version. + */ *(p++) = s->client_version >> 8; *(p++) = s->client_version & 0xff; -#endif /* Random stuff */ memcpy(p, s->s3->client_random, SSL3_RANDOM_SIZE); @@ -846,7 +843,11 @@ int ssl3_client_hello(SSL *s) #endif l = p - d; - ssl_set_handshake_header(s, SSL3_MT_CLIENT_HELLO, l); + if(!ssl_set_handshake_header(s, SSL3_MT_CLIENT_HELLO, l)) { + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE); + SSLerr(SSL_F_SSL3_CLIENT_HELLO, ERR_R_INTERNAL_ERROR); + goto err; + } s->state = SSL3_ST_CW_CLNT_HELLO_B; } @@ -1036,16 +1037,10 @@ int ssl3_get_server_hello(SSL *s) if (s->session->cipher) s->session->cipher_id = s->session->cipher->id; if (s->hit && (s->session->cipher_id != c->id)) { -/* Workaround is now obsolete */ -#if 0 - if (!(s->options & SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG)) -#endif - { - al = SSL_AD_ILLEGAL_PARAMETER; - SSLerr(SSL_F_SSL3_GET_SERVER_HELLO, - SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED); - goto f_err; - } + al = SSL_AD_ILLEGAL_PARAMETER; + SSLerr(SSL_F_SSL3_GET_SERVER_HELLO, + SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED); + goto f_err; } s->s3->tmp.new_cipher = c; /* @@ -1332,7 +1327,7 @@ int ssl3_get_key_exchange(SSL *s) #ifndef OPENSSL_NO_DH DH *dh = NULL; #endif -#ifndef OPENSSL_NO_ECDH +#ifndef OPENSSL_NO_EC EC_KEY *ecdh = NULL; BN_CTX *bn_ctx = NULL; EC_POINT *srvr_ecpoint = NULL; @@ -1385,22 +1380,16 @@ int ssl3_get_key_exchange(SSL *s) param = p = (unsigned char *)s->init_msg; if (s->session->sess_cert != NULL) { #ifndef OPENSSL_NO_RSA - if (s->session->sess_cert->peer_rsa_tmp != NULL) { - RSA_free(s->session->sess_cert->peer_rsa_tmp); - s->session->sess_cert->peer_rsa_tmp = NULL; - } + RSA_free(s->session->sess_cert->peer_rsa_tmp); + s->session->sess_cert->peer_rsa_tmp = NULL; #endif #ifndef OPENSSL_NO_DH - if (s->session->sess_cert->peer_dh_tmp) { - DH_free(s->session->sess_cert->peer_dh_tmp); - s->session->sess_cert->peer_dh_tmp = NULL; - } + DH_free(s->session->sess_cert->peer_dh_tmp); + s->session->sess_cert->peer_dh_tmp = NULL; #endif -#ifndef OPENSSL_NO_ECDH - if (s->session->sess_cert->peer_ecdh_tmp) { - EC_KEY_free(s->session->sess_cert->peer_ecdh_tmp); - s->session->sess_cert->peer_ecdh_tmp = NULL; - } +#ifndef OPENSSL_NO_EC + EC_KEY_free(s->session->sess_cert->peer_ecdh_tmp); + s->session->sess_cert->peer_ecdh_tmp = NULL; #endif } else { s->session->sess_cert = ssl_sess_cert_new(); @@ -1727,15 +1716,10 @@ int ssl3_get_key_exchange(SSL *s) s->session->sess_cert->peer_dh_tmp = dh; dh = NULL; - } else if ((alg_k & SSL_kDHr) || (alg_k & SSL_kDHd)) { - al = SSL_AD_ILLEGAL_PARAMETER; - SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, - SSL_R_TRIED_TO_USE_UNSUPPORTED_CIPHER); - goto f_err; } #endif /* !OPENSSL_NO_DH */ -#ifndef OPENSSL_NO_ECDH +#ifndef OPENSSL_NO_EC else if (alg_k & SSL_kECDHE) { EC_GROUP *ngroup; const EC_GROUP *group; @@ -1833,7 +1817,7 @@ int ssl3_get_key_exchange(SSL *s) X509_get_pubkey(s->session-> sess_cert->peer_pkeys[SSL_PKEY_RSA_ENC].x509); # endif -# ifndef OPENSSL_NO_ECDSA +# ifndef OPENSSL_NO_EC else if (alg_a & SSL_aECDSA) pkey = X509_get_pubkey(s->session-> @@ -1852,7 +1836,7 @@ int ssl3_get_key_exchange(SSL *s) SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_UNEXPECTED_MESSAGE); goto f_err; } -#endif /* !OPENSSL_NO_ECDH */ +#endif /* !OPENSSL_NO_EC */ /* p points to the next byte, there are 'n' bytes left */ @@ -1965,18 +1949,15 @@ int ssl3_get_key_exchange(SSL *s) err: EVP_PKEY_free(pkey); #ifndef OPENSSL_NO_RSA - if (rsa != NULL) - RSA_free(rsa); + RSA_free(rsa); #endif #ifndef OPENSSL_NO_DH - if (dh != NULL) - DH_free(dh); + DH_free(dh); #endif -#ifndef OPENSSL_NO_ECDH +#ifndef OPENSSL_NO_EC BN_CTX_free(bn_ctx); EC_POINT_free(srvr_ecpoint); - if (ecdh != NULL) - EC_KEY_free(ecdh); + EC_KEY_free(ecdh); #endif EVP_MD_CTX_cleanup(&md_ctx); return (-1); @@ -2091,14 +2072,6 @@ int ssl3_get_certificate_request(SSL *s) /* get the CA RDNs */ n2s(p, llen); -#if 0 - { - FILE *out; - out = fopen("/tmp/vsign.der", "w"); - fwrite(p, 1, llen, out); - fclose(out); - } -#endif if ((unsigned long)(p - d + llen) != n) { ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); @@ -2109,8 +2082,6 @@ int ssl3_get_certificate_request(SSL *s) for (nc = 0; nc < llen;) { n2s(p, l); if ((l + nc + 2) > llen) { - if ((s->options & SSL_OP_NETSCAPE_CA_DN_BUG)) - goto cont; /* netscape bugs */ ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST, SSL_R_CA_DN_TOO_LONG); goto err; @@ -2119,14 +2090,9 @@ int ssl3_get_certificate_request(SSL *s) q = p; if ((xn = d2i_X509_NAME(NULL, &q, l)) == NULL) { - /* If netscape tolerance is on, ignore errors */ - if (s->options & SSL_OP_NETSCAPE_CA_DN_BUG) - goto cont; - else { - ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); - SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST, ERR_R_ASN1_LIB); - goto err; - } + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); + SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST, ERR_R_ASN1_LIB); + goto err; } if (q != (p + l)) { @@ -2144,11 +2110,6 @@ int ssl3_get_certificate_request(SSL *s) nc += l + 2; } - if (0) { - cont: - ERR_clear_error(); - } - /* we should setup a certificate to return.... */ s->s3->tmp.cert_req = 1; s->s3->tmp.ctype_num = ctype_num; @@ -2225,11 +2186,7 @@ int ssl3_get_new_session_ticket(SSL *s) */ EVP_Digest(p, ticklen, s->session->session_id, &s->session->session_id_length, -# ifndef OPENSSL_NO_SHA256 EVP_sha256(), NULL); -# else - EVP_sha1(), NULL); -# endif ret = 1; return (ret); f_err: @@ -2334,7 +2291,7 @@ int ssl3_send_client_key_exchange(SSL *s) #ifndef OPENSSL_NO_KRB5 KSSL_ERR kssl_err; #endif /* OPENSSL_NO_KRB5 */ -#ifndef OPENSSL_NO_ECDH +#ifndef OPENSSL_NO_EC EC_KEY *clnt_ecdh = NULL; const EC_POINT *srvr_ecpoint = NULL; EVP_PKEY *srvr_pub_pkey = NULL; @@ -2342,6 +2299,8 @@ int ssl3_send_client_key_exchange(SSL *s) int encoded_pt_len = 0; BN_CTX *bn_ctx = NULL; #endif + unsigned char *pms = NULL; + size_t pmslen = 0; if (s->state == SSL3_ST_CW_KEY_EXCH_A) { p = ssl_handshake_start(s); @@ -2354,7 +2313,10 @@ int ssl3_send_client_key_exchange(SSL *s) #ifndef OPENSSL_NO_RSA else if (alg_k & SSL_kRSA) { RSA *rsa; - unsigned char tmp_buf[SSL_MAX_MASTER_KEY_LENGTH]; + pmslen = SSL_MAX_MASTER_KEY_LENGTH; + pms = OPENSSL_malloc(pmslen); + if (!pms) + goto memerr; if (s->session->sess_cert == NULL) { /* @@ -2382,19 +2344,16 @@ int ssl3_send_client_key_exchange(SSL *s) EVP_PKEY_free(pkey); } - tmp_buf[0] = s->client_version >> 8; - tmp_buf[1] = s->client_version & 0xff; - if (RAND_bytes(&(tmp_buf[2]), sizeof tmp_buf - 2) <= 0) + pms[0] = s->client_version >> 8; + pms[1] = s->client_version & 0xff; + if (RAND_bytes(pms + 2, pmslen - 2) <= 0) goto err; - s->session->master_key_length = sizeof tmp_buf; - q = p; /* Fix buf for TLS and beyond */ if (s->version > SSL3_VERSION) p += 2; - n = RSA_public_encrypt(sizeof tmp_buf, - tmp_buf, p, rsa, RSA_PKCS1_PADDING); + n = RSA_public_encrypt(pmslen, pms, p, rsa, RSA_PKCS1_PADDING); # ifdef PKCS1_CHECK if (s->options & SSL_OP_PKCS1_CHECK_1) p[1]++; @@ -2412,14 +2371,6 @@ int ssl3_send_client_key_exchange(SSL *s) s2n(n, q); n += 2; } - - s->session->master_key_length = - s->method->ssl3_enc->generate_master_secret(s, - s-> - session->master_key, - tmp_buf, - sizeof tmp_buf); - OPENSSL_cleanse(tmp_buf, sizeof tmp_buf); } #endif #ifndef OPENSSL_NO_KRB5 @@ -2468,25 +2419,25 @@ int ssl3_send_client_key_exchange(SSL *s) 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. - */ + /*- + * 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); @@ -2509,23 +2460,27 @@ int ssl3_send_client_key_exchange(SSL *s) n += 2; } - tmp_buf[0] = s->client_version >> 8; - tmp_buf[1] = s->client_version & 0xff; - if (RAND_bytes(&(tmp_buf[2]), sizeof tmp_buf - 2) <= 0) + 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); - */ + /*- + * 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, tmp_buf, - sizeof tmp_buf); + EVP_EncryptUpdate(&ciph_ctx, epms, &outl, pms, pmslen); EVP_EncryptFinal_ex(&ciph_ctx, &(epms[outl]), &padl); outl += padl; if (outl > (int)sizeof epms) { @@ -2540,15 +2495,6 @@ int ssl3_send_client_key_exchange(SSL *s) memcpy(p, epms, outl); p += outl; n += outl + 2; - - s->session->master_key_length = - s->method->ssl3_enc->generate_master_secret(s, - s-> - session->master_key, - tmp_buf, - sizeof tmp_buf); - - OPENSSL_cleanse(tmp_buf, sizeof tmp_buf); OPENSSL_cleanse(epms, outl); } #endif @@ -2607,12 +2553,17 @@ int ssl3_send_client_key_exchange(SSL *s) } } + pmslen = DH_size(dh_clnt); + pms = OPENSSL_malloc(pmslen); + if (!pms) + goto memerr; + /* * use the 'p' output buffer for the DH key, but make sure to * clear it out afterwards */ - n = DH_compute_key(p, dh_srvr->pub_key, dh_clnt); + n = DH_compute_key(pms, dh_srvr->pub_key, dh_clnt); if (scert->peer_dh_tmp == NULL) DH_free(dh_srvr); @@ -2621,15 +2572,7 @@ int ssl3_send_client_key_exchange(SSL *s) DH_free(dh_clnt); goto err; } - - /* generate master key from the result */ - s->session->master_key_length = - s->method->ssl3_enc->generate_master_secret(s, - s-> - session->master_key, - p, n); - /* clean up */ - memset(p, 0, n); + pmslen = n; if (s->s3->flags & TLS1_FLAGS_SKIP_CERT_VERIFY) n = 0; @@ -2647,7 +2590,7 @@ int ssl3_send_client_key_exchange(SSL *s) } #endif -#ifndef OPENSSL_NO_ECDH +#ifndef OPENSSL_NO_EC else if (alg_k & (SSL_kECDHE | SSL_kECDHr | SSL_kECDHe)) { const EC_GROUP *srvr_group = NULL; EC_KEY *tkey; @@ -2667,26 +2610,26 @@ int ssl3_send_client_key_exchange(SSL *s) * ecdh_clnt_cert to 1. */ if ((alg_k & (SSL_kECDHr | SSL_kECDHe)) && (s->cert != NULL)) { - /*- - * XXX: For now, we do not support client - * authentication using ECDH certificates. - * To add such support, one needs to add - * code that checks for appropriate - * conditions and sets ecdh_clnt_cert to 1. - * For example, the cert have an ECC - * key on the same curve as the server's - * and the key should be authorized for - * key agreement. - * - * One also needs to add code in ssl3_connect - * to skip sending the certificate verify - * message. - * - * if ((s->cert->key->privatekey != NULL) && - * (s->cert->key->privatekey->type == - * EVP_PKEY_EC) && ...) - * ecdh_clnt_cert = 1; - */ + /*- + * XXX: For now, we do not support client + * authentication using ECDH certificates. + * To add such support, one needs to add + * code that checks for appropriate + * conditions and sets ecdh_clnt_cert to 1. + * For example, the cert have an ECC + * key on the same curve as the server's + * and the key should be authorized for + * key agreement. + * + * One also needs to add code in ssl3_connect + * to skip sending the certificate verify + * message. + * + * if ((s->cert->key->privatekey != NULL) && + * (s->cert->key->privatekey->type == + * EVP_PKEY_EC) && ...) + * ecdh_clnt_cert = 1; + */ } if (s->session->sess_cert->peer_ecdh_tmp != NULL) { @@ -2762,22 +2705,16 @@ int ssl3_send_client_key_exchange(SSL *s) SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, ERR_R_ECDH_LIB); goto err; } - n = ECDH_compute_key(p, (field_size + 7) / 8, srvr_ecpoint, - clnt_ecdh, NULL); - if (n <= 0) { + pmslen = (field_size + 7) / 8; + pms = OPENSSL_malloc(pmslen); + if (!pms) + goto memerr; + n = ECDH_compute_key(pms, pmslen, srvr_ecpoint, clnt_ecdh, NULL); + if (n <= 0 || pmslen != (size_t)n) { SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, ERR_R_ECDH_LIB); goto err; } - /* generate master key from the result */ - s->session->master_key_length = - s->method->ssl3_enc->generate_master_secret(s, - s-> - session->master_key, - p, n); - - memset(p, 0, n); /* clean up */ - if (ecdh_clnt_cert) { /* Send empty client key exch message */ n = 0; @@ -2820,11 +2757,10 @@ int ssl3_send_client_key_exchange(SSL *s) BN_CTX_free(bn_ctx); if (encodedPoint != NULL) OPENSSL_free(encodedPoint); - if (clnt_ecdh != NULL) - EC_KEY_free(clnt_ecdh); + EC_KEY_free(clnt_ecdh); EVP_PKEY_free(srvr_pub_pkey); } -#endif /* !OPENSSL_NO_ECDH */ +#endif /* !OPENSSL_NO_EC */ else if (alg_k & SSL_kGOST) { /* GOST key exchange message creation */ EVP_PKEY_CTX *pkey_ctx; @@ -2832,10 +2768,15 @@ int ssl3_send_client_key_exchange(SSL *s) size_t msglen; unsigned int md_len; int keytype; - unsigned char premaster_secret[32], shared_ukm[32], tmp[256]; + unsigned char shared_ukm[32], tmp[256]; EVP_MD_CTX *ukm_hash; EVP_PKEY *pub_key; + pmslen = 32; + pms = OPENSSL_malloc(pmslen); + if (!pms) + goto memerr; + /* * Get server sertificate PKEY and create ctx from it */ @@ -2865,7 +2806,12 @@ int ssl3_send_client_key_exchange(SSL *s) EVP_PKEY_encrypt_init(pkey_ctx); /* Generate session key */ - RAND_bytes(premaster_secret, 32); + if (RAND_bytes(pms, pmslen) <= 0) { + EVP_PKEY_CTX_free(pkey_ctx); + SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, + ERR_R_INTERNAL_ERROR); + goto err; + }; /* * If we have client certificate, use its secret as peer key */ @@ -2905,8 +2851,7 @@ int ssl3_send_client_key_exchange(SSL *s) */ *(p++) = V_ASN1_SEQUENCE | V_ASN1_CONSTRUCTED; msglen = 255; - if (EVP_PKEY_encrypt(pkey_ctx, tmp, &msglen, premaster_secret, 32) - < 0) { + if (EVP_PKEY_encrypt(pkey_ctx, tmp, &msglen, pms, pmslen) < 0) { SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, SSL_R_LIBRARY_BUG); goto err; @@ -2927,12 +2872,6 @@ int ssl3_send_client_key_exchange(SSL *s) s->s3->flags |= TLS1_FLAGS_SKIP_CERT_VERIFY; } EVP_PKEY_CTX_free(pkey_ctx); - s->session->master_key_length = - s->method->ssl3_enc->generate_master_secret(s, - s-> - session->master_key, - premaster_secret, - 32); EVP_PKEY_free(pub_key); } @@ -2957,15 +2896,6 @@ int ssl3_send_client_key_exchange(SSL *s) ERR_R_MALLOC_FAILURE); goto err; } - - if ((s->session->master_key_length = - SRP_generate_client_master_secret(s, - s->session->master_key)) < - 0) { - SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, - ERR_R_INTERNAL_ERROR); - goto err; - } } #endif #ifndef OPENSSL_NO_PSK @@ -2978,8 +2908,7 @@ int ssl3_send_client_key_exchange(SSL *s) char identity[PSK_MAX_IDENTITY_LEN + 2]; size_t identity_len; unsigned char *t = NULL; - unsigned char psk_or_pre_ms[PSK_MAX_PSK_LEN * 2 + 4]; - unsigned int pre_ms_len = 0, psk_len = 0; + unsigned int psk_len = 0; int psk_err = 1; n = 0; @@ -2990,10 +2919,15 @@ int ssl3_send_client_key_exchange(SSL *s) } memset(identity, 0, sizeof(identity)); + /* Allocate maximum size buffer */ + pmslen = PSK_MAX_PSK_LEN * 2 + 4; + pms = OPENSSL_malloc(pmslen); + if (!pms) + goto memerr; + psk_len = s->psk_client_callback(s, s->ctx->psk_identity_hint, identity, sizeof(identity) - 1, - psk_or_pre_ms, - sizeof(psk_or_pre_ms)); + pms, pmslen); if (psk_len > PSK_MAX_PSK_LEN) { SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR); @@ -3003,6 +2937,8 @@ int ssl3_send_client_key_exchange(SSL *s) SSL_R_PSK_IDENTITY_NOT_FOUND); goto psk_err; } + /* Change pmslen to real length */ + pmslen = 2 + psk_len + 2 + psk_len; identity[PSK_MAX_IDENTITY_LEN + 1] = '\0'; identity_len = strlen(identity); if (identity_len > PSK_MAX_IDENTITY_LEN) { @@ -3011,9 +2947,8 @@ int ssl3_send_client_key_exchange(SSL *s) goto psk_err; } /* create PSK pre_master_secret */ - pre_ms_len = 2 + psk_len + 2 + psk_len; - t = psk_or_pre_ms; - memmove(psk_or_pre_ms + psk_len + 4, psk_or_pre_ms, psk_len); + t = pms; + memmove(pms + psk_len + 4, pms, psk_len); s2n(psk_len, t); memset(t, 0, psk_len); t += psk_len; @@ -3039,19 +2974,12 @@ int ssl3_send_client_key_exchange(SSL *s) goto psk_err; } - s->session->master_key_length = - s->method->ssl3_enc->generate_master_secret(s, - s-> - session->master_key, - psk_or_pre_ms, - pre_ms_len); s2n(identity_len, p); memcpy(p, identity, identity_len); n = 2 + identity_len; psk_err = 0; psk_err: OPENSSL_cleanse(identity, sizeof(identity)); - OPENSSL_cleanse(psk_or_pre_ms, sizeof(psk_or_pre_ms)); if (psk_err != 0) { ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE); goto err; @@ -3064,19 +2992,80 @@ int ssl3_send_client_key_exchange(SSL *s) goto err; } - ssl_set_handshake_header(s, SSL3_MT_CLIENT_KEY_EXCHANGE, n); + if(!ssl_set_handshake_header(s, SSL3_MT_CLIENT_KEY_EXCHANGE, n)) { + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE); + SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR); + goto err; + } + s->state = SSL3_ST_CW_KEY_EXCH_B; } /* SSL3_ST_CW_KEY_EXCH_B */ - return ssl_do_write(s); + n = ssl_do_write(s); +#ifndef OPENSSL_NO_SRP + /* Check for SRP */ + if (s->s3->tmp.new_cipher->algorithm_mkey & SSL_kSRP) { + /* + * If everything written generate master key: no need to save PMS as + * SRP_generate_client_master_secret generates it internally. + */ + if (n > 0) { + if ((s->session->master_key_length = + SRP_generate_client_master_secret(s, + s->session->master_key)) < + 0) { + SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, + ERR_R_INTERNAL_ERROR); + goto err; + } + } + } else +#endif + /* If we haven't written everything save PMS */ + if (n <= 0) { + s->cert->pms = pms; + s->cert->pmslen = pmslen; + } else { + /* If we don't have a PMS restore */ + if (pms == NULL) { + pms = s->cert->pms; + pmslen = s->cert->pmslen; + } + if (pms == NULL) { + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR); + SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE); + goto err; + } + s->session->master_key_length = + s->method->ssl3_enc->generate_master_secret(s, + s-> + session->master_key, + pms, pmslen); + OPENSSL_cleanse(pms, pmslen); + OPENSSL_free(pms); + s->cert->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); + goto err; + } + } + return n; + memerr: + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR); + SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE); err: -#ifndef OPENSSL_NO_ECDH + if (pms) { + OPENSSL_cleanse(pms, pmslen); + OPENSSL_free(pms); + s->cert->pms = NULL; + } +#ifndef OPENSSL_NO_EC BN_CTX_free(bn_ctx); if (encodedPoint != NULL) OPENSSL_free(encodedPoint); - if (clnt_ecdh != NULL) - EC_KEY_free(clnt_ecdh); + EC_KEY_free(clnt_ecdh); EVP_PKEY_free(srvr_pub_pkey); #endif return (-1); @@ -3136,7 +3125,15 @@ int ssl3_send_client_verify(SSL *s) } s2n(u, p); n = u + 4; - if (!ssl3_digest_cached_records(s)) + /* + * For extended master secret we've already digested cached + * records. + */ + if (s->session->flags & SSL_SESS_FLAG_EXTMS) { + BIO_free(s->s3->handshake_buffer); + s->s3->handshake_buffer = NULL; + s->s3->flags &= ~TLS1_FLAGS_KEEP_HANDSHAKE; + } else if (!ssl3_digest_cached_records(s)) goto err; } else #ifndef OPENSSL_NO_RSA @@ -3165,7 +3162,7 @@ int ssl3_send_client_verify(SSL *s) n = j + 2; } else #endif -#ifndef OPENSSL_NO_ECDSA +#ifndef OPENSSL_NO_EC if (pkey->type == EVP_PKEY_EC) { if (!ECDSA_sign(pkey->save_type, &(data[MD5_DIGEST_LENGTH]), @@ -3198,7 +3195,10 @@ int ssl3_send_client_verify(SSL *s) SSLerr(SSL_F_SSL3_SEND_CLIENT_VERIFY, ERR_R_INTERNAL_ERROR); goto err; } - ssl_set_handshake_header(s, SSL3_MT_CERTIFICATE_VERIFY, n); + if(!ssl_set_handshake_header(s, SSL3_MT_CERTIFICATE_VERIFY, n)) { + SSLerr(SSL_F_SSL3_SEND_CLIENT_VERIFY, ERR_R_INTERNAL_ERROR); + goto err; + } s->state = SSL3_ST_CW_CERT_VRFY_B; } EVP_MD_CTX_cleanup(&mctx); @@ -3374,7 +3374,7 @@ int ssl3_check_cert_and_algorithm(SSL *s) /* This is the passed certificate */ idx = sc->peer_cert_type; -#ifndef OPENSSL_NO_ECDH +#ifndef OPENSSL_NO_EC if (idx == SSL_PKEY_ECC) { if (ssl_check_srvr_ecc_cert_and_alg(sc->peer_pkeys[idx].x509, s) == 0) { /* check failed */