-/* ssl/statem/statem_clnt.c */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
#include <openssl/objects.h>
#include <openssl/evp.h>
#include <openssl/md5.h>
-#ifndef OPENSSL_NO_DH
-# include <openssl/dh.h>
-#endif
+#include <openssl/dh.h>
#include <openssl/bn.h>
-#ifndef OPENSSL_NO_ENGINE
-# include <openssl/engine.h>
-#endif
+#include <openssl/engine.h>
static ossl_inline int cert_req_allowed(SSL *s);
static int key_exchange_expected(SSL *s);
goto err;
}
- if ((sess == NULL) || (sess->ssl_version != s->version) ||
+ if ((sess == NULL) ||
+ !ssl_version_supported(s, sess->ssl_version) ||
/*
* In the case of EAP-FAST, we can have a pre-shared
* "ticket" without a session ID.
const SSL_CIPHER *c;
PACKET session_id;
size_t session_id_len;
- unsigned char *cipherchars;
+ const unsigned char *cipherchars;
int i, al = SSL_AD_INTERNAL_ERROR;
unsigned int compression;
unsigned int sversion;
}
}
+ s->session->ssl_version = s->version;
s->session->session_id_length = session_id_len;
/* session_id_len could be 0 */
memcpy(s->session->session_id, PACKET_data(&session_id),
session_id_len);
}
+ /* Session version and negotiated protocol version should match */
+ if (s->version != s->session->ssl_version) {
+ al = SSL_AD_PROTOCOL_VERSION;
+
+ SSLerr(SSL_F_TLS_PROCESS_SERVER_HELLO,
+ SSL_R_SSL_SESSION_VERSION_MISMATCH);
+ goto f_err;
+ }
+
c = ssl_get_cipher_by_char(s, cipherchars);
if (c == NULL) {
/* unknown cipher */
SSLerr(SSL_F_TLS_PROCESS_SERVER_HELLO, SSL_R_UNKNOWN_CIPHER_RETURNED);
goto f_err;
}
- /* Set version disabled mask now we know version */
- if (!SSL_USE_TLS1_2_CIPHERS(s))
- s->s3->tmp.mask_ssl = SSL_TLSV1_2;
- else
- s->s3->tmp.mask_ssl = 0;
- /* Skip TLS v1.0 ciphersuites if SSLv3 */
- if ((c->algorithm_ssl & SSL_TLSV1) && s->version == SSL3_VERSION)
- s->s3->tmp.mask_ssl |= SSL_TLSV1;
/*
- * If it is a disabled cipher we didn't send it in client hello, so
- * return an error.
+ * Now that we know the version, update the check to see if it's an allowed
+ * version.
+ */
+ s->s3->tmp.min_ver = s->version;
+ s->s3->tmp.max_ver = s->version;
+ /*
+ * If it is a disabled cipher we either didn't send it in client hello,
+ * or it's not allowed for the selected protocol. So we return an error.
*/
if (ssl_cipher_disabled(s, c, SSL_SECOP_CIPHER_CHECK)) {
al = SSL_AD_ILLEGAL_PARAMETER;
int al, i, ret = MSG_PROCESS_ERROR, exp_idx;
unsigned long cert_list_len, cert_len;
X509 *x = NULL;
- unsigned char *certstart, *certbytes;
+ const unsigned char *certstart, *certbytes;
STACK_OF(X509) *sk = NULL;
EVP_PKEY *pkey = NULL;
}
i = ssl_verify_cert_chain(s, sk);
- if (s->verify_mode != SSL_VERIFY_NONE && i <= 0) {
+ if ((s->verify_mode & SSL_VERIFY_PEER) && i <= 0) {
al = ssl_verify_alarm_type(s->verify_result);
SSLerr(SSL_F_TLS_PROCESS_SERVER_CERTIFICATE,
SSL_R_CERTIFICATE_VERIFY_FAILED);
PACKET prime, generator, pub_key;
DH *dh;
+ BIGNUM *p, *g, *bnpub_key;
if (!PACKET_get_length_prefixed_2(pkt, &prime)
|| !PACKET_get_length_prefixed_2(pkt, &generator)
goto err;
}
- 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) {
+ 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);
+ BN_free(p);
+ BN_free(g);
+ BN_free(bnpub_key);
goto err;
}
- if (BN_is_zero(dh->p) || BN_is_zero(dh->g) || BN_is_zero(dh->pub_key)) {
+ 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);
+ BN_free(p);
+ BN_free(g);
+ BN_free(bnpub_key);
goto f_err;
}
+ if (!DH_set0_pqg(dh, p, NULL, g)) {
+ SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, ERR_R_BN_LIB);
+ BN_free(p);
+ BN_free(g);
+ BN_free(bnpub_key);
+ goto err;
+ }
+
+ if (!DH_set0_key(dh, bnpub_key, NULL)) {
+ SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, ERR_R_BN_LIB);
+ BN_free(bnpub_key);
+ goto err;
+ }
+
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);
#ifndef OPENSSL_NO_EC
else if (alg_k & (SSL_kECDHE | SSL_kECDHEPSK)) {
PACKET encoded_pt;
- unsigned char *ecparams;
+ const unsigned char *ecparams;
int curve_nid;
/*
}
if (SSL_USE_SIGALGS(s)) {
- unsigned char *sigalgs;
+ const unsigned char *sigalgs;
int rv;
if (!PACKET_get_bytes(pkt, &sigalgs, 2)) {
SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, SSL_R_LENGTH_TOO_SHORT);
int ret = MSG_PROCESS_ERROR;
unsigned int list_len, ctype_num, i, name_len;
X509_NAME *xn = NULL;
- unsigned char *data;
- unsigned char *namestart, *namebytes;
+ const unsigned char *data;
+ const unsigned char *namestart, *namebytes;
STACK_OF(X509_NAME) *ca_sk = NULL;
if ((ca_sk = sk_X509_NAME_new(ca_dn_cmp)) == NULL) {
SSLerr(SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST, ERR_R_MALLOC_FAILURE);
goto err;
}
+ xn = NULL;
}
/* we should setup a certificate to return.... */
err:
ossl_statem_set_error(s);
done:
+ X509_NAME_free(xn);
sk_X509_NAME_pop_free(ca_sk, X509_NAME_free);
return ret;
}
}
}
+#ifndef OPENSSL_NO_CT
+ if (s->ct_validation_callback != NULL) {
+ /* 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;
+ }
+ }
+#endif
+
#ifndef OPENSSL_NO_SCTP
/* Only applies to renegotiation */
if (SSL_IS_DTLS(s) && BIO_dgram_is_sctp(SSL_get_wbio(s))
#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;
#endif
#ifndef OPENSSL_NO_EC
- else if (alg_k & (SSL_kECDHE | SSL_kECDHr | SSL_kECDHe | SSL_kECDHEPSK)) {
+ else if (alg_k & (SSL_kECDHE | SSL_kECDHEPSK)) {
- if (s->s3->peer_tmp != NULL) {
- skey = s->s3->peer_tmp;
- } else {
- /* Get the Server Public Key from Cert */
- skey = X509_get0_pubkey(s->session->peer);
- if ((skey == NULL) || EVP_PKEY_get0_EC_KEY(skey) == NULL) {
- SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE,
+ skey = s->s3->peer_tmp;
+ if ((skey == NULL) || EVP_PKEY_get0_EC_KEY(skey) == NULL) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE,
ERR_R_INTERNAL_ERROR);
- goto err;
+ goto err;
}
- }
ckey = ssl_generate_pkey(skey, NID_undef);
SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,
SSL_R_MISSING_ECDSA_SIGNING_CERT);
goto f_err;
- } else if (alg_k & (SSL_kECDHr | SSL_kECDHe)) {
- SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM, SSL_R_MISSING_ECDH_CERT);
- goto f_err;
}
#endif
pkey = X509_get0_pubkey(s->session->peer);
/* 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 = s->method->put_cipher_by_char(c, p);
p += j;
}
};
j = s->method->put_cipher_by_char(&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 = {