* 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.
+ * 4. Handshake 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.
#ifndef OPENSSL_NO_DH
else if (alg_k & (SSL_kDHE | SSL_kDHEPSK)) {
PACKET prime, generator, pub_key;
+ EVP_PKEY *peer_tmp = NULL;
- DH *dh;
+ DH *dh = NULL;
+ BIGNUM *p = NULL, *g = NULL, *bnpub_key = NULL;
if (!PACKET_get_length_prefixed_2(pkt, &prime)
|| !PACKET_get_length_prefixed_2(pkt, &generator)
goto f_err;
}
- s->s3->peer_tmp = EVP_PKEY_new();
+ peer_tmp = EVP_PKEY_new();
dh = DH_new();
- if (s->s3->peer_tmp == NULL || dh == NULL) {
+ if (peer_tmp == NULL || dh == NULL) {
+ al = SSL_AD_INTERNAL_ERROR;
SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE);
- DH_free(dh);
- goto err;
+ goto dherr;
}
- if (EVP_PKEY_assign_DH(s->s3->peer_tmp, dh) == 0) {
- SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, ERR_R_EVP_LIB);
- DH_free(dh);
- goto err;
+ p = BN_bin2bn(PACKET_data(&prime), PACKET_remaining(&prime), NULL);
+ g = BN_bin2bn(PACKET_data(&generator), PACKET_remaining(&generator),
+ NULL);
+ bnpub_key = BN_bin2bn(PACKET_data(&pub_key), PACKET_remaining(&pub_key),
+ NULL);
+ if (p == NULL || g == NULL || bnpub_key == NULL) {
+ SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, ERR_R_BN_LIB);
+ goto dherr;
+ }
+
+ if (BN_is_zero(p) || BN_is_zero(g) || BN_is_zero(bnpub_key)) {
+ SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, SSL_R_BAD_DH_VALUE);
+ goto dherr;
}
- if ((dh->p = BN_bin2bn(PACKET_data(&prime),
- PACKET_remaining(&prime), NULL)) == NULL
- || (dh->g = BN_bin2bn(PACKET_data(&generator),
- PACKET_remaining(&generator), NULL)) == NULL
- || (dh->pub_key =
- BN_bin2bn(PACKET_data(&pub_key),
- PACKET_remaining(&pub_key), NULL)) == NULL) {
+ if (!DH_set0_pqg(dh, p, NULL, g)) {
+ al = SSL_AD_INTERNAL_ERROR;
SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, ERR_R_BN_LIB);
- goto err;
+ goto dherr;
}
- if (BN_is_zero(dh->p) || BN_is_zero(dh->g) || BN_is_zero(dh->pub_key)) {
- SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, SSL_R_BAD_DH_VALUE);
- goto f_err;
+ if (!DH_set0_key(dh, bnpub_key, NULL)) {
+ al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, ERR_R_BN_LIB);
+ goto dherr;
}
if (!ssl_security(s, SSL_SECOP_TMP_DH, DH_security_bits(dh), 0, dh)) {
al = SSL_AD_HANDSHAKE_FAILURE;
SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, SSL_R_DH_KEY_TOO_SMALL);
- goto f_err;
+ goto dherr;
}
+
+ if (EVP_PKEY_assign_DH(peer_tmp, dh) == 0) {
+ al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, ERR_R_EVP_LIB);
+ goto dherr;
+ }
+
+ s->s3->peer_tmp = peer_tmp;
+
+ goto dhend;
+ dherr:
+ BN_free(p);
+ BN_free(g);
+ BN_free(bnpub_key);
+ DH_free(dh);
+ EVP_PKEY_free(peer_tmp);
+ goto f_err;
+ dhend:
+ /*
+ * FIXME: This makes assumptions about which ciphersuites come with
+ * public keys. We should have a less ad-hoc way of doing this
+ */
if (alg_a & (SSL_aRSA|SSL_aDSS))
pkey = X509_get0_pubkey(s->session->peer);
/* else anonymous DH, so no certificate or pkey. */
#ifndef OPENSSL_NO_CT
if (s->ct_validation_callback != NULL) {
- if (!ssl_validate_ct(s)) {
+ /* Note we validate the SCTs whether or not we abort on error */
+ if (!ssl_validate_ct(s) && (s->verify_mode & SSL_VERIFY_PEER)) {
ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
return MSG_PROCESS_ERROR;
}
#ifndef OPENSSL_NO_DH
else if (alg_k & (SSL_kDHE | SSL_kDHEPSK)) {
DH *dh_clnt = NULL;
+ BIGNUM *pub_key;
skey = s->s3->peer_tmp;
if (skey == NULL) {
SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE,
/* send off the data */
- n = BN_num_bytes(dh_clnt->pub_key);
+ DH_get0_key(dh_clnt, &pub_key, NULL);
+ n = BN_num_bytes(pub_key);
s2n(n, p);
- BN_bn2bin(dh_clnt->pub_key, p);
+ BN_bn2bin(pub_key, p);
n += 2;
EVP_PKEY_free(ckey);
ckey = NULL;
unsigned char *pms = NULL;
size_t pmslen = 0;
+ pms = s->s3->tmp.pms;
+ pmslen = s->s3->tmp.pmslen;
+
#ifndef OPENSSL_NO_SRP
/* Check for SRP */
if (s->s3->tmp.new_cipher->algorithm_mkey & SSL_kSRP) {
return 1;
}
#endif
- pms = s->s3->tmp.pms;
- pmslen = s->s3->tmp.pmslen;
if (pms == NULL && !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK)) {
ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
if (!ssl_generate_master_secret(s, pms, pmslen, 1)) {
ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
SSLerr(SSL_F_TLS_CLIENT_KEY_EXCHANGE_POST_WORK, ERR_R_INTERNAL_ERROR);
+ /* ssl_generate_master_secret frees the pms even on error */
+ pms = NULL;
+ pmslen = 0;
goto err;
}
+ pms = NULL;
+ pmslen = 0;
#ifndef OPENSSL_NO_SCTP
if (SSL_IS_DTLS(s)) {