#include <stdio.h>
#include "../ssl_locl.h"
#include "statem_locl.h"
+#include "internal/cryptlib.h"
#include <openssl/buffer.h>
#include <openssl/objects.h>
#include <openssl/evp.h>
ret = ssl3_write_bytes(s, type, &s->init_buf->data[s->init_off],
s->init_num, &written);
if (ret < 0)
- return (-1);
+ return -1;
if (type == SSL3_RT_HANDSHAKE)
/*
* should not be done for 'Hello Request's, but in that case we'll
s->msg_callback(1, s->version, type, s->init_buf->data,
(size_t)(s->init_off + s->init_num), s,
s->msg_callback_arg);
- return (1);
+ return 1;
}
s->init_off += written;
s->init_num -= written;
- return (0);
+ return 0;
}
int tls_close_construct_packet(SSL *s, WPACKET *pkt, int htype)
* ClientHello.
*/
if (ssl_get_min_max_version(s, &ver_min, &ver_max) != 0) {
- SSLerr(SSL_F_TLS_SETUP_HANDSHAKE, ERR_R_INTERNAL_ERROR);
- ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_SETUP_HANDSHAKE,
+ ERR_R_INTERNAL_ERROR);
return 0;
}
for (i = 0; i < sk_SSL_CIPHER_num(ciphers); i++) {
break;
}
if (!ok) {
- SSLerr(SSL_F_TLS_SETUP_HANDSHAKE, SSL_R_NO_CIPHERS_AVAILABLE);
+ SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS_SETUP_HANDSHAKE,
+ SSL_R_NO_CIPHERS_AVAILABLE);
ERR_add_error_data(1, "No ciphers enabled for max supported "
"SSL/TLS version");
- ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
return 0;
}
if (SSL_IS_FIRST_HANDSHAKE(s)) {
- s->ctx->stats.sess_accept++;
+ /* N.B. s->session_ctx == s->ctx here */
+ CRYPTO_atomic_add(&s->session_ctx->stats.sess_accept, 1, &i,
+ s->session_ctx->lock);
} else if ((s->options & SSL_OP_NO_RENEGOTIATION)) {
/* Renegotiation is disabled */
ssl3_send_alert(s, SSL3_AL_WARNING, SSL_AD_NO_RENEGOTIATION);
* Server attempting to renegotiate with client that doesn't
* support secure renegotiation.
*/
- SSLerr(SSL_F_TLS_SETUP_HANDSHAKE,
- SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED);
- ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
+ SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS_SETUP_HANDSHAKE,
+ SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED);
return 0;
} else {
- s->ctx->stats.sess_accept_renegotiate++;
+ /* N.B. s->ctx may not equal s->session_ctx */
+ CRYPTO_atomic_add(&s->ctx->stats.sess_accept_renegotiate, 1, &i,
+ s->ctx->lock);
s->s3->tmp.cert_request = 0;
}
} else {
+ int discard;
if (SSL_IS_FIRST_HANDSHAKE(s))
- s->ctx->stats.sess_connect++;
+ CRYPTO_atomic_add(&s->session_ctx->stats.sess_connect, 1, &discard,
+ s->session_ctx->lock);
else
- s->ctx->stats.sess_connect_renegotiate++;
+ CRYPTO_atomic_add(&s->session_ctx->stats.sess_connect_renegotiate,
+ 1, &discard, s->session_ctx->lock);
/* mark client_random uninitialized */
memset(s->s3->client_random, 0, sizeof(s->s3->client_random));
goto err;
}
pkey = s->s3->tmp.cert->privatekey;
- md = ssl_md(lu->hash_idx);
- if (pkey == NULL || md == NULL) {
+ if (pkey == NULL || !tls1_lookup_md(lu, &md)) {
SSLerr(SSL_F_TLS_CONSTRUCT_CERT_VERIFY, ERR_R_INTERNAL_ERROR);
goto err;
}
#ifndef OPENSSL_NO_GOST
unsigned char *gost_data = NULL;
#endif
- int al = SSL_AD_INTERNAL_ERROR, ret = MSG_PROCESS_ERROR;
- int type = 0, j;
+ int al = SSL_AD_INTERNAL_ERROR;
+ MSG_PROCESS_RETURN ret = MSG_PROCESS_ERROR;
+ int j;
unsigned int len;
X509 *peer;
const EVP_MD *md = NULL;
if (pkey == NULL)
goto f_err;
- type = X509_certificate_type(peer, pkey);
-
- if (!(type & EVP_PKT_SIGN)) {
+ if (ssl_cert_lookup_by_pkey(pkey, NULL) == NULL) {
SSLerr(SSL_F_TLS_PROCESS_CERT_VERIFY,
SSL_R_SIGNATURE_FOR_NON_SIGNING_CERTIFICATE);
al = SSL_AD_ILLEGAL_PARAMETER;
goto f_err;
}
- md = ssl_md(s->s3->tmp.peer_sigalg->hash_idx);
+ if (!tls1_lookup_md(s->s3->tmp.peer_sigalg, &md)) {
+ SSLerr(SSL_F_TLS_PROCESS_CERT_VERIFY, ERR_R_INTERNAL_ERROR);
+ al = SSL_AD_INTERNAL_ERROR;
+ goto f_err;
+ }
/* Check for broken implementations of GOST ciphersuites */
/*
}
} else {
j = EVP_DigestVerify(mctx, data, len, hdata, hdatalen);
- if (j < 0) {
- SSLerr(SSL_F_TLS_PROCESS_CERT_VERIFY, ERR_R_EVP_LIB);
- goto f_err;
- } else if (j == 0) {
+ if (j <= 0) {
al = SSL_AD_DECRYPT_ERROR;
SSLerr(SSL_F_TLS_PROCESS_CERT_VERIFY, SSL_R_BAD_SIGNATURE);
goto f_err;
&& (!s->method->ssl3_enc->change_cipher_state(s,
SSL3_CC_HANDSHAKE | SSL3_CHANGE_CIPHER_CLIENT_WRITE))) {
SSLerr(SSL_F_TLS_CONSTRUCT_FINISHED, SSL_R_CANNOT_CHANGE_CIPHER);
- goto err;
+ /*
+ * This is a fatal error, which leaves
+ * enc_write_ctx in an inconsistent state
+ * and thus ssl3_send_alert may crash.
+ */
+ return 0;
}
if (s->server) {
*/
WORK_STATE tls_finish_handshake(SSL *s, WORK_STATE wst, int clearbufs)
{
+ int discard;
void (*cb) (const SSL *ssl, int type, int val) = NULL;
#ifndef OPENSSL_NO_SCTP
if (s->server) {
ssl_update_cache(s, SSL_SESS_CACHE_SERVER);
- s->ctx->stats.sess_accept_good++;
+ /* N.B. s->ctx may not equal s->session_ctx */
+ CRYPTO_atomic_add(&s->ctx->stats.sess_accept_good, 1, &discard,
+ s->ctx->lock);
s->handshake_func = ossl_statem_accept;
} else {
- ssl_update_cache(s, SSL_SESS_CACHE_CLIENT);
+ /*
+ * In TLSv1.3 we update the cache as part of processing the
+ * NewSessionTicket
+ */
+ if (!SSL_IS_TLS13(s))
+ ssl_update_cache(s, SSL_SESS_CACHE_CLIENT);
if (s->hit)
- s->ctx->stats.sess_hit++;
+ CRYPTO_atomic_add(&s->session_ctx->stats.sess_hit, 1, &discard,
+ s->session_ctx->lock);
s->handshake_func = ossl_statem_connect;
- s->ctx->stats.sess_connect_good++;
+ CRYPTO_atomic_add(&s->session_ctx->stats.sess_connect_good, 1,
+ &discard, s->session_ctx->lock);
}
if (s->info_callback != NULL)
return 1;
}
-int ssl_cert_type(const X509 *x, const EVP_PKEY *pk)
-{
- if (pk == NULL && (pk = X509_get0_pubkey(x)) == NULL)
- return -1;
-
- switch (EVP_PKEY_id(pk)) {
- default:
- return -1;
- case EVP_PKEY_RSA:
- return SSL_PKEY_RSA;
- case EVP_PKEY_DSA:
- return SSL_PKEY_DSA_SIGN;
-#ifndef OPENSSL_NO_EC
- case EVP_PKEY_EC:
- return SSL_PKEY_ECC;
-#endif
-#ifndef OPENSSL_NO_GOST
- case NID_id_GostR3410_2001:
- return SSL_PKEY_GOST01;
- case NID_id_GostR3410_2012_256:
- return SSL_PKEY_GOST12_256;
- case NID_id_GostR3410_2012_512:
- return SSL_PKEY_GOST12_512;
-#endif
- }
-}
-
int ssl_verify_alarm_type(long type)
{
int al;
al = SSL_AD_CERTIFICATE_UNKNOWN;
break;
}
- return (al);
+ return al;
}
int ssl_allow_compression(SSL *s)
* 1) or 0 otherwise.
*/
#ifndef OPENSSL_NO_EC
-int check_in_list(SSL *s, unsigned int group_id, const unsigned char *groups,
+int check_in_list(SSL *s, uint16_t group_id, const uint16_t *groups,
size_t num_groups, int checkallow)
{
size_t i;
if (groups == NULL || num_groups == 0)
return 0;
- for (i = 0; i < num_groups; i++, groups += 2) {
- if (group_id == GET_GROUP_ID(groups, 0)
+ for (i = 0; i < num_groups; i++) {
+ uint16_t group = groups[i];
+
+ if (group_id == group
&& (!checkallow
- || tls_curve_allowed(s, groups, SSL_SECOP_CURVE_CHECK))) {
+ || tls_curve_allowed(s, group, SSL_SECOP_CURVE_CHECK))) {
return 1;
}
}
/* Inject the synthetic message_hash message */
msghdr[0] = SSL3_MT_MESSAGE_HASH;
- msghdr[SSL3_HM_HEADER_LENGTH - 1] = hashlen;
+ msghdr[SSL3_HM_HEADER_LENGTH - 1] = (unsigned char)hashlen;
if (!ssl3_finish_mac(s, msghdr, SSL3_HM_HEADER_LENGTH)
|| !ssl3_finish_mac(s, hashval, hashlen)) {
SSLerr(SSL_F_CREATE_SYNTHETIC_MESSAGE_HASH, ERR_R_INTERNAL_ERROR);
return 1;
}
+
+/* Create a buffer containing data to be signed for server key exchange */
+size_t construct_key_exchange_tbs(const SSL *s, unsigned char **ptbs,
+ const void *param, size_t paramlen)
+{
+ size_t tbslen = 2 * SSL3_RANDOM_SIZE + paramlen;
+ unsigned char *tbs = OPENSSL_malloc(tbslen);
+
+ if (tbs == NULL)
+ return 0;
+ memcpy(tbs, s->s3->client_random, SSL3_RANDOM_SIZE);
+ memcpy(tbs + SSL3_RANDOM_SIZE, s->s3->server_random, SSL3_RANDOM_SIZE);
+
+ memcpy(tbs + SSL3_RANDOM_SIZE * 2, param, paramlen);
+
+ *ptbs = tbs;
+ return tbslen;
+}