#include "internal/e_os.h"
#include <stdio.h>
#include "../ssl_local.h"
#include "statem_local.h"
#include "internal/constant_time.h"
#include "internal/cryptlib.h"
#include "internal/ssl_unwrap.h"
#include <openssl/buffer.h>
#include <openssl/rand.h>
#include <openssl/objects.h>
#include <openssl/evp.h>
#include <openssl/x509.h>
#include <openssl/dh.h>
#include <openssl/rsa.h>
#include <openssl/bn.h>
#include <openssl/md5.h>
#include <openssl/trace.h>
#include <openssl/core_names.h>
#include <openssl/asn1t.h>
#include <openssl/comp.h>
#include "internal/comp.h"
#define TICKET_NONCE_SIZE 8
typedef struct {
ASN1_TYPE *kxBlob;
ASN1_TYPE *opaqueBlob;
} GOST_KX_MESSAGE;
DECLARE_ASN1_FUNCTIONS(GOST_KX_MESSAGE)
ASN1_SEQUENCE(GOST_KX_MESSAGE) = {
ASN1_SIMPLE(GOST_KX_MESSAGE, kxBlob, ASN1_ANY),
ASN1_OPT(GOST_KX_MESSAGE, opaqueBlob, ASN1_ANY),
} ASN1_SEQUENCE_END(GOST_KX_MESSAGE)
IMPLEMENT_ASN1_FUNCTIONS(GOST_KX_MESSAGE)
static CON_FUNC_RETURN tls_construct_encrypted_extensions(SSL_CONNECTION *s,
WPACKET *pkt);
static ossl_inline int received_client_cert(const SSL_CONNECTION *sc)
{
return sc->session->peer_rpk != NULL || sc->session->peer != NULL;
}
static int ossl_statem_server13_read_transition(SSL_CONNECTION *s, int mt)
{
OSSL_STATEM *st = &s->statem;
switch (st->hand_state) {
default:
break;
case TLS_ST_EARLY_DATA:
if (s->hello_retry_request == SSL_HRR_PENDING) {
if (mt == SSL3_MT_CLIENT_HELLO) {
st->hand_state = TLS_ST_SR_CLNT_HELLO;
return 1;
}
break;
} else if (s->ext.early_data == SSL_EARLY_DATA_ACCEPTED
&& !SSL_NO_EOED(s)) {
if (mt == SSL3_MT_END_OF_EARLY_DATA) {
st->hand_state = TLS_ST_SR_END_OF_EARLY_DATA;
return 1;
}
break;
}
case TLS_ST_SR_END_OF_EARLY_DATA:
case TLS_ST_SW_FINISHED:
if (s->s3.tmp.cert_request) {
if (mt == SSL3_MT_CERTIFICATE) {
st->hand_state = TLS_ST_SR_CERT;
return 1;
}
#ifndef OPENSSL_NO_COMP_ALG
if (mt == SSL3_MT_COMPRESSED_CERTIFICATE
&& s->ext.compress_certificate_sent) {
st->hand_state = TLS_ST_SR_COMP_CERT;
return 1;
}
#endif
} else {
if (mt == SSL3_MT_FINISHED) {
st->hand_state = TLS_ST_SR_FINISHED;
return 1;
}
}
break;
case TLS_ST_SR_COMP_CERT:
case TLS_ST_SR_CERT:
if (!received_client_cert(s)) {
if (mt == SSL3_MT_FINISHED) {
st->hand_state = TLS_ST_SR_FINISHED;
return 1;
}
} else {
if (mt == SSL3_MT_CERTIFICATE_VERIFY) {
st->hand_state = TLS_ST_SR_CERT_VRFY;
return 1;
}
}
break;
case TLS_ST_SR_CERT_VRFY:
if (mt == SSL3_MT_FINISHED) {
st->hand_state = TLS_ST_SR_FINISHED;
return 1;
}
break;
case TLS_ST_OK:
if (s->early_data_state == SSL_EARLY_DATA_READING)
break;
if (s->post_handshake_auth == SSL_PHA_REQUESTED) {
if (mt == SSL3_MT_CERTIFICATE) {
st->hand_state = TLS_ST_SR_CERT;
return 1;
}
#ifndef OPENSSL_NO_COMP_ALG
if (mt == SSL3_MT_COMPRESSED_CERTIFICATE
&& s->ext.compress_certificate_sent) {
st->hand_state = TLS_ST_SR_COMP_CERT;
return 1;
}
#endif
}
if (mt == SSL3_MT_KEY_UPDATE && !SSL_IS_QUIC_HANDSHAKE(s)) {
st->hand_state = TLS_ST_SR_KEY_UPDATE;
return 1;
}
break;
}
return 0;
}
int ossl_statem_server_read_transition(SSL_CONNECTION *s, int mt)
{
OSSL_STATEM *st = &s->statem;
if (SSL_CONNECTION_IS_TLS13(s)) {
if (!ossl_statem_server13_read_transition(s, mt))
goto err;
return 1;
}
switch (st->hand_state) {
default:
break;
case TLS_ST_BEFORE:
case TLS_ST_OK:
case DTLS_ST_SW_HELLO_VERIFY_REQUEST:
if (mt == SSL3_MT_CLIENT_HELLO) {
st->hand_state = TLS_ST_SR_CLNT_HELLO;
return 1;
}
break;
case TLS_ST_SW_SRVR_DONE:
if (mt == SSL3_MT_CLIENT_KEY_EXCHANGE) {
if (s->s3.tmp.cert_request) {
if (s->version == SSL3_VERSION) {
if ((s->verify_mode & SSL_VERIFY_PEER)
&& (s->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT)) {
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE);
return 0;
}
st->hand_state = TLS_ST_SR_KEY_EXCH;
return 1;
}
} else {
st->hand_state = TLS_ST_SR_KEY_EXCH;
return 1;
}
} else if (s->s3.tmp.cert_request) {
if (mt == SSL3_MT_CERTIFICATE) {
st->hand_state = TLS_ST_SR_CERT;
return 1;
}
}
break;
case TLS_ST_SR_CERT:
if (mt == SSL3_MT_CLIENT_KEY_EXCHANGE) {
st->hand_state = TLS_ST_SR_KEY_EXCH;
return 1;
}
break;
case TLS_ST_SR_KEY_EXCH:
if (!received_client_cert(s) || st->no_cert_verify) {
if (mt == SSL3_MT_CHANGE_CIPHER_SPEC) {
st->hand_state = TLS_ST_SR_CHANGE;
return 1;
}
} else {
if (mt == SSL3_MT_CERTIFICATE_VERIFY) {
st->hand_state = TLS_ST_SR_CERT_VRFY;
return 1;
}
}
break;
case TLS_ST_SR_CERT_VRFY:
if (mt == SSL3_MT_CHANGE_CIPHER_SPEC) {
st->hand_state = TLS_ST_SR_CHANGE;
return 1;
}
break;
case TLS_ST_SR_CHANGE:
#ifndef OPENSSL_NO_NEXTPROTONEG
if (s->s3.npn_seen) {
if (mt == SSL3_MT_NEXT_PROTO) {
st->hand_state = TLS_ST_SR_NEXT_PROTO;
return 1;
}
} else {
#endif
if (mt == SSL3_MT_FINISHED) {
st->hand_state = TLS_ST_SR_FINISHED;
return 1;
}
#ifndef OPENSSL_NO_NEXTPROTONEG
}
#endif
break;
#ifndef OPENSSL_NO_NEXTPROTONEG
case TLS_ST_SR_NEXT_PROTO:
if (mt == SSL3_MT_FINISHED) {
st->hand_state = TLS_ST_SR_FINISHED;
return 1;
}
break;
#endif
case TLS_ST_SW_FINISHED:
if (mt == SSL3_MT_CHANGE_CIPHER_SPEC) {
st->hand_state = TLS_ST_SR_CHANGE;
return 1;
}
break;
}
err:
if (SSL_CONNECTION_IS_DTLS(s) && mt == SSL3_MT_CHANGE_CIPHER_SPEC) {
BIO *rbio;
s->init_num = 0;
s->rwstate = SSL_READING;
rbio = SSL_get_rbio(SSL_CONNECTION_GET_SSL(s));
BIO_clear_retry_flags(rbio);
BIO_set_retry_read(rbio);
return 0;
}
SSLfatal(s, SSL3_AD_UNEXPECTED_MESSAGE, SSL_R_UNEXPECTED_MESSAGE);
return 0;
}
static int send_server_key_exchange(SSL_CONNECTION *s)
{
unsigned long alg_k = s->s3.tmp.new_cipher->algorithm_mkey;
if (alg_k & (SSL_kDHE | SSL_kECDHE)
#ifndef OPENSSL_NO_PSK
|| ((alg_k & (SSL_kPSK | SSL_kRSAPSK))
&& s->cert->psk_identity_hint)
|| (alg_k & (SSL_PSK & (SSL_kDHEPSK | SSL_kECDHEPSK)))
#endif
#ifndef OPENSSL_NO_SRP
|| (alg_k & SSL_kSRP)
#endif
) {
return 1;
}
return 0;
}
static int get_compressed_certificate_alg(SSL_CONNECTION *sc)
{
#ifndef OPENSSL_NO_COMP_ALG
int *alg = sc->ext.compress_certificate_from_peer;
if (sc->s3.tmp.cert == NULL)
return TLSEXT_comp_cert_none;
for (; *alg != TLSEXT_comp_cert_none; alg++) {
if (sc->s3.tmp.cert->comp_cert[*alg] != NULL)
return *alg;
}
#endif
return TLSEXT_comp_cert_none;
}
int send_certificate_request(SSL_CONNECTION *s)
{
if (
s->verify_mode & SSL_VERIFY_PEER
&& (!SSL_CONNECTION_IS_TLS13(s)
|| !(s->verify_mode & SSL_VERIFY_POST_HANDSHAKE)
|| s->post_handshake_auth == SSL_PHA_REQUEST_PENDING)
&& (s->certreqs_sent < 1 || !(s->verify_mode & SSL_VERIFY_CLIENT_ONCE))
&& (!(s->s3.tmp.new_cipher->algorithm_auth & SSL_aNULL)
|| (s->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT))
&& !(s->s3.tmp.new_cipher->algorithm_auth & SSL_aSRP)
&& !(s->s3.tmp.new_cipher->algorithm_auth & SSL_aPSK)) {
return 1;
}
return 0;
}
static int do_compressed_cert(SSL_CONNECTION *sc)
{
return sc->ext.server_cert_type == TLSEXT_cert_type_x509
&& get_compressed_certificate_alg(sc) != TLSEXT_comp_cert_none;
}
static WRITE_TRAN ossl_statem_server13_write_transition(SSL_CONNECTION *s)
{
OSSL_STATEM *st = &s->statem;
switch (st->hand_state) {
default:
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return WRITE_TRAN_ERROR;
case TLS_ST_OK:
if (s->key_update != SSL_KEY_UPDATE_NONE) {
st->hand_state = TLS_ST_SW_KEY_UPDATE;
return WRITE_TRAN_CONTINUE;
}
if (s->post_handshake_auth == SSL_PHA_REQUEST_PENDING) {
st->hand_state = TLS_ST_SW_CERT_REQ;
return WRITE_TRAN_CONTINUE;
}
if (s->ext.extra_tickets_expected > 0) {
st->hand_state = TLS_ST_SW_SESSION_TICKET;
return WRITE_TRAN_CONTINUE;
}
return WRITE_TRAN_FINISHED;
case TLS_ST_SR_CLNT_HELLO:
st->hand_state = TLS_ST_SW_SRVR_HELLO;
return WRITE_TRAN_CONTINUE;
case TLS_ST_SW_SRVR_HELLO:
if ((s->options & SSL_OP_ENABLE_MIDDLEBOX_COMPAT) != 0
&& s->hello_retry_request != SSL_HRR_COMPLETE)
st->hand_state = TLS_ST_SW_CHANGE;
else if (s->hello_retry_request == SSL_HRR_PENDING)
st->hand_state = TLS_ST_EARLY_DATA;
else
st->hand_state = TLS_ST_SW_ENCRYPTED_EXTENSIONS;
return WRITE_TRAN_CONTINUE;
case TLS_ST_SW_CHANGE:
if (s->hello_retry_request == SSL_HRR_PENDING)
st->hand_state = TLS_ST_EARLY_DATA;
else
st->hand_state = TLS_ST_SW_ENCRYPTED_EXTENSIONS;
return WRITE_TRAN_CONTINUE;
case TLS_ST_SW_ENCRYPTED_EXTENSIONS:
if (s->hit)
st->hand_state = TLS_ST_SW_FINISHED;
else if (send_certificate_request(s))
st->hand_state = TLS_ST_SW_CERT_REQ;
else if (do_compressed_cert(s))
st->hand_state = TLS_ST_SW_COMP_CERT;
else
st->hand_state = TLS_ST_SW_CERT;
return WRITE_TRAN_CONTINUE;
case TLS_ST_SW_CERT_REQ:
if (s->post_handshake_auth == SSL_PHA_REQUEST_PENDING) {
s->post_handshake_auth = SSL_PHA_REQUESTED;
st->hand_state = TLS_ST_OK;
} else if (do_compressed_cert(s)) {
st->hand_state = TLS_ST_SW_COMP_CERT;
} else {
st->hand_state = TLS_ST_SW_CERT;
}
return WRITE_TRAN_CONTINUE;
case TLS_ST_SW_COMP_CERT:
case TLS_ST_SW_CERT:
st->hand_state = TLS_ST_SW_CERT_VRFY;
return WRITE_TRAN_CONTINUE;
case TLS_ST_SW_CERT_VRFY:
st->hand_state = TLS_ST_SW_FINISHED;
return WRITE_TRAN_CONTINUE;
case TLS_ST_SW_FINISHED:
st->hand_state = TLS_ST_EARLY_DATA;
s->ts_msg_write = ossl_time_now();
return WRITE_TRAN_CONTINUE;
case TLS_ST_EARLY_DATA:
return WRITE_TRAN_FINISHED;
case TLS_ST_SR_FINISHED:
s->ts_msg_read = ossl_time_now();
if (s->post_handshake_auth == SSL_PHA_REQUESTED) {
s->post_handshake_auth = SSL_PHA_EXT_RECEIVED;
} else if (!s->ext.ticket_expected) {
st->hand_state = TLS_ST_OK;
return WRITE_TRAN_CONTINUE;
}
if (s->num_tickets > s->sent_tickets)
st->hand_state = TLS_ST_SW_SESSION_TICKET;
else
st->hand_state = TLS_ST_OK;
return WRITE_TRAN_CONTINUE;
case TLS_ST_SR_KEY_UPDATE:
case TLS_ST_SW_KEY_UPDATE:
st->hand_state = TLS_ST_OK;
return WRITE_TRAN_CONTINUE;
case TLS_ST_SW_SESSION_TICKET:
if (!SSL_IS_FIRST_HANDSHAKE(s) && s->ext.extra_tickets_expected > 0) {
return WRITE_TRAN_CONTINUE;
} else if (s->hit || s->num_tickets <= s->sent_tickets) {
st->hand_state = TLS_ST_OK;
}
return WRITE_TRAN_CONTINUE;
}
}
WRITE_TRAN ossl_statem_server_write_transition(SSL_CONNECTION *s)
{
OSSL_STATEM *st = &s->statem;
if (SSL_CONNECTION_IS_TLS13(s))
return ossl_statem_server13_write_transition(s);
switch (st->hand_state) {
default:
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return WRITE_TRAN_ERROR;
case TLS_ST_OK:
if (st->request_state == TLS_ST_SW_HELLO_REQ) {
st->hand_state = TLS_ST_SW_HELLO_REQ;
st->request_state = TLS_ST_BEFORE;
return WRITE_TRAN_CONTINUE;
}
if (!tls_setup_handshake(s)) {
return WRITE_TRAN_ERROR;
}
case TLS_ST_BEFORE:
return WRITE_TRAN_FINISHED;
case TLS_ST_SW_HELLO_REQ:
st->hand_state = TLS_ST_OK;
return WRITE_TRAN_CONTINUE;
case TLS_ST_SR_CLNT_HELLO:
if (SSL_CONNECTION_IS_DTLS(s) && !s->d1->cookie_verified
&& (SSL_get_options(SSL_CONNECTION_GET_SSL(s)) & SSL_OP_COOKIE_EXCHANGE)) {
st->hand_state = DTLS_ST_SW_HELLO_VERIFY_REQUEST;
} else if (s->renegotiate == 0 && !SSL_IS_FIRST_HANDSHAKE(s)) {
st->hand_state = TLS_ST_OK;
return WRITE_TRAN_CONTINUE;
} else {
st->hand_state = TLS_ST_SW_SRVR_HELLO;
}
return WRITE_TRAN_CONTINUE;
case DTLS_ST_SW_HELLO_VERIFY_REQUEST:
return WRITE_TRAN_FINISHED;
case TLS_ST_SW_SRVR_HELLO:
if (s->hit) {
if (s->ext.ticket_expected)
st->hand_state = TLS_ST_SW_SESSION_TICKET;
else
st->hand_state = TLS_ST_SW_CHANGE;
} else {
if (!(s->s3.tmp.new_cipher->algorithm_auth & (SSL_aNULL | SSL_aSRP | SSL_aPSK))) {
st->hand_state = TLS_ST_SW_CERT;
} else if (send_server_key_exchange(s)) {
st->hand_state = TLS_ST_SW_KEY_EXCH;
} else if (send_certificate_request(s)) {
st->hand_state = TLS_ST_SW_CERT_REQ;
} else {
st->hand_state = TLS_ST_SW_SRVR_DONE;
}
}
return WRITE_TRAN_CONTINUE;
case TLS_ST_SW_CERT:
if (s->ext.status_expected) {
st->hand_state = TLS_ST_SW_CERT_STATUS;
return WRITE_TRAN_CONTINUE;
}
case TLS_ST_SW_CERT_STATUS:
if (send_server_key_exchange(s)) {
st->hand_state = TLS_ST_SW_KEY_EXCH;
return WRITE_TRAN_CONTINUE;
}
case TLS_ST_SW_KEY_EXCH:
if (send_certificate_request(s)) {
st->hand_state = TLS_ST_SW_CERT_REQ;
return WRITE_TRAN_CONTINUE;
}
case TLS_ST_SW_CERT_REQ:
st->hand_state = TLS_ST_SW_SRVR_DONE;
return WRITE_TRAN_CONTINUE;
case TLS_ST_SW_SRVR_DONE:
s->ts_msg_write = ossl_time_now();
return WRITE_TRAN_FINISHED;
case TLS_ST_SR_FINISHED:
s->ts_msg_read = ossl_time_now();
if (s->hit) {
st->hand_state = TLS_ST_OK;
return WRITE_TRAN_CONTINUE;
} else if (s->ext.ticket_expected) {
st->hand_state = TLS_ST_SW_SESSION_TICKET;
} else {
st->hand_state = TLS_ST_SW_CHANGE;
}
return WRITE_TRAN_CONTINUE;
case TLS_ST_SW_SESSION_TICKET:
st->hand_state = TLS_ST_SW_CHANGE;
return WRITE_TRAN_CONTINUE;
case TLS_ST_SW_CHANGE:
st->hand_state = TLS_ST_SW_FINISHED;
return WRITE_TRAN_CONTINUE;
case TLS_ST_SW_FINISHED:
if (s->hit) {
return WRITE_TRAN_FINISHED;
}
st->hand_state = TLS_ST_OK;
return WRITE_TRAN_CONTINUE;
}
}
WORK_STATE ossl_statem_server_pre_work(SSL_CONNECTION *s, WORK_STATE wst)
{
OSSL_STATEM *st = &s->statem;
SSL *ssl = SSL_CONNECTION_GET_SSL(s);
switch (st->hand_state) {
default:
break;
case TLS_ST_SW_HELLO_REQ:
s->shutdown = 0;
if (SSL_CONNECTION_IS_DTLS(s))
dtls1_clear_sent_buffer(s);
break;
case DTLS_ST_SW_HELLO_VERIFY_REQUEST:
s->shutdown = 0;
if (SSL_CONNECTION_IS_DTLS(s)) {
dtls1_clear_sent_buffer(s);
st->use_timer = 0;
}
break;
case TLS_ST_SW_SRVR_HELLO:
if (SSL_CONNECTION_IS_DTLS(s)) {
st->use_timer = 1;
}
break;
case TLS_ST_SW_SRVR_DONE:
#ifndef OPENSSL_NO_SCTP
if (SSL_CONNECTION_IS_DTLS(s) && BIO_dgram_is_sctp(SSL_get_wbio(ssl))) {
return dtls_wait_for_dry(s);
}
#endif
return WORK_FINISHED_CONTINUE;
case TLS_ST_SW_SESSION_TICKET:
if (SSL_CONNECTION_IS_TLS13(s) && s->sent_tickets == 0
&& s->ext.extra_tickets_expected == 0) {
return tls_finish_handshake(s, wst, 0, 0);
}
if (SSL_CONNECTION_IS_DTLS(s)) {
st->use_timer = 0;
}
break;
case TLS_ST_SW_CHANGE:
if (SSL_CONNECTION_IS_TLS13(s))
break;
if (s->session->cipher == NULL) {
s->session->cipher = s->s3.tmp.new_cipher;
} else if (s->session->cipher != s->s3.tmp.new_cipher) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return WORK_ERROR;
}
if (!ssl->method->ssl3_enc->setup_key_block(s)) {
return WORK_ERROR;
}
if (SSL_CONNECTION_IS_DTLS(s)) {
st->use_timer = 0;
}
return WORK_FINISHED_CONTINUE;
case TLS_ST_EARLY_DATA:
if (s->early_data_state != SSL_EARLY_DATA_ACCEPTING
&& (s->s3.flags & TLS1_FLAGS_STATELESS) == 0)
return WORK_FINISHED_CONTINUE;
if (SSL_NO_EOED(s) && s->ext.early_data == SSL_EARLY_DATA_ACCEPTED
&& s->early_data_state != SSL_EARLY_DATA_FINISHED_READING) {
s->early_data_state = SSL_EARLY_DATA_FINISHED_READING;
if (!ssl->method->ssl3_enc->change_cipher_state(s, SSL3_CC_HANDSHAKE | SSL3_CHANGE_CIPHER_SERVER_READ)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return WORK_ERROR;
}
return WORK_FINISHED_SWAP;
}
case TLS_ST_OK:
return tls_finish_handshake(s, wst, 1, 1);
}
return WORK_FINISHED_CONTINUE;
}
static ossl_inline int conn_is_closed(void)
{
switch (get_last_sys_error()) {
#if defined(EPIPE)
case EPIPE:
return 1;
#endif
#if defined(ECONNRESET)
case ECONNRESET:
return 1;
#endif
#if defined(WSAECONNRESET)
case WSAECONNRESET:
return 1;
#endif
default:
return 0;
}
}
WORK_STATE ossl_statem_server_post_work(SSL_CONNECTION *s, WORK_STATE wst)
{
OSSL_STATEM *st = &s->statem;
SSL *ssl = SSL_CONNECTION_GET_SSL(s);
s->init_num = 0;
switch (st->hand_state) {
default:
break;
case TLS_ST_SW_HELLO_REQ:
if (statem_flush(s) != 1)
return WORK_MORE_A;
if (!ssl3_init_finished_mac(s)) {
return WORK_ERROR;
}
break;
case DTLS_ST_SW_HELLO_VERIFY_REQUEST:
if (statem_flush(s) != 1)
return WORK_MORE_A;
if (s->version != DTLS1_BAD_VER && !ssl3_init_finished_mac(s)) {
return WORK_ERROR;
}
s->first_packet = 1;
break;
case TLS_ST_SW_SRVR_HELLO:
if (SSL_CONNECTION_IS_TLS13(s)
&& s->hello_retry_request == SSL_HRR_PENDING) {
if ((s->options & SSL_OP_ENABLE_MIDDLEBOX_COMPAT) == 0
&& statem_flush(s) != 1)
return WORK_MORE_A;
break;
}
#ifndef OPENSSL_NO_SCTP
if (SSL_CONNECTION_IS_DTLS(s) && s->hit) {
unsigned char sctpauthkey[64];
char labelbuffer[sizeof(DTLS1_SCTP_AUTH_LABEL)];
size_t labellen;
memcpy(labelbuffer, DTLS1_SCTP_AUTH_LABEL,
sizeof(DTLS1_SCTP_AUTH_LABEL));
labellen = sizeof(labelbuffer) - 1;
if (s->mode & SSL_MODE_DTLS_SCTP_LABEL_LENGTH_BUG)
labellen += 1;
if (SSL_export_keying_material(ssl, sctpauthkey,
sizeof(sctpauthkey), labelbuffer,
labellen, NULL, 0,
0)
<= 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return WORK_ERROR;
}
BIO_ctrl(SSL_get_wbio(ssl), BIO_CTRL_DGRAM_SCTP_ADD_AUTH_KEY,
sizeof(sctpauthkey), sctpauthkey);
}
#endif
if (!SSL_CONNECTION_IS_TLS13(s)
|| ((s->options & SSL_OP_ENABLE_MIDDLEBOX_COMPAT) != 0
&& s->hello_retry_request != SSL_HRR_COMPLETE))
break;
case TLS_ST_SW_CHANGE:
if (s->hello_retry_request == SSL_HRR_PENDING) {
if (!statem_flush(s))
return WORK_MORE_A;
break;
}
if (SSL_CONNECTION_IS_TLS13(s)) {
if (!ssl->method->ssl3_enc->setup_key_block(s)
|| !tls13_store_handshake_traffic_hash(s)
|| !ssl->method->ssl3_enc->change_cipher_state(s,
SSL3_CC_HANDSHAKE | SSL3_CHANGE_CIPHER_SERVER_WRITE)) {
return WORK_ERROR;
}
if (s->ext.early_data != SSL_EARLY_DATA_ACCEPTED
&& !ssl->method->ssl3_enc->change_cipher_state(s,
SSL3_CC_HANDSHAKE | SSL3_CHANGE_CIPHER_SERVER_READ)) {
return WORK_ERROR;
}
if (s->rlayer.rrlmethod->set_plain_alerts != NULL)
s->rlayer.rrlmethod->set_plain_alerts(s->rlayer.rrl, 1);
break;
}
#ifndef OPENSSL_NO_SCTP
if (SSL_CONNECTION_IS_DTLS(s) && !s->hit) {
BIO_ctrl(SSL_get_wbio(ssl), BIO_CTRL_DGRAM_SCTP_NEXT_AUTH_KEY,
0, NULL);
}
#endif
if (!ssl->method->ssl3_enc->change_cipher_state(s,
SSL3_CHANGE_CIPHER_SERVER_WRITE)) {
return WORK_ERROR;
}
break;
case TLS_ST_SW_SRVR_DONE:
if (statem_flush(s) != 1)
return WORK_MORE_A;
break;
case TLS_ST_SW_FINISHED:
if (statem_flush(s) != 1)
return WORK_MORE_A;
#ifndef OPENSSL_NO_SCTP
if (SSL_CONNECTION_IS_DTLS(s) && s->hit) {
BIO_ctrl(SSL_get_wbio(ssl), BIO_CTRL_DGRAM_SCTP_NEXT_AUTH_KEY,
0, NULL);
}
#endif
if (SSL_CONNECTION_IS_TLS13(s)) {
size_t dummy;
if (!ssl->method->ssl3_enc->generate_master_secret(s,
s->master_secret, s->handshake_secret, 0,
&dummy)
|| !tls13_store_server_finished_hash(s)
|| !ssl->method->ssl3_enc->change_cipher_state(s,
SSL3_CC_APPLICATION | SSL3_CHANGE_CIPHER_SERVER_WRITE))
return WORK_ERROR;
}
break;
case TLS_ST_SW_CERT_REQ:
if (s->post_handshake_auth == SSL_PHA_REQUEST_PENDING) {
if (statem_flush(s) != 1)
return WORK_MORE_A;
} else {
if (!SSL_CONNECTION_IS_TLS13(s)
|| (s->options & SSL_OP_NO_TX_CERTIFICATE_COMPRESSION) != 0)
s->ext.compress_certificate_from_peer[0] = TLSEXT_comp_cert_none;
}
break;
case TLS_ST_SW_ENCRYPTED_EXTENSIONS:
if (!s->hit && !send_certificate_request(s)) {
if (!SSL_CONNECTION_IS_TLS13(s)
|| (s->options & SSL_OP_NO_TX_CERTIFICATE_COMPRESSION) != 0)
s->ext.compress_certificate_from_peer[0] = TLSEXT_comp_cert_none;
}
break;
case TLS_ST_SW_KEY_UPDATE:
if (statem_flush(s) != 1)
return WORK_MORE_A;
if (!tls13_update_key(s, 1)) {
return WORK_ERROR;
}
break;
case TLS_ST_SW_SESSION_TICKET:
clear_sys_error();
if (SSL_CONNECTION_IS_TLS13(s) && statem_flush(s) != 1) {
if (SSL_get_error(ssl, 0) == SSL_ERROR_SYSCALL
&& conn_is_closed()) {
s->rwstate = SSL_NOTHING;
break;
}
return WORK_MORE_A;
}
break;
}
return WORK_FINISHED_CONTINUE;
}
int ossl_statem_server_construct_message(SSL_CONNECTION *s,
confunc_f *confunc, int *mt)
{
OSSL_STATEM *st = &s->statem;
switch (st->hand_state) {
default:
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_BAD_HANDSHAKE_STATE);
return 0;
case TLS_ST_SW_CHANGE:
if (SSL_CONNECTION_IS_DTLS(s))
*confunc = dtls_construct_change_cipher_spec;
else
*confunc = tls_construct_change_cipher_spec;
*mt = SSL3_MT_CHANGE_CIPHER_SPEC;
break;
case DTLS_ST_SW_HELLO_VERIFY_REQUEST:
*confunc = dtls_construct_hello_verify_request;
*mt = DTLS1_MT_HELLO_VERIFY_REQUEST;
break;
case TLS_ST_SW_HELLO_REQ:
*confunc = NULL;
*mt = SSL3_MT_HELLO_REQUEST;
break;
case TLS_ST_SW_SRVR_HELLO:
*confunc = tls_construct_server_hello;
*mt = SSL3_MT_SERVER_HELLO;
break;
case TLS_ST_SW_CERT:
*confunc = tls_construct_server_certificate;
*mt = SSL3_MT_CERTIFICATE;
break;
#ifndef OPENSSL_NO_COMP_ALG
case TLS_ST_SW_COMP_CERT:
*confunc = tls_construct_server_compressed_certificate;
*mt = SSL3_MT_COMPRESSED_CERTIFICATE;
break;
#endif
case TLS_ST_SW_CERT_VRFY:
*confunc = tls_construct_cert_verify;
*mt = SSL3_MT_CERTIFICATE_VERIFY;
break;
case TLS_ST_SW_KEY_EXCH:
*confunc = tls_construct_server_key_exchange;
*mt = SSL3_MT_SERVER_KEY_EXCHANGE;
break;
case TLS_ST_SW_CERT_REQ:
*confunc = tls_construct_certificate_request;
*mt = SSL3_MT_CERTIFICATE_REQUEST;
break;
case TLS_ST_SW_SRVR_DONE:
*confunc = tls_construct_server_done;
*mt = SSL3_MT_SERVER_DONE;
break;
case TLS_ST_SW_SESSION_TICKET:
*confunc = tls_construct_new_session_ticket;
*mt = SSL3_MT_NEWSESSION_TICKET;
break;
case TLS_ST_SW_CERT_STATUS:
*confunc = tls_construct_cert_status;
*mt = SSL3_MT_CERTIFICATE_STATUS;
break;
case TLS_ST_SW_FINISHED:
*confunc = tls_construct_finished;
*mt = SSL3_MT_FINISHED;
break;
case TLS_ST_EARLY_DATA:
*confunc = NULL;
*mt = SSL3_MT_DUMMY;
break;
case TLS_ST_SW_ENCRYPTED_EXTENSIONS:
*confunc = tls_construct_encrypted_extensions;
*mt = SSL3_MT_ENCRYPTED_EXTENSIONS;
break;
case TLS_ST_SW_KEY_UPDATE:
*confunc = tls_construct_key_update;
*mt = SSL3_MT_KEY_UPDATE;
break;
}
return 1;
}
#define CLIENT_HELLO_MAX_LENGTH 131396
#define CLIENT_KEY_EXCH_MAX_LENGTH 2048
#define NEXT_PROTO_MAX_LENGTH 514
size_t ossl_statem_server_max_message_size(SSL_CONNECTION *s)
{
OSSL_STATEM *st = &s->statem;
switch (st->hand_state) {
default:
return 0;
case TLS_ST_SR_CLNT_HELLO:
return CLIENT_HELLO_MAX_LENGTH;
case TLS_ST_SR_END_OF_EARLY_DATA:
return END_OF_EARLY_DATA_MAX_LENGTH;
case TLS_ST_SR_COMP_CERT:
case TLS_ST_SR_CERT:
return s->max_cert_list;
case TLS_ST_SR_KEY_EXCH:
return CLIENT_KEY_EXCH_MAX_LENGTH;
case TLS_ST_SR_CERT_VRFY:
return CERTIFICATE_VERIFY_MAX_LENGTH;
#ifndef OPENSSL_NO_NEXTPROTONEG
case TLS_ST_SR_NEXT_PROTO:
return NEXT_PROTO_MAX_LENGTH;
#endif
case TLS_ST_SR_CHANGE:
return CCS_MAX_LENGTH;
case TLS_ST_SR_FINISHED:
return FINISHED_MAX_LENGTH;
case TLS_ST_SR_KEY_UPDATE:
return KEY_UPDATE_MAX_LENGTH;
}
}
MSG_PROCESS_RETURN ossl_statem_server_process_message(SSL_CONNECTION *s,
PACKET *pkt)
{
OSSL_STATEM *st = &s->statem;
switch (st->hand_state) {
default:
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return MSG_PROCESS_ERROR;
case TLS_ST_SR_CLNT_HELLO:
return tls_process_client_hello(s, pkt);
case TLS_ST_SR_END_OF_EARLY_DATA:
return tls_process_end_of_early_data(s, pkt);
case TLS_ST_SR_CERT:
return tls_process_client_certificate(s, pkt);
#ifndef OPENSSL_NO_COMP_ALG
case TLS_ST_SR_COMP_CERT:
return tls_process_client_compressed_certificate(s, pkt);
#endif
case TLS_ST_SR_KEY_EXCH:
return tls_process_client_key_exchange(s, pkt);
case TLS_ST_SR_CERT_VRFY:
return tls_process_cert_verify(s, pkt);
#ifndef OPENSSL_NO_NEXTPROTONEG
case TLS_ST_SR_NEXT_PROTO:
return tls_process_next_proto(s, pkt);
#endif
case TLS_ST_SR_CHANGE:
return tls_process_change_cipher_spec(s, pkt);
case TLS_ST_SR_FINISHED:
return tls_process_finished(s, pkt);
case TLS_ST_SR_KEY_UPDATE:
return tls_process_key_update(s, pkt);
}
}
WORK_STATE ossl_statem_server_post_process_message(SSL_CONNECTION *s,
WORK_STATE wst)
{
OSSL_STATEM *st = &s->statem;
switch (st->hand_state) {
default:
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return WORK_ERROR;
case TLS_ST_SR_CLNT_HELLO:
return tls_post_process_client_hello(s, wst);
case TLS_ST_SR_KEY_EXCH:
return tls_post_process_client_key_exchange(s, wst);
}
}
#ifndef OPENSSL_NO_SRP
static int ssl_check_srp_ext_ClientHello(SSL_CONNECTION *s)
{
int ret;
int al = SSL_AD_UNRECOGNIZED_NAME;
if ((s->s3.tmp.new_cipher->algorithm_mkey & SSL_kSRP) && (s->srp_ctx.TLS_ext_srp_username_callback != NULL)) {
if (s->srp_ctx.login == NULL) {
SSLfatal(s, SSL_AD_UNKNOWN_PSK_IDENTITY,
SSL_R_PSK_IDENTITY_NOT_FOUND);
return -1;
} else {
ret = ssl_srp_server_param_with_username_intern(s, &al);
if (ret < 0)
return 0;
if (ret == SSL3_AL_FATAL) {
SSLfatal(s, al,
al == SSL_AD_UNKNOWN_PSK_IDENTITY
? SSL_R_PSK_IDENTITY_NOT_FOUND
: SSL_R_CLIENTHELLO_TLSEXT);
return -1;
}
}
}
return 1;
}
#endif
int dtls_raw_hello_verify_request(WPACKET *pkt, unsigned char *cookie,
size_t cookie_len)
{
if (!WPACKET_put_bytes_u16(pkt, DTLS1_VERSION)
|| !WPACKET_sub_memcpy_u8(pkt, cookie, cookie_len))
return 0;
return 1;
}
CON_FUNC_RETURN dtls_construct_hello_verify_request(SSL_CONNECTION *s,
WPACKET *pkt)
{
unsigned int cookie_leni;
SSL_CTX *sctx = SSL_CONNECTION_GET_CTX(s);
if (sctx->app_gen_cookie_cb == NULL
|| sctx->app_gen_cookie_cb(SSL_CONNECTION_GET_USER_SSL(s), s->d1->cookie,
&cookie_leni)
== 0
|| cookie_leni > DTLS1_COOKIE_LENGTH) {
SSLfatal(s, SSL_AD_NO_ALERT, SSL_R_COOKIE_GEN_CALLBACK_FAILURE);
return CON_FUNC_ERROR;
}
s->d1->cookie_len = cookie_leni;
if (!dtls_raw_hello_verify_request(pkt, s->d1->cookie,
s->d1->cookie_len)) {
SSLfatal(s, SSL_AD_NO_ALERT, ERR_R_INTERNAL_ERROR);
return CON_FUNC_ERROR;
}
return CON_FUNC_SUCCESS;
}
static void ssl_check_for_safari(SSL_CONNECTION *s,
const CLIENTHELLO_MSG *hello)
{
static const unsigned char kSafariExtensionsBlock[] = {
0x00,
0x0a,
0x00,
0x08,
0x00,
0x06,
0x00,
0x17,
0x00,
0x18,
0x00,
0x19,
0x00,
0x0b,
0x00,
0x02,
0x01,
0x00,
0x00,
0x0d,
0x00,
0x0c,
0x00,
0x0a,
0x05,
0x01,
0x04,
0x01,
0x02,
0x01,
0x04,
0x03,
0x02,
0x03,
};
static const size_t kSafariCommonExtensionsLength = 18;
unsigned int type;
PACKET sni, tmppkt;
size_t ext_len;
tmppkt = hello->extensions;
if (!PACKET_forward(&tmppkt, 2)
|| !PACKET_get_net_2(&tmppkt, &type)
|| !PACKET_get_length_prefixed_2(&tmppkt, &sni)) {
return;
}
if (type != TLSEXT_TYPE_server_name)
return;
ext_len = TLS1_get_client_version(
SSL_CONNECTION_GET_SSL(s))
>= TLS1_2_VERSION
? sizeof(kSafariExtensionsBlock)
: kSafariCommonExtensionsLength;
s->s3.is_probably_safari = PACKET_equal(&tmppkt, kSafariExtensionsBlock,
ext_len);
}
#define RENEG_OPTIONS_OK(options) \
((options & SSL_OP_NO_RENEGOTIATION) == 0 \
&& (options & SSL_OP_ALLOW_CLIENT_RENEGOTIATION) != 0)
MSG_PROCESS_RETURN tls_process_client_hello(SSL_CONNECTION *s, PACKET *pkt)
{
PACKET session_id, compression, extensions, cookie;
static const unsigned char null_compression = 0;
CLIENTHELLO_MSG *clienthello = NULL;
if (s->renegotiate == 0 && !SSL_IS_FIRST_HANDSHAKE(s)) {
if (!ossl_assert(!SSL_CONNECTION_IS_TLS13(s))) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
if (!RENEG_OPTIONS_OK(s->options)
|| (!s->s3.send_connection_binding
&& (s->options
& SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION)
== 0)) {
ssl3_send_alert(s, SSL3_AL_WARNING, SSL_AD_NO_RENEGOTIATION);
return MSG_PROCESS_FINISHED_READING;
}
s->renegotiate = 1;
s->new_session = 1;
}
clienthello = OPENSSL_zalloc(sizeof(*clienthello));
if (clienthello == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
clienthello->isv2 = RECORD_LAYER_is_sslv2_record(&s->rlayer);
PACKET_null_init(&cookie);
if (clienthello->isv2) {
unsigned int mt;
if (!SSL_IS_FIRST_HANDSHAKE(s)
|| s->hello_retry_request != SSL_HRR_NONE) {
SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_R_UNEXPECTED_MESSAGE);
goto err;
}
if (!PACKET_get_1(pkt, &mt)
|| mt != SSL2_MT_CLIENT_HELLO) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
}
if (!PACKET_get_net_2(pkt, &clienthello->legacy_version)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_TOO_SHORT);
goto err;
}
if (clienthello->isv2) {
unsigned int ciphersuite_len, session_id_len, challenge_len;
PACKET challenge;
if (!PACKET_get_net_2(pkt, &ciphersuite_len)
|| !PACKET_get_net_2(pkt, &session_id_len)
|| !PACKET_get_net_2(pkt, &challenge_len)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_RECORD_LENGTH_MISMATCH);
goto err;
}
if (session_id_len > SSL_MAX_SSL_SESSION_ID_LENGTH) {
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_LENGTH_MISMATCH);
goto err;
}
if (!PACKET_get_sub_packet(pkt, &clienthello->ciphersuites,
ciphersuite_len)
|| !PACKET_copy_bytes(pkt, clienthello->session_id, session_id_len)
|| !PACKET_get_sub_packet(pkt, &challenge, challenge_len)
|| PACKET_remaining(pkt) != 0) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_RECORD_LENGTH_MISMATCH);
goto err;
}
clienthello->session_id_len = session_id_len;
challenge_len = challenge_len > SSL3_RANDOM_SIZE
? SSL3_RANDOM_SIZE
: challenge_len;
memset(clienthello->random, 0, SSL3_RANDOM_SIZE);
if (!PACKET_copy_bytes(&challenge,
clienthello->random + SSL3_RANDOM_SIZE - challenge_len, challenge_len)
|| !PACKET_buf_init(&compression, &null_compression, 1)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
PACKET_null_init(&clienthello->extensions);
} else {
if (!PACKET_copy_bytes(pkt, clienthello->random, SSL3_RANDOM_SIZE)
|| !PACKET_get_length_prefixed_1(pkt, &session_id)
|| !PACKET_copy_all(&session_id, clienthello->session_id,
SSL_MAX_SSL_SESSION_ID_LENGTH,
&clienthello->session_id_len)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH);
goto err;
}
if (SSL_CONNECTION_IS_DTLS(s)) {
if (!PACKET_get_length_prefixed_1(pkt, &cookie)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH);
goto err;
}
if (!PACKET_copy_all(&cookie, clienthello->dtls_cookie,
DTLS1_COOKIE_LENGTH,
&clienthello->dtls_cookie_len)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
if (SSL_get_options(SSL_CONNECTION_GET_SSL(s)) & SSL_OP_COOKIE_EXCHANGE) {
if (clienthello->dtls_cookie_len == 0) {
OPENSSL_free(clienthello);
return MSG_PROCESS_FINISHED_READING;
}
}
}
if (!PACKET_get_length_prefixed_2(pkt, &clienthello->ciphersuites)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH);
goto err;
}
if (!PACKET_get_length_prefixed_1(pkt, &compression)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH);
goto err;
}
if (PACKET_remaining(pkt) == 0) {
PACKET_null_init(&clienthello->extensions);
} else {
if (!PACKET_get_length_prefixed_2(pkt, &clienthello->extensions)
|| PACKET_remaining(pkt) != 0) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH);
goto err;
}
}
}
if (!PACKET_copy_all(&compression, clienthello->compressions,
MAX_COMPRESSIONS_SIZE,
&clienthello->compressions_len)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
extensions = clienthello->extensions;
if (!tls_collect_extensions(s, &extensions, SSL_EXT_CLIENT_HELLO,
&clienthello->pre_proc_exts,
&clienthello->pre_proc_exts_len, 1)) {
goto err;
}
s->clienthello = clienthello;
return MSG_PROCESS_CONTINUE_PROCESSING;
err:
if (clienthello != NULL)
OPENSSL_free(clienthello->pre_proc_exts);
OPENSSL_free(clienthello);
return MSG_PROCESS_ERROR;
}
static int tls_early_post_process_client_hello(SSL_CONNECTION *s)
{
unsigned int j;
int i, al = SSL_AD_INTERNAL_ERROR;
int protverr;
unsigned long id;
#ifndef OPENSSL_NO_COMP
SSL_COMP *comp = NULL;
#endif
const SSL_CIPHER *c;
STACK_OF(SSL_CIPHER) *ciphers = NULL;
STACK_OF(SSL_CIPHER) *scsvs = NULL;
CLIENTHELLO_MSG *clienthello = s->clienthello;
DOWNGRADE dgrd = DOWNGRADE_NONE;
SSL_CTX *sctx = SSL_CONNECTION_GET_CTX(s);
SSL *ssl = SSL_CONNECTION_GET_SSL(s);
SSL *ussl = SSL_CONNECTION_GET_USER_SSL(s);
if (sctx->client_hello_cb != NULL) {
switch (sctx->client_hello_cb(ussl, &al, sctx->client_hello_cb_arg)) {
case SSL_CLIENT_HELLO_SUCCESS:
break;
case SSL_CLIENT_HELLO_RETRY:
s->rwstate = SSL_CLIENT_HELLO_CB;
return -1;
case SSL_CLIENT_HELLO_ERROR:
default:
SSLfatal(s, al, SSL_R_CALLBACK_FAILED);
goto err;
}
}
memcpy(s->s3.client_random, clienthello->random, SSL3_RANDOM_SIZE);
if (clienthello->isv2) {
if (clienthello->legacy_version == SSL2_VERSION
|| (clienthello->legacy_version & 0xff00)
!= (SSL3_VERSION_MAJOR << 8)) {
SSLfatal(s, SSL_AD_PROTOCOL_VERSION, SSL_R_UNKNOWN_PROTOCOL);
goto err;
}
s->client_version = clienthello->legacy_version;
}
protverr = ssl_choose_server_version(s, clienthello, &dgrd);
if (protverr) {
if (SSL_IS_FIRST_HANDSHAKE(s)) {
s->version = s->client_version = clienthello->legacy_version;
}
SSLfatal(s, SSL_AD_PROTOCOL_VERSION, protverr);
goto err;
}
if (SSL_CONNECTION_IS_TLS13(s)
&& RECORD_LAYER_processed_read_pending(&s->rlayer)) {
SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_R_NOT_ON_RECORD_BOUNDARY);
goto err;
}
if (SSL_CONNECTION_IS_DTLS(s)) {
if (SSL_get_options(ssl) & SSL_OP_COOKIE_EXCHANGE) {
if (sctx->app_verify_cookie_cb != NULL) {
if (sctx->app_verify_cookie_cb(ussl, clienthello->dtls_cookie,
clienthello->dtls_cookie_len)
== 0) {
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
SSL_R_COOKIE_MISMATCH);
goto err;
}
} else if (s->d1->cookie_len != clienthello->dtls_cookie_len
|| memcmp(clienthello->dtls_cookie, s->d1->cookie,
s->d1->cookie_len)
!= 0) {
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_R_COOKIE_MISMATCH);
goto err;
}
s->d1->cookie_verified = 1;
}
}
s->hit = 0;
if (!ssl_cache_cipherlist(s, &clienthello->ciphersuites,
clienthello->isv2)
|| !ossl_bytes_to_cipher_list(s, &clienthello->ciphersuites, &ciphers,
&scsvs, clienthello->isv2, 1)) {
goto err;
}
s->s3.send_connection_binding = 0;
if (scsvs != NULL) {
for (i = 0; i < sk_SSL_CIPHER_num(scsvs); i++) {
c = sk_SSL_CIPHER_value(scsvs, i);
if (SSL_CIPHER_get_id(c) == SSL3_CK_SCSV) {
if (s->renegotiate) {
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
SSL_R_SCSV_RECEIVED_WHEN_RENEGOTIATING);
goto err;
}
s->s3.send_connection_binding = 1;
} else if (SSL_CIPHER_get_id(c) == SSL3_CK_FALLBACK_SCSV && !ssl_check_version_downgrade(s)) {
SSLfatal(s, SSL_AD_INAPPROPRIATE_FALLBACK,
SSL_R_INAPPROPRIATE_FALLBACK);
goto err;
}
}
}
if (SSL_CONNECTION_IS_TLS13(s)) {
const SSL_CIPHER *cipher = ssl3_choose_cipher(s, ciphers, SSL_get_ciphers(ssl));
if (cipher == NULL) {
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_R_NO_SHARED_CIPHER);
goto err;
}
if (s->hello_retry_request == SSL_HRR_PENDING
&& (s->s3.tmp.new_cipher == NULL
|| s->s3.tmp.new_cipher->id != cipher->id)) {
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_BAD_CIPHER);
goto err;
}
s->s3.tmp.new_cipher = cipher;
}
if (!tls_parse_extension(s, TLSEXT_IDX_extended_master_secret,
SSL_EXT_CLIENT_HELLO,
clienthello->pre_proc_exts, NULL, 0)) {
goto err;
}
if (clienthello->isv2 || (s->new_session && (s->options & SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION))) {
if (!ssl_get_new_session(s, 1)) {
goto err;
}
} else {
i = ssl_get_prev_session(s, clienthello);
if (i == 1) {
s->hit = 1;
} else if (i == -1) {
goto err;
} else {
if (!ssl_get_new_session(s, 1)) {
goto err;
}
}
}
if (SSL_CONNECTION_IS_TLS13(s)) {
memcpy(s->tmp_session_id, s->clienthello->session_id,
s->clienthello->session_id_len);
s->tmp_session_id_len = s->clienthello->session_id_len;
}
if (!SSL_CONNECTION_IS_TLS13(s) && s->hit) {
j = 0;
id = s->session->cipher->id;
OSSL_TRACE_BEGIN(TLS_CIPHER)
{
BIO_printf(trc_out, "client sent %d ciphers\n",
sk_SSL_CIPHER_num(ciphers));
}
for (i = 0; i < sk_SSL_CIPHER_num(ciphers); i++) {
c = sk_SSL_CIPHER_value(ciphers, i);
if (trc_out != NULL)
BIO_printf(trc_out, "client [%2d of %2d]:%s\n", i,
sk_SSL_CIPHER_num(ciphers), SSL_CIPHER_get_name(c));
if (c->id == id) {
j = 1;
break;
}
}
if (j == 0) {
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
SSL_R_REQUIRED_CIPHER_MISSING);
OSSL_TRACE_CANCEL(TLS_CIPHER);
goto err;
}
OSSL_TRACE_END(TLS_CIPHER);
}
if (clienthello->compressions_len == 0) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_NO_COMPRESSION_SPECIFIED);
goto err;
}
if (memchr(clienthello->compressions, 0,
clienthello->compressions_len)
== NULL) {
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
SSL_R_REQUIRED_COMPRESSION_ALGORITHM_MISSING);
goto err;
}
if (s->options & SSL_OP_SAFARI_ECDHE_ECDSA_BUG)
ssl_check_for_safari(s, clienthello);
if (!tls_parse_all_extensions(s, SSL_EXT_CLIENT_HELLO,
clienthello->pre_proc_exts, NULL, 0, 1)) {
goto err;
}
{
unsigned char *pos;
pos = s->s3.server_random;
if (ssl_fill_hello_random(s, 1, pos, SSL3_RANDOM_SIZE, dgrd) <= 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
}
if (!s->hit && !tls1_set_server_sigalgs(s)) {
goto err;
}
if (!s->hit
&& s->version >= TLS1_VERSION
&& !SSL_CONNECTION_IS_TLS13(s)
&& !SSL_CONNECTION_IS_DTLS(s)
&& s->ext.session_secret_cb != NULL) {
const SSL_CIPHER *pref_cipher = NULL;
int master_key_length;
master_key_length = sizeof(s->session->master_key);
if (s->ext.session_secret_cb(ussl, s->session->master_key,
&master_key_length, ciphers,
&pref_cipher,
s->ext.session_secret_cb_arg)
&& master_key_length > 0) {
s->session->master_key_length = master_key_length;
s->hit = 1;
s->peer_ciphers = ciphers;
s->session->verify_result = X509_V_OK;
ciphers = NULL;
if (pref_cipher == NULL)
pref_cipher = ssl3_choose_cipher(s, s->peer_ciphers,
SSL_get_ciphers(ssl));
if (pref_cipher == NULL) {
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_R_NO_SHARED_CIPHER);
goto err;
}
s->session->cipher = pref_cipher;
sk_SSL_CIPHER_free(s->cipher_list);
s->cipher_list = sk_SSL_CIPHER_dup(s->peer_ciphers);
sk_SSL_CIPHER_free(s->cipher_list_by_id);
s->cipher_list_by_id = sk_SSL_CIPHER_dup(s->peer_ciphers);
}
}
s->s3.tmp.new_compression = NULL;
if (SSL_CONNECTION_IS_TLS13(s)) {
if (clienthello->compressions_len != 1) {
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
SSL_R_INVALID_COMPRESSION_ALGORITHM);
goto err;
}
}
#ifndef OPENSSL_NO_COMP
else if (s->session->compress_meth != 0) {
int m, comp_id = s->session->compress_meth;
unsigned int k;
if (!ssl_allow_compression(s)) {
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
SSL_R_INCONSISTENT_COMPRESSION);
goto err;
}
for (m = 0; m < sk_SSL_COMP_num(sctx->comp_methods); m++) {
comp = sk_SSL_COMP_value(sctx->comp_methods, m);
if (comp_id == comp->id) {
s->s3.tmp.new_compression = comp;
break;
}
}
if (s->s3.tmp.new_compression == NULL) {
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
SSL_R_INVALID_COMPRESSION_ALGORITHM);
goto err;
}
for (k = 0; k < clienthello->compressions_len; k++) {
if (clienthello->compressions[k] == comp_id)
break;
}
if (k >= clienthello->compressions_len) {
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
SSL_R_REQUIRED_COMPRESSION_ALGORITHM_MISSING);
goto err;
}
} else if (s->hit) {
comp = NULL;
} else if (ssl_allow_compression(s) && sctx->comp_methods) {
int m, nn, v, done = 0;
unsigned int o;
nn = sk_SSL_COMP_num(sctx->comp_methods);
for (m = 0; m < nn; m++) {
comp = sk_SSL_COMP_value(sctx->comp_methods, m);
v = comp->id;
for (o = 0; o < clienthello->compressions_len; o++) {
if (v == clienthello->compressions[o]) {
done = 1;
break;
}
}
if (done)
break;
}
if (done)
s->s3.tmp.new_compression = comp;
else
comp = NULL;
}
#else
if (s->session->compress_meth != 0) {
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_R_INCONSISTENT_COMPRESSION);
goto err;
}
#endif
if (!s->hit || SSL_CONNECTION_IS_TLS13(s)) {
sk_SSL_CIPHER_free(s->peer_ciphers);
s->peer_ciphers = ciphers;
if (ciphers == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
ciphers = NULL;
}
if (!s->hit) {
#ifdef OPENSSL_NO_COMP
s->session->compress_meth = 0;
#else
s->session->compress_meth = (comp == NULL) ? 0 : comp->id;
#endif
}
sk_SSL_CIPHER_free(ciphers);
sk_SSL_CIPHER_free(scsvs);
OPENSSL_free(clienthello->pre_proc_exts);
OPENSSL_free(s->clienthello);
s->clienthello = NULL;
return 1;
err:
sk_SSL_CIPHER_free(ciphers);
sk_SSL_CIPHER_free(scsvs);
OPENSSL_free(clienthello->pre_proc_exts);
OPENSSL_free(s->clienthello);
s->clienthello = NULL;
return 0;
}
static int tls_handle_status_request(SSL_CONNECTION *s)
{
SSL_CTX *sctx = SSL_CONNECTION_GET_CTX(s);
s->ext.status_expected = 0;
if (s->ext.status_type != TLSEXT_STATUSTYPE_nothing && sctx != NULL
&& sctx->ext.status_cb != NULL) {
int ret;
if (s->s3.tmp.cert != NULL) {
s->cert->key = s->s3.tmp.cert;
ret = sctx->ext.status_cb(SSL_CONNECTION_GET_USER_SSL(s),
sctx->ext.status_arg);
switch (ret) {
case SSL_TLSEXT_ERR_NOACK:
s->ext.status_expected = 0;
break;
case SSL_TLSEXT_ERR_OK:
if (s->ext.ocsp.resp)
s->ext.status_expected = 1;
break;
case SSL_TLSEXT_ERR_ALERT_FATAL:
default:
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_CLIENTHELLO_TLSEXT);
return 0;
}
}
}
return 1;
}
int tls_handle_alpn(SSL_CONNECTION *s)
{
const unsigned char *selected = NULL;
unsigned char selected_len = 0;
SSL_CTX *sctx = SSL_CONNECTION_GET_CTX(s);
if (sctx->ext.alpn_select_cb != NULL && s->s3.alpn_proposed != NULL) {
int r = sctx->ext.alpn_select_cb(SSL_CONNECTION_GET_USER_SSL(s),
&selected, &selected_len,
s->s3.alpn_proposed,
(unsigned int)s->s3.alpn_proposed_len,
sctx->ext.alpn_select_cb_arg);
if (r == SSL_TLSEXT_ERR_OK) {
OPENSSL_free(s->s3.alpn_selected);
s->s3.alpn_selected = OPENSSL_memdup(selected, selected_len);
if (s->s3.alpn_selected == NULL) {
s->s3.alpn_selected_len = 0;
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
s->s3.alpn_selected_len = selected_len;
#ifndef OPENSSL_NO_NEXTPROTONEG
s->s3.npn_seen = 0;
#endif
if (s->session->ext.alpn_selected == NULL
|| selected_len != s->session->ext.alpn_selected_len
|| memcmp(selected, s->session->ext.alpn_selected,
selected_len)
!= 0) {
s->ext.early_data_ok = 0;
if (!s->hit) {
if (!ossl_assert(s->session->ext.alpn_selected == NULL)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
ERR_R_INTERNAL_ERROR);
return 0;
}
s->session->ext.alpn_selected = OPENSSL_memdup(selected,
selected_len);
if (s->session->ext.alpn_selected == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
ERR_R_INTERNAL_ERROR);
return 0;
}
s->session->ext.alpn_selected_len = selected_len;
}
}
return 1;
} else if (r != SSL_TLSEXT_ERR_NOACK) {
SSLfatal(s, SSL_AD_NO_APPLICATION_PROTOCOL,
SSL_R_NO_APPLICATION_PROTOCOL);
return 0;
}
}
if (s->session->ext.alpn_selected != NULL) {
s->ext.early_data_ok = 0;
}
return 1;
}
WORK_STATE tls_post_process_client_hello(SSL_CONNECTION *s, WORK_STATE wst)
{
const SSL_CIPHER *cipher;
SSL *ssl = SSL_CONNECTION_GET_SSL(s);
SSL *ussl = SSL_CONNECTION_GET_USER_SSL(s);
if (wst == WORK_MORE_A) {
int rv = tls_early_post_process_client_hello(s);
if (rv == 0) {
goto err;
}
if (rv < 0)
return WORK_MORE_A;
wst = WORK_MORE_B;
}
if (wst == WORK_MORE_B) {
if (!s->hit || SSL_CONNECTION_IS_TLS13(s)) {
if (!s->hit && s->cert->cert_cb != NULL) {
int rv = s->cert->cert_cb(ussl, s->cert->cert_cb_arg);
if (rv == 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_CERT_CB_ERROR);
goto err;
}
if (rv < 0) {
s->rwstate = SSL_X509_LOOKUP;
return WORK_MORE_B;
}
s->rwstate = SSL_NOTHING;
}
if (!SSL_CONNECTION_IS_TLS13(s)) {
cipher = ssl3_choose_cipher(s, s->peer_ciphers,
SSL_get_ciphers(ssl));
if (cipher == NULL) {
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
SSL_R_NO_SHARED_CIPHER);
goto err;
}
s->s3.tmp.new_cipher = cipher;
}
if (!s->hit) {
if (!tls_choose_sigalg(s, 1)) {
goto err;
}
if (s->not_resumable_session_cb != NULL)
s->session->not_resumable = s->not_resumable_session_cb(ussl,
((s->s3.tmp.new_cipher->algorithm_mkey
& (SSL_kDHE | SSL_kECDHE))
!= 0));
if (s->session->not_resumable)
s->ext.ticket_expected = 0;
}
} else {
s->s3.tmp.new_cipher = s->session->cipher;
}
if (!tls_handle_status_request(s)) {
goto err;
}
if (!SSL_CONNECTION_IS_TLS13(s) && !tls_handle_alpn(s)) {
goto err;
}
wst = WORK_MORE_C;
}
#ifndef OPENSSL_NO_SRP
if (wst == WORK_MORE_C) {
int ret;
if ((ret = ssl_check_srp_ext_ClientHello(s)) == 0) {
s->rwstate = SSL_X509_LOOKUP;
return WORK_MORE_C;
}
if (ret < 0) {
goto err;
}
}
#endif
return WORK_FINISHED_STOP;
err:
return WORK_ERROR;
}
CON_FUNC_RETURN tls_construct_server_hello(SSL_CONNECTION *s, WPACKET *pkt)
{
int compm;
size_t sl, len;
int version;
unsigned char *session_id;
int usetls13 = SSL_CONNECTION_IS_TLS13(s)
|| s->hello_retry_request == SSL_HRR_PENDING;
version = usetls13 ? TLS1_2_VERSION : s->version;
if (!WPACKET_put_bytes_u16(pkt, version)
|| !WPACKET_memcpy(pkt,
s->hello_retry_request == SSL_HRR_PENDING
? hrrrandom
: s->s3.server_random,
SSL3_RANDOM_SIZE)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return CON_FUNC_ERROR;
}
if (!(SSL_CONNECTION_GET_CTX(s)->session_cache_mode & SSL_SESS_CACHE_SERVER)
&& !s->hit)
s->session->session_id_length = 0;
if (usetls13) {
sl = s->tmp_session_id_len;
session_id = s->tmp_session_id;
} else {
sl = s->session->session_id_length;
session_id = s->session->session_id;
}
if (sl > sizeof(s->session->session_id)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return CON_FUNC_ERROR;
}
#ifdef OPENSSL_NO_COMP
compm = 0;
#else
if (usetls13 || s->s3.tmp.new_compression == NULL)
compm = 0;
else
compm = s->s3.tmp.new_compression->id;
#endif
if (!WPACKET_sub_memcpy_u8(pkt, session_id, sl)
|| !SSL_CONNECTION_GET_SSL(s)->method->put_cipher_by_char(s->s3.tmp.new_cipher,
pkt, &len)
|| !WPACKET_put_bytes_u8(pkt, compm)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return CON_FUNC_ERROR;
}
if (!tls_construct_extensions(s, pkt,
s->hello_retry_request == SSL_HRR_PENDING
? SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST
: (SSL_CONNECTION_IS_TLS13(s)
? SSL_EXT_TLS1_3_SERVER_HELLO
: SSL_EXT_TLS1_2_SERVER_HELLO),
NULL, 0)) {
return CON_FUNC_ERROR;
}
if (s->hello_retry_request == SSL_HRR_PENDING) {
SSL_SESSION_free(s->session);
s->session = NULL;
s->hit = 0;
if (!create_synthetic_message_hash(s, NULL, 0, NULL, 0)) {
return CON_FUNC_ERROR;
}
} else if (!(s->verify_mode & SSL_VERIFY_PEER)
&& !ssl3_digest_cached_records(s, 0)) {
;
return CON_FUNC_ERROR;
}
return CON_FUNC_SUCCESS;
}
CON_FUNC_RETURN tls_construct_server_done(SSL_CONNECTION *s, WPACKET *pkt)
{
if (!s->s3.tmp.cert_request) {
if (!ssl3_digest_cached_records(s, 0)) {
return CON_FUNC_ERROR;
}
}
return CON_FUNC_SUCCESS;
}
CON_FUNC_RETURN tls_construct_server_key_exchange(SSL_CONNECTION *s,
WPACKET *pkt)
{
EVP_PKEY *pkdh = NULL;
unsigned char *encodedPoint = NULL;
size_t encodedlen = 0;
int curve_id = 0;
const SIGALG_LOOKUP *lu = s->s3.tmp.sigalg;
int i;
unsigned long type;
BIGNUM *r[4];
EVP_MD_CTX *md_ctx = EVP_MD_CTX_new();
EVP_PKEY_CTX *pctx = NULL;
size_t paramlen, paramoffset;
int freer = 0;
CON_FUNC_RETURN ret = CON_FUNC_ERROR;
SSL_CTX *sctx = SSL_CONNECTION_GET_CTX(s);
if (!WPACKET_get_total_written(pkt, ¶moffset)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
if (md_ctx == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_EVP_LIB);
goto err;
}
type = s->s3.tmp.new_cipher->algorithm_mkey;
r[0] = r[1] = r[2] = r[3] = NULL;
#ifndef OPENSSL_NO_PSK
if (type & (SSL_kPSK | SSL_kRSAPSK)) {
} else
#endif
if (type & (SSL_kDHE | SSL_kDHEPSK)) {
CERT *cert = s->cert;
EVP_PKEY *pkdhp = NULL;
if (s->cert->dh_tmp_auto) {
pkdh = ssl_get_auto_dh(s);
if (pkdh == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
pkdhp = pkdh;
} else {
pkdhp = cert->dh_tmp;
}
#if !defined(OPENSSL_NO_DEPRECATED_3_0)
if ((pkdhp == NULL) && (s->cert->dh_tmp_cb != NULL)) {
pkdh = ssl_dh_to_pkey(s->cert->dh_tmp_cb(SSL_CONNECTION_GET_USER_SSL(s),
0, 1024));
if (pkdh == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
pkdhp = pkdh;
}
#endif
if (pkdhp == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_MISSING_TMP_DH_KEY);
goto err;
}
if (!ssl_security(s, SSL_SECOP_TMP_DH,
EVP_PKEY_get_security_bits(pkdhp), 0, pkdhp)) {
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_R_DH_KEY_TOO_SMALL);
goto err;
}
if (s->s3.tmp.pkey != NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
s->s3.tmp.pkey = ssl_generate_pkey(s, pkdhp);
if (s->s3.tmp.pkey == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
EVP_PKEY_free(pkdh);
pkdh = NULL;
freer = 1;
if (!EVP_PKEY_get_bn_param(s->s3.tmp.pkey, OSSL_PKEY_PARAM_FFC_P,
&r[0])
|| !EVP_PKEY_get_bn_param(s->s3.tmp.pkey, OSSL_PKEY_PARAM_FFC_G,
&r[1])
|| !EVP_PKEY_get_bn_param(s->s3.tmp.pkey,
OSSL_PKEY_PARAM_PUB_KEY, &r[2])) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
} else if (type & (SSL_kECDHE | SSL_kECDHEPSK)) {
if (s->s3.tmp.pkey != NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
curve_id = tls1_shared_group(s, -2);
if (curve_id == 0) {
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
SSL_R_UNSUPPORTED_ELLIPTIC_CURVE);
goto err;
}
s->session->kex_group = curve_id;
s->s3.tmp.pkey = ssl_generate_pkey_group(s, curve_id);
if (s->s3.tmp.pkey == NULL) {
goto err;
}
encodedlen = EVP_PKEY_get1_encoded_public_key(s->s3.tmp.pkey,
&encodedPoint);
if (encodedlen == 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_EC_LIB);
goto err;
}
r[0] = NULL;
r[1] = NULL;
r[2] = NULL;
r[3] = NULL;
} else
#ifndef OPENSSL_NO_SRP
if (type & SSL_kSRP) {
if ((s->srp_ctx.N == NULL) || (s->srp_ctx.g == NULL) || (s->srp_ctx.s == NULL) || (s->srp_ctx.B == NULL)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_MISSING_SRP_PARAM);
goto err;
}
r[0] = s->srp_ctx.N;
r[1] = s->srp_ctx.g;
r[2] = s->srp_ctx.s;
r[3] = s->srp_ctx.B;
} else
#endif
{
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE);
goto err;
}
if (((s->s3.tmp.new_cipher->algorithm_auth & (SSL_aNULL | SSL_aSRP)) != 0)
|| ((s->s3.tmp.new_cipher->algorithm_mkey & SSL_PSK)) != 0) {
lu = NULL;
} else if (lu == NULL) {
SSLfatal(s, SSL_AD_DECODE_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
#ifndef OPENSSL_NO_PSK
if (type & SSL_PSK) {
size_t len = (s->cert->psk_identity_hint == NULL)
? 0
: strlen(s->cert->psk_identity_hint);
if (len > PSK_MAX_IDENTITY_LEN
|| !WPACKET_sub_memcpy_u16(pkt, s->cert->psk_identity_hint,
len)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
}
#endif
for (i = 0; i < 4 && r[i] != NULL; i++) {
unsigned char *binval;
int res;
#ifndef OPENSSL_NO_SRP
if ((i == 2) && (type & SSL_kSRP)) {
res = WPACKET_start_sub_packet_u8(pkt);
} else
#endif
res = WPACKET_start_sub_packet_u16(pkt);
if (!res) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
if ((i == 2) && (type & (SSL_kDHE | SSL_kDHEPSK))) {
size_t len = BN_num_bytes(r[0]) - BN_num_bytes(r[2]);
if (len > 0) {
if (!WPACKET_allocate_bytes(pkt, len, &binval)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
memset(binval, 0, len);
}
}
if (!WPACKET_allocate_bytes(pkt, BN_num_bytes(r[i]), &binval)
|| !WPACKET_close(pkt)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
BN_bn2bin(r[i], binval);
}
if (type & (SSL_kECDHE | SSL_kECDHEPSK)) {
if (!WPACKET_put_bytes_u8(pkt, NAMED_CURVE_TYPE)
|| !WPACKET_put_bytes_u8(pkt, 0)
|| !WPACKET_put_bytes_u8(pkt, curve_id)
|| !WPACKET_sub_memcpy_u8(pkt, encodedPoint, encodedlen)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
OPENSSL_free(encodedPoint);
encodedPoint = NULL;
}
if (lu != NULL) {
EVP_PKEY *pkey = s->s3.tmp.cert->privatekey;
const EVP_MD *md;
unsigned char *sigbytes1, *sigbytes2, *tbs;
size_t siglen = 0, tbslen;
if (pkey == NULL || !tls1_lookup_md(sctx, lu, &md)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
if (!WPACKET_get_length(pkt, ¶mlen)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
if (SSL_USE_SIGALGS(s) && !WPACKET_put_bytes_u16(pkt, lu->sigalg)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
if (EVP_DigestSignInit_ex(md_ctx, &pctx,
md == NULL ? NULL : EVP_MD_get0_name(md),
sctx->libctx, sctx->propq, pkey,
NULL)
<= 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
if (lu->sig == EVP_PKEY_RSA_PSS) {
if (EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING) <= 0
|| EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx, RSA_PSS_SALTLEN_DIGEST) <= 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_EVP_LIB);
goto err;
}
}
tbslen = construct_key_exchange_tbs(s, &tbs,
s->init_buf->data + paramoffset,
paramlen);
if (tbslen == 0) {
goto err;
}
if (EVP_DigestSign(md_ctx, NULL, &siglen, tbs, tbslen) <= 0
|| !WPACKET_sub_reserve_bytes_u16(pkt, siglen, &sigbytes1)
|| EVP_DigestSign(md_ctx, sigbytes1, &siglen, tbs, tbslen) <= 0
|| !WPACKET_sub_allocate_bytes_u16(pkt, siglen, &sigbytes2)
|| sigbytes1 != sigbytes2) {
OPENSSL_free(tbs);
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
OPENSSL_free(tbs);
}
ret = CON_FUNC_SUCCESS;
err:
EVP_PKEY_free(pkdh);
OPENSSL_free(encodedPoint);
EVP_MD_CTX_free(md_ctx);
if (freer) {
BN_free(r[0]);
BN_free(r[1]);
BN_free(r[2]);
BN_free(r[3]);
}
return ret;
}
CON_FUNC_RETURN tls_construct_certificate_request(SSL_CONNECTION *s,
WPACKET *pkt)
{
if (SSL_CONNECTION_IS_TLS13(s)) {
if (s->post_handshake_auth == SSL_PHA_REQUEST_PENDING) {
OPENSSL_free(s->pha_context);
s->pha_context_len = 32;
if ((s->pha_context = OPENSSL_malloc(s->pha_context_len)) == NULL) {
s->pha_context_len = 0;
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return CON_FUNC_ERROR;
}
if (RAND_bytes_ex(SSL_CONNECTION_GET_CTX(s)->libctx,
s->pha_context, s->pha_context_len, 0)
<= 0
|| !WPACKET_sub_memcpy_u8(pkt, s->pha_context,
s->pha_context_len)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return CON_FUNC_ERROR;
}
if (!tls13_restore_handshake_digest_for_pha(s)) {
return CON_FUNC_ERROR;
}
} else {
if (!WPACKET_put_bytes_u8(pkt, 0)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return CON_FUNC_ERROR;
}
}
if (!tls_construct_extensions(s, pkt,
SSL_EXT_TLS1_3_CERTIFICATE_REQUEST, NULL,
0)) {
return CON_FUNC_ERROR;
}
goto done;
}
if (!WPACKET_start_sub_packet_u8(pkt)
|| !ssl3_get_req_cert_type(s, pkt) || !WPACKET_close(pkt)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return CON_FUNC_ERROR;
}
if (SSL_USE_SIGALGS(s)) {
const uint16_t *psigs;
size_t nl = tls12_get_psigalgs(s, 1, &psigs);
if (!WPACKET_start_sub_packet_u16(pkt)
|| !WPACKET_set_flags(pkt, WPACKET_FLAGS_NON_ZERO_LENGTH)
|| !tls12_copy_sigalgs(s, pkt, psigs, nl)
|| !WPACKET_close(pkt)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return CON_FUNC_ERROR;
}
}
if (!construct_ca_names(s, get_ca_names(s), pkt)) {
return CON_FUNC_ERROR;
}
done:
s->certreqs_sent++;
s->s3.tmp.cert_request = 1;
return CON_FUNC_SUCCESS;
}
static int tls_process_cke_psk_preamble(SSL_CONNECTION *s, PACKET *pkt)
{
#ifndef OPENSSL_NO_PSK
unsigned char psk[PSK_MAX_PSK_LEN];
size_t psklen;
PACKET psk_identity;
if (!PACKET_get_length_prefixed_2(pkt, &psk_identity)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH);
return 0;
}
if (PACKET_remaining(&psk_identity) > PSK_MAX_IDENTITY_LEN) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_DATA_LENGTH_TOO_LONG);
return 0;
}
if (s->psk_server_callback == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_PSK_NO_SERVER_CB);
return 0;
}
if (!PACKET_strndup(&psk_identity, &s->session->psk_identity)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
psklen = s->psk_server_callback(SSL_CONNECTION_GET_USER_SSL(s),
s->session->psk_identity,
psk, sizeof(psk));
if (psklen > PSK_MAX_PSK_LEN) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
} else if (psklen == 0) {
SSLfatal(s, SSL_AD_UNKNOWN_PSK_IDENTITY, SSL_R_PSK_IDENTITY_NOT_FOUND);
return 0;
}
OPENSSL_free(s->s3.tmp.psk);
s->s3.tmp.psk = OPENSSL_memdup(psk, psklen);
OPENSSL_cleanse(psk, psklen);
if (s->s3.tmp.psk == NULL) {
s->s3.tmp.psklen = 0;
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_CRYPTO_LIB);
return 0;
}
s->s3.tmp.psklen = psklen;
return 1;
#else
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
#endif
}
static int tls_process_cke_rsa(SSL_CONNECTION *s, PACKET *pkt)
{
size_t outlen;
PACKET enc_premaster;
EVP_PKEY *rsa = NULL;
unsigned char *rsa_decrypt = NULL;
int ret = 0;
EVP_PKEY_CTX *ctx = NULL;
OSSL_PARAM params[3], *p = params;
SSL_CTX *sctx = SSL_CONNECTION_GET_CTX(s);
rsa = s->cert->pkeys[SSL_PKEY_RSA].privatekey;
if (rsa == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_MISSING_RSA_CERTIFICATE);
return 0;
}
if (s->version == SSL3_VERSION || s->version == DTLS1_BAD_VER) {
enc_premaster = *pkt;
} else {
if (!PACKET_get_length_prefixed_2(pkt, &enc_premaster)
|| PACKET_remaining(pkt) != 0) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH);
return 0;
}
}
outlen = SSL_MAX_MASTER_KEY_LENGTH;
rsa_decrypt = OPENSSL_malloc(outlen);
if (rsa_decrypt == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_CRYPTO_LIB);
return 0;
}
ctx = EVP_PKEY_CTX_new_from_pkey(sctx->libctx, rsa, sctx->propq);
if (ctx == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_EVP_LIB);
goto err;
}
if (EVP_PKEY_decrypt_init(ctx) <= 0
|| EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_WITH_TLS_PADDING) <= 0) {
SSLfatal(s, SSL_AD_DECRYPT_ERROR, SSL_R_DECRYPTION_FAILED);
goto err;
}
*p++ = OSSL_PARAM_construct_uint(OSSL_ASYM_CIPHER_PARAM_TLS_CLIENT_VERSION,
(unsigned int *)&s->client_version);
if ((s->options & SSL_OP_TLS_ROLLBACK_BUG) != 0)
*p++ = OSSL_PARAM_construct_uint(
OSSL_ASYM_CIPHER_PARAM_TLS_NEGOTIATED_VERSION,
(unsigned int *)&s->version);
*p++ = OSSL_PARAM_construct_end();
if (!EVP_PKEY_CTX_set_params(ctx, params)
|| EVP_PKEY_decrypt(ctx, rsa_decrypt, &outlen,
PACKET_data(&enc_premaster),
PACKET_remaining(&enc_premaster))
<= 0) {
SSLfatal(s, SSL_AD_DECRYPT_ERROR, SSL_R_DECRYPTION_FAILED);
goto err;
}
if (outlen != SSL_MAX_MASTER_KEY_LENGTH) {
OPENSSL_cleanse(rsa_decrypt, SSL_MAX_MASTER_KEY_LENGTH);
SSLfatal(s, SSL_AD_DECRYPT_ERROR, SSL_R_DECRYPTION_FAILED);
goto err;
}
if (!ssl_generate_master_secret(s, rsa_decrypt, outlen, 0)) {
goto err;
}
ret = 1;
err:
OPENSSL_free(rsa_decrypt);
EVP_PKEY_CTX_free(ctx);
return ret;
}
static int tls_process_cke_dhe(SSL_CONNECTION *s, PACKET *pkt)
{
EVP_PKEY *skey = NULL;
unsigned int i;
const unsigned char *data;
EVP_PKEY *ckey = NULL;
int ret = 0;
if (!PACKET_get_net_2(pkt, &i) || PACKET_remaining(pkt) != i) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_DH_PUBLIC_VALUE_LENGTH_IS_WRONG);
goto err;
}
skey = s->s3.tmp.pkey;
if (skey == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_MISSING_TMP_DH_KEY);
goto err;
}
if (PACKET_remaining(pkt) == 0L) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_MISSING_TMP_DH_KEY);
goto err;
}
if (!PACKET_get_bytes(pkt, &data, i)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
ckey = EVP_PKEY_new();
if (ckey == NULL || EVP_PKEY_copy_parameters(ckey, skey) == 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_COPY_PARAMETERS_FAILED);
goto err;
}
if (EVP_PKEY_set1_encoded_public_key(ckey, data, i) <= 0) {
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_BAD_KEY_SHARE);
goto err;
}
if (ssl_derive(s, skey, ckey, 1) == 0) {
goto err;
}
ret = 1;
EVP_PKEY_free(s->s3.tmp.pkey);
s->s3.tmp.pkey = NULL;
err:
EVP_PKEY_free(ckey);
return ret;
}
static int tls_process_cke_ecdhe(SSL_CONNECTION *s, PACKET *pkt)
{
EVP_PKEY *skey = s->s3.tmp.pkey;
EVP_PKEY *ckey = NULL;
int ret = 0;
if (PACKET_remaining(pkt) == 0L) {
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_R_MISSING_TMP_ECDH_KEY);
goto err;
} else {
unsigned int i;
const unsigned char *data;
if (!PACKET_get_1(pkt, &i) || !PACKET_get_bytes(pkt, &data, i)
|| PACKET_remaining(pkt) != 0) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH);
goto err;
}
if (skey == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_MISSING_TMP_ECDH_KEY);
goto err;
}
ckey = EVP_PKEY_new();
if (ckey == NULL || EVP_PKEY_copy_parameters(ckey, skey) <= 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_COPY_PARAMETERS_FAILED);
goto err;
}
if (EVP_PKEY_set1_encoded_public_key(ckey, data, i) <= 0) {
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_BAD_KEY_SHARE);
goto err;
}
}
if (ssl_derive(s, skey, ckey, 1) == 0) {
goto err;
}
ret = 1;
EVP_PKEY_free(s->s3.tmp.pkey);
s->s3.tmp.pkey = NULL;
err:
EVP_PKEY_free(ckey);
return ret;
}
static int tls_process_cke_srp(SSL_CONNECTION *s, PACKET *pkt)
{
#ifndef OPENSSL_NO_SRP
unsigned int i;
const unsigned char *data;
if (!PACKET_get_net_2(pkt, &i)
|| !PACKET_get_bytes(pkt, &data, i)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_SRP_A_LENGTH);
return 0;
}
if ((s->srp_ctx.A = BN_bin2bn(data, i, NULL)) == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_BN_LIB);
return 0;
}
if (BN_ucmp(s->srp_ctx.A, s->srp_ctx.N) >= 0 || BN_is_zero(s->srp_ctx.A)) {
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_BAD_SRP_PARAMETERS);
return 0;
}
OPENSSL_free(s->session->srp_username);
s->session->srp_username = OPENSSL_strdup(s->srp_ctx.login);
if (s->session->srp_username == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_CRYPTO_LIB);
return 0;
}
if (!srp_generate_server_master_secret(s)) {
return 0;
}
return 1;
#else
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
#endif
}
static int tls_process_cke_gost(SSL_CONNECTION *s, PACKET *pkt)
{
#ifndef OPENSSL_NO_GOST
EVP_PKEY_CTX *pkey_ctx;
EVP_PKEY *client_pub_pkey = NULL, *pk = NULL;
unsigned char premaster_secret[32];
const unsigned char *start;
size_t outlen = sizeof(premaster_secret), inlen;
unsigned long alg_a;
GOST_KX_MESSAGE *pKX = NULL;
const unsigned char *ptr;
int ret = 0;
SSL_CTX *sctx = SSL_CONNECTION_GET_CTX(s);
alg_a = s->s3.tmp.new_cipher->algorithm_auth;
if (alg_a & SSL_aGOST12) {
pk = s->cert->pkeys[SSL_PKEY_GOST12_512].privatekey;
if (pk == NULL) {
pk = s->cert->pkeys[SSL_PKEY_GOST12_256].privatekey;
}
if (pk == NULL) {
pk = s->cert->pkeys[SSL_PKEY_GOST01].privatekey;
}
} else if (alg_a & SSL_aGOST01) {
pk = s->cert->pkeys[SSL_PKEY_GOST01].privatekey;
}
pkey_ctx = EVP_PKEY_CTX_new_from_pkey(sctx->libctx, pk, sctx->propq);
if (pkey_ctx == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_EVP_LIB);
return 0;
}
if (EVP_PKEY_decrypt_init(pkey_ctx) <= 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
client_pub_pkey = tls_get_peer_pkey(s);
if (client_pub_pkey) {
if (EVP_PKEY_derive_set_peer(pkey_ctx, client_pub_pkey) <= 0)
ERR_clear_error();
}
ptr = PACKET_data(pkt);
pKX = d2i_GOST_KX_MESSAGE(NULL, &ptr, PACKET_remaining(pkt));
if (pKX == NULL
|| pKX->kxBlob == NULL
|| ASN1_TYPE_get(pKX->kxBlob) != V_ASN1_SEQUENCE) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_DECRYPTION_FAILED);
goto err;
}
if (!PACKET_forward(pkt, ptr - PACKET_data(pkt))) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_DECRYPTION_FAILED);
goto err;
}
if (PACKET_remaining(pkt) != 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_DECRYPTION_FAILED);
goto err;
}
inlen = pKX->kxBlob->value.sequence->length;
start = pKX->kxBlob->value.sequence->data;
if (EVP_PKEY_decrypt(pkey_ctx, premaster_secret, &outlen, start,
inlen)
<= 0) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_DECRYPTION_FAILED);
goto err;
}
if (!ssl_generate_master_secret(s, premaster_secret, outlen, 0)) {
goto err;
}
if (EVP_PKEY_CTX_ctrl(pkey_ctx, -1, -1, EVP_PKEY_CTRL_PEER_KEY, 2,
NULL)
> 0)
s->statem.no_cert_verify = 1;
ret = 1;
err:
EVP_PKEY_CTX_free(pkey_ctx);
GOST_KX_MESSAGE_free(pKX);
return ret;
#else
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
#endif
}
static int tls_process_cke_gost18(SSL_CONNECTION *s, PACKET *pkt)
{
#ifndef OPENSSL_NO_GOST
unsigned char rnd_dgst[32];
EVP_PKEY_CTX *pkey_ctx = NULL;
EVP_PKEY *pk = NULL;
unsigned char premaster_secret[32];
const unsigned char *start = NULL;
size_t outlen = sizeof(premaster_secret), inlen = 0;
int ret = 0;
int cipher_nid = ossl_gost18_cke_cipher_nid(s);
SSL_CTX *sctx = SSL_CONNECTION_GET_CTX(s);
if (cipher_nid == NID_undef) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
if (ossl_gost_ukm(s, rnd_dgst) <= 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
pk = s->cert->pkeys[SSL_PKEY_GOST12_512].privatekey != NULL ? s->cert->pkeys[SSL_PKEY_GOST12_512].privatekey : s->cert->pkeys[SSL_PKEY_GOST12_256].privatekey;
if (pk == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_BAD_HANDSHAKE_STATE);
goto err;
}
pkey_ctx = EVP_PKEY_CTX_new_from_pkey(sctx->libctx, pk, sctx->propq);
if (pkey_ctx == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_EVP_LIB);
goto err;
}
if (EVP_PKEY_decrypt_init(pkey_ctx) <= 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
if (EVP_PKEY_CTX_ctrl(pkey_ctx, -1, EVP_PKEY_OP_DECRYPT,
EVP_PKEY_CTRL_SET_IV, 32, rnd_dgst)
<= 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_LIBRARY_BUG);
goto err;
}
if (EVP_PKEY_CTX_ctrl(pkey_ctx, -1, EVP_PKEY_OP_DECRYPT,
EVP_PKEY_CTRL_CIPHER, cipher_nid, NULL)
<= 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_LIBRARY_BUG);
goto err;
}
inlen = PACKET_remaining(pkt);
start = PACKET_data(pkt);
if (EVP_PKEY_decrypt(pkey_ctx, premaster_secret, &outlen, start, inlen) <= 0) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_DECRYPTION_FAILED);
goto err;
}
if (!ssl_generate_master_secret(s, premaster_secret, outlen, 0)) {
goto err;
}
ret = 1;
err:
EVP_PKEY_CTX_free(pkey_ctx);
return ret;
#else
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
#endif
}
MSG_PROCESS_RETURN tls_process_client_key_exchange(SSL_CONNECTION *s,
PACKET *pkt)
{
unsigned long alg_k;
alg_k = s->s3.tmp.new_cipher->algorithm_mkey;
if ((alg_k & SSL_PSK) && !tls_process_cke_psk_preamble(s, pkt)) {
goto err;
}
if (alg_k & SSL_kPSK) {
if (PACKET_remaining(pkt) != 0) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH);
goto err;
}
if (!ssl_generate_master_secret(s, NULL, 0, 0)) {
goto err;
}
} else if (alg_k & (SSL_kRSA | SSL_kRSAPSK)) {
if (!tls_process_cke_rsa(s, pkt)) {
goto err;
}
} else if (alg_k & (SSL_kDHE | SSL_kDHEPSK)) {
if (!tls_process_cke_dhe(s, pkt)) {
goto err;
}
} else if (alg_k & (SSL_kECDHE | SSL_kECDHEPSK)) {
if (!tls_process_cke_ecdhe(s, pkt)) {
goto err;
}
} else if (alg_k & SSL_kSRP) {
if (!tls_process_cke_srp(s, pkt)) {
goto err;
}
} else if (alg_k & SSL_kGOST) {
if (!tls_process_cke_gost(s, pkt)) {
goto err;
}
} else if (alg_k & SSL_kGOST18) {
if (!tls_process_cke_gost18(s, pkt)) {
goto err;
}
} else {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_UNKNOWN_CIPHER_TYPE);
goto err;
}
return MSG_PROCESS_CONTINUE_PROCESSING;
err:
#ifndef OPENSSL_NO_PSK
OPENSSL_clear_free(s->s3.tmp.psk, s->s3.tmp.psklen);
s->s3.tmp.psk = NULL;
s->s3.tmp.psklen = 0;
#endif
return MSG_PROCESS_ERROR;
}
WORK_STATE tls_post_process_client_key_exchange(SSL_CONNECTION *s,
WORK_STATE wst)
{
#ifndef OPENSSL_NO_SCTP
if (wst == WORK_MORE_A) {
if (SSL_CONNECTION_IS_DTLS(s)) {
unsigned char sctpauthkey[64];
char labelbuffer[sizeof(DTLS1_SCTP_AUTH_LABEL)];
size_t labellen;
memcpy(labelbuffer, DTLS1_SCTP_AUTH_LABEL,
sizeof(DTLS1_SCTP_AUTH_LABEL));
labellen = sizeof(labelbuffer) - 1;
if (s->mode & SSL_MODE_DTLS_SCTP_LABEL_LENGTH_BUG)
labellen += 1;
if (SSL_export_keying_material(SSL_CONNECTION_GET_SSL(s),
sctpauthkey,
sizeof(sctpauthkey), labelbuffer,
labellen, NULL, 0,
0)
<= 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return WORK_ERROR;
}
BIO_ctrl(s->wbio, BIO_CTRL_DGRAM_SCTP_ADD_AUTH_KEY,
sizeof(sctpauthkey), sctpauthkey);
}
}
#endif
if (s->statem.no_cert_verify || !received_client_cert(s)) {
if (!ssl3_digest_cached_records(s, 0)) {
return WORK_ERROR;
}
return WORK_FINISHED_CONTINUE;
} else {
if (!s->s3.handshake_buffer) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return WORK_ERROR;
}
if (!ssl3_digest_cached_records(s, 1)) {
return WORK_ERROR;
}
}
return WORK_FINISHED_CONTINUE;
}
MSG_PROCESS_RETURN tls_process_client_rpk(SSL_CONNECTION *sc, PACKET *pkt)
{
MSG_PROCESS_RETURN ret = MSG_PROCESS_ERROR;
SSL_SESSION *new_sess = NULL;
EVP_PKEY *peer_rpk = NULL;
if (!tls_process_rpk(sc, pkt, &peer_rpk)) {
goto err;
}
if (peer_rpk == NULL) {
if ((sc->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT)
&& (sc->verify_mode & SSL_VERIFY_PEER)) {
SSLfatal(sc, SSL_AD_CERTIFICATE_REQUIRED,
SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE);
goto err;
}
} else {
if (ssl_verify_rpk(sc, peer_rpk) <= 0) {
SSLfatal(sc, ssl_x509err2alert(sc->verify_result),
SSL_R_CERTIFICATE_VERIFY_FAILED);
goto err;
}
}
if (sc->post_handshake_auth == SSL_PHA_REQUESTED) {
if ((new_sess = ssl_session_dup(sc->session, 0)) == NULL) {
SSLfatal(sc, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
goto err;
}
SSL_SESSION_free(sc->session);
sc->session = new_sess;
}
X509_free(sc->session->peer);
sc->session->peer = NULL;
sk_X509_pop_free(sc->session->peer_chain, X509_free);
sc->session->peer_chain = NULL;
EVP_PKEY_free(sc->session->peer_rpk);
sc->session->peer_rpk = peer_rpk;
peer_rpk = NULL;
sc->session->verify_result = sc->verify_result;
if (SSL_CONNECTION_IS_TLS13(sc)) {
if (!ssl3_digest_cached_records(sc, 1)) {
goto err;
}
if (!ssl_handshake_hash(sc, sc->cert_verify_hash,
sizeof(sc->cert_verify_hash),
&sc->cert_verify_hash_len)) {
;
goto err;
}
sc->sent_tickets = 0;
}
ret = MSG_PROCESS_CONTINUE_READING;
err:
EVP_PKEY_free(peer_rpk);
return ret;
}
MSG_PROCESS_RETURN tls_process_client_certificate(SSL_CONNECTION *s,
PACKET *pkt)
{
int i;
MSG_PROCESS_RETURN ret = MSG_PROCESS_ERROR;
X509 *x = NULL;
unsigned long l;
const unsigned char *certstart, *certbytes;
STACK_OF(X509) *sk = NULL;
PACKET spkt, context;
size_t chainidx;
SSL_SESSION *new_sess = NULL;
SSL_CTX *sctx = SSL_CONNECTION_GET_CTX(s);
if (s->rlayer.rrlmethod->set_plain_alerts != NULL)
s->rlayer.rrlmethod->set_plain_alerts(s->rlayer.rrl, 0);
if (s->ext.client_cert_type == TLSEXT_cert_type_rpk)
return tls_process_client_rpk(s, pkt);
if (s->ext.client_cert_type != TLSEXT_cert_type_x509) {
SSLfatal(s, SSL_AD_UNSUPPORTED_CERTIFICATE,
SSL_R_UNKNOWN_CERTIFICATE_TYPE);
goto err;
}
if ((sk = sk_X509_new_null()) == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_CRYPTO_LIB);
goto err;
}
if (SSL_CONNECTION_IS_TLS13(s)
&& (!PACKET_get_length_prefixed_1(pkt, &context)
|| (s->pha_context == NULL && PACKET_remaining(&context) != 0)
|| (s->pha_context != NULL
&& !PACKET_equal(&context, s->pha_context,
s->pha_context_len)))) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_INVALID_CONTEXT);
goto err;
}
if (!PACKET_get_length_prefixed_3(pkt, &spkt)
|| PACKET_remaining(pkt) != 0) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH);
goto err;
}
for (chainidx = 0; PACKET_remaining(&spkt) > 0; chainidx++) {
if (!PACKET_get_net_3(&spkt, &l)
|| !PACKET_get_bytes(&spkt, &certbytes, l)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_CERT_LENGTH_MISMATCH);
goto err;
}
certstart = certbytes;
x = X509_new_ex(sctx->libctx, sctx->propq);
if (x == NULL) {
SSLfatal(s, SSL_AD_DECODE_ERROR, ERR_R_X509_LIB);
goto err;
}
if (d2i_X509(&x, (const unsigned char **)&certbytes, l) == NULL) {
SSLfatal(s, SSL_AD_DECODE_ERROR, ERR_R_ASN1_LIB);
goto err;
}
if (certbytes != (certstart + l)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_CERT_LENGTH_MISMATCH);
goto err;
}
if (SSL_CONNECTION_IS_TLS13(s)) {
RAW_EXTENSION *rawexts = NULL;
PACKET extensions;
if (!PACKET_get_length_prefixed_2(&spkt, &extensions)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_LENGTH);
goto err;
}
if (!tls_collect_extensions(s, &extensions,
SSL_EXT_TLS1_3_CERTIFICATE, &rawexts,
NULL, chainidx == 0)
|| !tls_parse_all_extensions(s, SSL_EXT_TLS1_3_CERTIFICATE,
rawexts, x, chainidx,
PACKET_remaining(&spkt) == 0)) {
OPENSSL_free(rawexts);
goto err;
}
OPENSSL_free(rawexts);
}
if (!sk_X509_push(sk, x)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_CRYPTO_LIB);
goto err;
}
x = NULL;
}
if (sk_X509_num(sk) <= 0) {
if (s->version == SSL3_VERSION) {
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
SSL_R_NO_CERTIFICATES_RETURNED);
goto err;
}
else if ((s->verify_mode & SSL_VERIFY_PEER) && (s->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT)) {
SSLfatal(s, SSL_AD_CERTIFICATE_REQUIRED,
SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE);
goto err;
}
if (s->s3.handshake_buffer && !ssl3_digest_cached_records(s, 0)) {
goto err;
}
} else {
EVP_PKEY *pkey;
i = ssl_verify_cert_chain(s, sk);
if (i <= 0) {
SSLfatal(s, ssl_x509err2alert(s->verify_result),
SSL_R_CERTIFICATE_VERIFY_FAILED);
goto err;
}
pkey = X509_get0_pubkey(sk_X509_value(sk, 0));
if (pkey == NULL) {
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
SSL_R_UNKNOWN_CERTIFICATE_TYPE);
goto err;
}
}
if (s->post_handshake_auth == SSL_PHA_REQUESTED) {
if ((new_sess = ssl_session_dup(s->session, 0)) == 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_SSL_LIB);
goto err;
}
SSL_SESSION_free(s->session);
s->session = new_sess;
}
X509_free(s->session->peer);
s->session->peer = sk_X509_shift(sk);
s->session->verify_result = s->verify_result;
OSSL_STACK_OF_X509_free(s->session->peer_chain);
s->session->peer_chain = sk;
sk = NULL;
EVP_PKEY_free(s->session->peer_rpk);
s->session->peer_rpk = NULL;
if (SSL_CONNECTION_IS_TLS13(s) && !ssl3_digest_cached_records(s, 1)) {
goto err;
}
if (SSL_CONNECTION_IS_TLS13(s)) {
if (!ssl_handshake_hash(s, s->cert_verify_hash,
sizeof(s->cert_verify_hash),
&s->cert_verify_hash_len)) {
goto err;
}
s->sent_tickets = 0;
}
ret = MSG_PROCESS_CONTINUE_READING;
err:
X509_free(x);
OSSL_STACK_OF_X509_free(sk);
return ret;
}
#ifndef OPENSSL_NO_COMP_ALG
MSG_PROCESS_RETURN tls_process_client_compressed_certificate(SSL_CONNECTION *sc, PACKET *pkt)
{
MSG_PROCESS_RETURN ret = MSG_PROCESS_ERROR;
PACKET tmppkt;
BUF_MEM *buf = BUF_MEM_new();
if (tls13_process_compressed_certificate(sc, pkt, &tmppkt, buf) != MSG_PROCESS_ERROR)
ret = tls_process_client_certificate(sc, &tmppkt);
BUF_MEM_free(buf);
return ret;
}
#endif
CON_FUNC_RETURN tls_construct_server_certificate(SSL_CONNECTION *s, WPACKET *pkt)
{
CERT_PKEY *cpk = s->s3.tmp.cert;
if (cpk == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return CON_FUNC_ERROR;
}
if (SSL_CONNECTION_IS_TLS13(s) && !WPACKET_put_bytes_u8(pkt, 0)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return CON_FUNC_ERROR;
}
switch (s->ext.server_cert_type) {
case TLSEXT_cert_type_rpk:
if (!tls_output_rpk(s, pkt, cpk)) {
return 0;
}
break;
case TLSEXT_cert_type_x509:
if (!ssl3_output_cert_chain(s, pkt, cpk, 0)) {
return 0;
}
break;
default:
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
return CON_FUNC_SUCCESS;
}
#ifndef OPENSSL_NO_COMP_ALG
CON_FUNC_RETURN tls_construct_server_compressed_certificate(SSL_CONNECTION *sc, WPACKET *pkt)
{
int alg = get_compressed_certificate_alg(sc);
OSSL_COMP_CERT *cc = sc->s3.tmp.cert->comp_cert[alg];
if (!ossl_assert(cc != NULL)) {
SSLfatal(sc, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
if (!WPACKET_put_bytes_u16(pkt, alg)
|| !WPACKET_put_bytes_u24(pkt, cc->orig_len)
|| !WPACKET_start_sub_packet_u24(pkt)
|| !WPACKET_memcpy(pkt, cc->data, cc->len)
|| !WPACKET_close(pkt))
return 0;
sc->s3.tmp.cert->cert_comp_used++;
return 1;
}
#endif
static int create_ticket_prequel(SSL_CONNECTION *s, WPACKET *pkt,
uint32_t age_add, unsigned char *tick_nonce)
{
uint32_t timeout = (uint32_t)ossl_time2seconds(s->session->timeout);
#define ONE_WEEK_SEC (7 * 24 * 60 * 60)
if (SSL_CONNECTION_IS_TLS13(s)) {
if (ossl_time_compare(s->session->timeout,
ossl_seconds2time(ONE_WEEK_SEC))
> 0)
timeout = ONE_WEEK_SEC;
} else if (s->hit)
timeout = 0;
if (!WPACKET_put_bytes_u32(pkt, timeout)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
if (SSL_CONNECTION_IS_TLS13(s)) {
if (!WPACKET_put_bytes_u32(pkt, age_add)
|| !WPACKET_sub_memcpy_u8(pkt, tick_nonce, TICKET_NONCE_SIZE)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
}
if (!WPACKET_start_sub_packet_u16(pkt)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
return 1;
}
static CON_FUNC_RETURN construct_stateless_ticket(SSL_CONNECTION *s,
WPACKET *pkt,
uint32_t age_add,
unsigned char *tick_nonce)
{
unsigned char *senc = NULL;
EVP_CIPHER_CTX *ctx = NULL;
SSL_HMAC *hctx = NULL;
unsigned char *p, *encdata1, *encdata2, *macdata1, *macdata2;
const unsigned char *const_p;
int len, slen_full, slen, lenfinal;
SSL_SESSION *sess;
size_t hlen;
SSL_CTX *tctx = s->session_ctx;
unsigned char iv[EVP_MAX_IV_LENGTH];
unsigned char key_name[TLSEXT_KEYNAME_LENGTH];
int iv_len;
CON_FUNC_RETURN ok = CON_FUNC_ERROR;
size_t macoffset, macendoffset;
SSL *ssl = SSL_CONNECTION_GET_USER_SSL(s);
SSL_CTX *sctx = SSL_CONNECTION_GET_CTX(s);
slen_full = i2d_SSL_SESSION(s->session, NULL);
if (slen_full == 0 || slen_full > 0xFF00) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
senc = OPENSSL_malloc(slen_full);
if (senc == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_CRYPTO_LIB);
goto err;
}
ctx = EVP_CIPHER_CTX_new();
if (ctx == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_EVP_LIB);
goto err;
}
hctx = ssl_hmac_new(tctx);
if (hctx == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_SSL_LIB);
goto err;
}
p = senc;
if (!i2d_SSL_SESSION(s->session, &p)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
const_p = senc;
sess = d2i_SSL_SESSION_ex(NULL, &const_p, slen_full, sctx->libctx,
sctx->propq);
if (sess == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
slen = i2d_SSL_SESSION(sess, NULL);
if (slen == 0 || slen > slen_full) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
SSL_SESSION_free(sess);
goto err;
}
p = senc;
if (!i2d_SSL_SESSION(sess, &p)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
SSL_SESSION_free(sess);
goto err;
}
SSL_SESSION_free(sess);
#ifndef OPENSSL_NO_DEPRECATED_3_0
if (tctx->ext.ticket_key_evp_cb != NULL || tctx->ext.ticket_key_cb != NULL)
#else
if (tctx->ext.ticket_key_evp_cb != NULL)
#endif
{
int ret = 0;
if (tctx->ext.ticket_key_evp_cb != NULL)
ret = tctx->ext.ticket_key_evp_cb(ssl, key_name, iv, ctx,
ssl_hmac_get0_EVP_MAC_CTX(hctx),
1);
#ifndef OPENSSL_NO_DEPRECATED_3_0
else if (tctx->ext.ticket_key_cb != NULL)
ret = tctx->ext.ticket_key_cb(ssl, key_name, iv, ctx,
ssl_hmac_get0_HMAC_CTX(hctx), 1);
#endif
if (ret == 0) {
if (SSL_CONNECTION_IS_TLS13(s)) {
ok = CON_FUNC_DONT_SEND;
goto err;
}
if (!WPACKET_put_bytes_u32(pkt, 0)
|| !WPACKET_put_bytes_u16(pkt, 0)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
OPENSSL_free(senc);
EVP_CIPHER_CTX_free(ctx);
ssl_hmac_free(hctx);
return CON_FUNC_SUCCESS;
}
if (ret < 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_CALLBACK_FAILED);
goto err;
}
iv_len = EVP_CIPHER_CTX_get_iv_length(ctx);
if (iv_len < 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
} else {
EVP_CIPHER *cipher = EVP_CIPHER_fetch(sctx->libctx, "AES-256-CBC",
sctx->propq);
if (cipher == NULL) {
SSLfatal_alert(s, SSL_AD_INTERNAL_ERROR);
goto err;
}
iv_len = EVP_CIPHER_get_iv_length(cipher);
if (iv_len < 0
|| RAND_bytes_ex(sctx->libctx, iv, iv_len, 0) <= 0
|| !EVP_EncryptInit_ex(ctx, cipher, NULL,
tctx->ext.secure->tick_aes_key, iv)
|| !ssl_hmac_init(hctx, tctx->ext.secure->tick_hmac_key,
sizeof(tctx->ext.secure->tick_hmac_key),
"SHA256")) {
EVP_CIPHER_free(cipher);
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
EVP_CIPHER_free(cipher);
memcpy(key_name, tctx->ext.tick_key_name,
sizeof(tctx->ext.tick_key_name));
}
if (!create_ticket_prequel(s, pkt, age_add, tick_nonce)) {
goto err;
}
if (!WPACKET_get_total_written(pkt, &macoffset)
|| !WPACKET_memcpy(pkt, key_name, sizeof(key_name))
|| !WPACKET_memcpy(pkt, iv, iv_len)
|| !WPACKET_reserve_bytes(pkt, slen + EVP_MAX_BLOCK_LENGTH,
&encdata1)
|| !EVP_EncryptUpdate(ctx, encdata1, &len, senc, slen)
|| !WPACKET_allocate_bytes(pkt, len, &encdata2)
|| encdata1 != encdata2
|| !EVP_EncryptFinal(ctx, encdata1 + len, &lenfinal)
|| !WPACKET_allocate_bytes(pkt, lenfinal, &encdata2)
|| encdata1 + len != encdata2
|| len + lenfinal > slen + EVP_MAX_BLOCK_LENGTH
|| !WPACKET_get_total_written(pkt, &macendoffset)
|| !ssl_hmac_update(hctx,
(unsigned char *)s->init_buf->data + macoffset,
macendoffset - macoffset)
|| !WPACKET_reserve_bytes(pkt, EVP_MAX_MD_SIZE, &macdata1)
|| !ssl_hmac_final(hctx, macdata1, &hlen, EVP_MAX_MD_SIZE)
|| hlen > EVP_MAX_MD_SIZE
|| !WPACKET_allocate_bytes(pkt, hlen, &macdata2)
|| macdata1 != macdata2) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
if (!WPACKET_close(pkt)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
ok = CON_FUNC_SUCCESS;
err:
OPENSSL_free(senc);
EVP_CIPHER_CTX_free(ctx);
ssl_hmac_free(hctx);
return ok;
}
static int construct_stateful_ticket(SSL_CONNECTION *s, WPACKET *pkt,
uint32_t age_add,
unsigned char *tick_nonce)
{
if (!create_ticket_prequel(s, pkt, age_add, tick_nonce)) {
return 0;
}
if (!WPACKET_memcpy(pkt, s->session->session_id,
s->session->session_id_length)
|| !WPACKET_close(pkt)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
return 1;
}
static void tls_update_ticket_counts(SSL_CONNECTION *s)
{
s->sent_tickets++;
s->next_ticket_nonce++;
if (s->ext.extra_tickets_expected > 0)
s->ext.extra_tickets_expected--;
}
CON_FUNC_RETURN tls_construct_new_session_ticket(SSL_CONNECTION *s, WPACKET *pkt)
{
SSL_CTX *tctx = s->session_ctx;
unsigned char tick_nonce[TICKET_NONCE_SIZE];
union {
unsigned char age_add_c[sizeof(uint32_t)];
uint32_t age_add;
} age_add_u;
CON_FUNC_RETURN ret = CON_FUNC_ERROR;
age_add_u.age_add = 0;
if (SSL_CONNECTION_IS_TLS13(s)) {
size_t i, hashlen;
uint64_t nonce;
static const unsigned char nonce_label[] = { 0x72, 0x65, 0x73, 0x75, 0x6D,
0x70, 0x74, 0x69, 0x6F, 0x6E };
const EVP_MD *md = ssl_handshake_md(s);
int hashleni = EVP_MD_get_size(md);
if (!ossl_assert(hashleni > 0)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
hashlen = (size_t)hashleni;
if (s->sent_tickets != 0 || s->hit) {
SSL_SESSION *new_sess = ssl_session_dup(s->session, 0);
if (new_sess == NULL) {
goto err;
}
SSL_SESSION_free(s->session);
s->session = new_sess;
}
if (!ssl_generate_session_id(s, s->session)) {
goto err;
}
if (RAND_bytes_ex(SSL_CONNECTION_GET_CTX(s)->libctx,
age_add_u.age_add_c, sizeof(age_add_u), 0)
<= 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
s->session->ext.tick_age_add = age_add_u.age_add;
nonce = s->next_ticket_nonce;
for (i = TICKET_NONCE_SIZE; i > 0; i--) {
tick_nonce[i - 1] = (unsigned char)(nonce & 0xff);
nonce >>= 8;
}
if (!tls13_hkdf_expand(s, md, s->resumption_master_secret,
nonce_label,
sizeof(nonce_label),
tick_nonce,
TICKET_NONCE_SIZE,
s->session->master_key,
hashlen, 1)) {
goto err;
}
s->session->master_key_length = hashlen;
s->session->time = ossl_time_now();
ssl_session_calculate_timeout(s->session);
if (s->s3.alpn_selected != NULL) {
OPENSSL_free(s->session->ext.alpn_selected);
s->session->ext.alpn_selected = OPENSSL_memdup(s->s3.alpn_selected, s->s3.alpn_selected_len);
if (s->session->ext.alpn_selected == NULL) {
s->session->ext.alpn_selected_len = 0;
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_CRYPTO_LIB);
goto err;
}
s->session->ext.alpn_selected_len = s->s3.alpn_selected_len;
}
s->session->ext.max_early_data = s->max_early_data;
}
if (tctx->generate_ticket_cb != NULL && tctx->generate_ticket_cb(SSL_CONNECTION_GET_USER_SSL(s), tctx->ticket_cb_data) == 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
if (SSL_CONNECTION_IS_TLS13(s)
&& ((s->options & SSL_OP_NO_TICKET) != 0
|| (s->max_early_data > 0
&& (s->options & SSL_OP_NO_ANTI_REPLAY) == 0))) {
if (!construct_stateful_ticket(s, pkt, age_add_u.age_add, tick_nonce)) {
goto err;
}
} else {
CON_FUNC_RETURN tmpret;
tmpret = construct_stateless_ticket(s, pkt, age_add_u.age_add,
tick_nonce);
if (tmpret != CON_FUNC_SUCCESS) {
if (tmpret == CON_FUNC_DONT_SEND) {
ret = CON_FUNC_DONT_SEND;
tls_update_ticket_counts(s);
}
goto err;
}
}
if (SSL_CONNECTION_IS_TLS13(s)) {
if (!tls_construct_extensions(s, pkt,
SSL_EXT_TLS1_3_NEW_SESSION_TICKET,
NULL, 0)) {
goto err;
}
tls_update_ticket_counts(s);
ssl_update_cache(s, SSL_SESS_CACHE_SERVER);
}
ret = CON_FUNC_SUCCESS;
err:
return ret;
}
int tls_construct_cert_status_body(SSL_CONNECTION *s, WPACKET *pkt)
{
if (!WPACKET_put_bytes_u8(pkt, s->ext.status_type)
|| !WPACKET_sub_memcpy_u24(pkt, s->ext.ocsp.resp,
s->ext.ocsp.resp_len)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
return 1;
}
CON_FUNC_RETURN tls_construct_cert_status(SSL_CONNECTION *s, WPACKET *pkt)
{
if (!tls_construct_cert_status_body(s, pkt)) {
return CON_FUNC_ERROR;
}
return CON_FUNC_SUCCESS;
}
#ifndef OPENSSL_NO_NEXTPROTONEG
MSG_PROCESS_RETURN tls_process_next_proto(SSL_CONNECTION *s, PACKET *pkt)
{
PACKET next_proto, padding;
size_t next_proto_len;
if (!PACKET_get_length_prefixed_1(pkt, &next_proto)
|| !PACKET_get_length_prefixed_1(pkt, &padding)
|| PACKET_remaining(pkt) > 0) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH);
return MSG_PROCESS_ERROR;
}
if (!PACKET_memdup(&next_proto, &s->ext.npn, &next_proto_len)) {
s->ext.npn_len = 0;
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return MSG_PROCESS_ERROR;
}
s->ext.npn_len = (unsigned char)next_proto_len;
return MSG_PROCESS_CONTINUE_READING;
}
#endif
static CON_FUNC_RETURN tls_construct_encrypted_extensions(SSL_CONNECTION *s,
WPACKET *pkt)
{
if (!tls_construct_extensions(s, pkt, SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS,
NULL, 0)) {
return CON_FUNC_ERROR;
}
return CON_FUNC_SUCCESS;
}
MSG_PROCESS_RETURN tls_process_end_of_early_data(SSL_CONNECTION *s, PACKET *pkt)
{
if (PACKET_remaining(pkt) != 0) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH);
return MSG_PROCESS_ERROR;
}
if (s->early_data_state != SSL_EARLY_DATA_READING
&& s->early_data_state != SSL_EARLY_DATA_READ_RETRY) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return MSG_PROCESS_ERROR;
}
if (RECORD_LAYER_processed_read_pending(&s->rlayer)) {
SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_R_NOT_ON_RECORD_BOUNDARY);
return MSG_PROCESS_ERROR;
}
s->early_data_state = SSL_EARLY_DATA_FINISHED_READING;
if (!SSL_CONNECTION_GET_SSL(s)->method->ssl3_enc->change_cipher_state(s,
SSL3_CC_HANDSHAKE | SSL3_CHANGE_CIPHER_SERVER_READ)) {
return MSG_PROCESS_ERROR;
}
return MSG_PROCESS_CONTINUE_READING;
}