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 *,
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;
}
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)
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
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;
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)
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);
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);
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:
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;
#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);
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)) {
{
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;
* 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,
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;
al = SSL_AD_PROTOCOL_VERSION;
goto f_err;
}
- s->version = s->method->version;
+ 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];
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.
goto f_err;
}
}
-#endif /* OPENSSL_NO_TLSEXT */
if (j != 0 && j == s->session->session_id_length
&& memcmp(p, s->session->session_id, j) == 0) {
}
/* 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.
}
#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 */
SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
goto err;
}
+
+ 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->session->sess_cert->peer_rsa_tmp = rsa;
rsa = NULL;
}
return (X509_NAME_cmp(*a, *b));
}
-#ifndef OPENSSL_NO_TLSEXT
int ssl3_get_new_session_ticket(SSL *s)
{
int ok, al, ret = 0, ticklen;
}
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 */
s->state = SSL_ST_ERR;
return (-1);
}
-#endif
int ssl3_get_server_done(SSL *s)
{
}
DH_free(dh_clnt);
-
- /* perhaps clean things up a bit EAY EAY EAY EAY */
}
#endif
int i, idx;
long alg_k, alg_a;
EVP_PKEY *pkey = NULL;
+ int pkey_bits;
SESS_CERT *sc;
#ifndef OPENSSL_NO_RSA
RSA *rsa;
#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;
}
#endif
pkey = X509_get_pubkey(sc->peer_pkeys[idx].x509);
+ pkey_bits = EVP_PKEY_bits(pkey);
i = X509_certificate_type(sc->peer_pkeys[idx].x509, pkey);
EVP_PKEY_free(pkey);
}
#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)) {
# 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;
} 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
{
}
return (1);
f_err:
- ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
+ ssl3_send_alert(s, SSL3_AL_FATAL, al);
err:
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
return 0;
}
-# ifndef OPENSSL_NO_NEXTPROTONEG
+#ifndef OPENSSL_NO_NEXTPROTONEG
int ssl3_send_next_proto(SSL *s)
{
unsigned int len, padding_len;
return ssl3_do_write(s, SSL3_RT_HANDSHAKE);
}
-# endif
#endif
int ssl_do_client_cert_cb(SSL *s, X509 **px509, EVP_PKEY **ppkey)