/*
- * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved.
* Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
* Copyright 2005 Nokia. All rights reserved.
*
static int ssl_cipher_list_to_bytes(SSL_CONNECTION *s, STACK_OF(SSL_CIPHER) *sk,
WPACKET *pkt);
+static ossl_inline int received_server_cert(SSL_CONNECTION *sc)
+{
+ return sc->session->peer_rpk != NULL || sc->session->peer != NULL;
+}
+
/*
* Is a CertificateRequest message allowed at the moment or not?
*
st->hand_state = TLS_ST_CR_CERT;
return 1;
}
+#ifndef OPENSSL_NO_COMP_ALG
+ if (mt == SSL3_MT_COMPRESSED_CERTIFICATE
+ && s->ext.compress_certificate_sent) {
+ st->hand_state = TLS_ST_CR_COMP_CERT;
+ return 1;
+ }
+#endif
}
break;
st->hand_state = TLS_ST_CR_CERT;
return 1;
}
+#ifndef OPENSSL_NO_COMP_ALG
+ if (mt == SSL3_MT_COMPRESSED_CERTIFICATE
+ && s->ext.compress_certificate_sent) {
+ st->hand_state = TLS_ST_CR_COMP_CERT;
+ return 1;
+ }
+#endif
break;
case TLS_ST_CR_CERT:
+ case TLS_ST_CR_COMP_CERT:
if (mt == SSL3_MT_CERTIFICATE_VERIFY) {
st->hand_state = TLS_ST_CR_CERT_VRFY;
return 1;
st->hand_state = TLS_ST_CR_SESSION_TICKET;
return 1;
}
- if (mt == SSL3_MT_KEY_UPDATE) {
+ if (mt == SSL3_MT_KEY_UPDATE && !SSL_IS_QUIC_HANDSHAKE(s)) {
st->hand_state = TLS_ST_CR_KEY_UPDATE;
return 1;
}
break;
case TLS_ST_CR_CERT:
+ case TLS_ST_CR_COMP_CERT:
/*
* The CertificateStatus message is optional even if
* |ext.status_expected| is set
return 0;
}
+static int do_compressed_cert(SSL_CONNECTION *sc)
+{
+ /* If we negotiated RPK, we won't try to compress it */
+ return sc->ext.client_cert_type == TLSEXT_cert_type_x509
+ && sc->ext.compress_certificate_from_peer[0] != TLSEXT_comp_cert_none;
+}
+
/*
* ossl_statem_client13_write_transition() works out what handshake state to
* move to next when the TLSv1.3 client is writing messages to be sent to the
case TLS_ST_CR_CERT_REQ:
if (s->post_handshake_auth == SSL_PHA_REQUESTED) {
- st->hand_state = TLS_ST_CW_CERT;
+ if (do_compressed_cert(s))
+ st->hand_state = TLS_ST_CW_COMP_CERT;
+ else
+ st->hand_state = TLS_ST_CW_CERT;
return WRITE_TRAN_CONTINUE;
}
/*
else if ((s->options & SSL_OP_ENABLE_MIDDLEBOX_COMPAT) != 0
&& s->hello_retry_request == SSL_HRR_NONE)
st->hand_state = TLS_ST_CW_CHANGE;
+ else if (s->s3.tmp.cert_req == 0)
+ st->hand_state = TLS_ST_CW_FINISHED;
+ else if (do_compressed_cert(s))
+ st->hand_state = TLS_ST_CW_COMP_CERT;
else
- st->hand_state = (s->s3.tmp.cert_req != 0) ? TLS_ST_CW_CERT
- : TLS_ST_CW_FINISHED;
+ st->hand_state = TLS_ST_CW_CERT;
+
+ s->ts_msg_read = ossl_time_now();
return WRITE_TRAN_CONTINUE;
case TLS_ST_PENDING_EARLY_DATA_END:
case TLS_ST_CW_END_OF_EARLY_DATA:
case TLS_ST_CW_CHANGE:
- st->hand_state = (s->s3.tmp.cert_req != 0) ? TLS_ST_CW_CERT
- : TLS_ST_CW_FINISHED;
+ if (s->s3.tmp.cert_req == 0)
+ st->hand_state = TLS_ST_CW_FINISHED;
+ else if (do_compressed_cert(s))
+ st->hand_state = TLS_ST_CW_COMP_CERT;
+ else
+ st->hand_state = TLS_ST_CW_CERT;
return WRITE_TRAN_CONTINUE;
+ case TLS_ST_CW_COMP_CERT:
case TLS_ST_CW_CERT:
/* If a non-empty Certificate we also send CertificateVerify */
st->hand_state = (s->s3.tmp.cert_req == 1) ? TLS_ST_CW_CERT_VRFY
* No transition at the end of writing because we don't know what
* we will be sent
*/
+ s->ts_msg_write = ossl_time_now();
return WRITE_TRAN_FINISHED;
case TLS_ST_CR_SRVR_HELLO:
return WRITE_TRAN_CONTINUE;
case TLS_ST_EARLY_DATA:
+ s->ts_msg_write = ossl_time_now();
return WRITE_TRAN_FINISHED;
case DTLS_ST_CR_HELLO_VERIFY_REQUEST:
return WRITE_TRAN_CONTINUE;
case TLS_ST_CR_SRVR_DONE:
+ s->ts_msg_read = ossl_time_now();
if (s->s3.tmp.cert_req)
st->hand_state = TLS_ST_CW_CERT;
else
/* SSLfatal() already called */
return WORK_ERROR;
}
+ } else if (s->ext.early_data == SSL_EARLY_DATA_REJECTED) {
+ /*
+ * This must be a second ClientHello after an HRR following an
+ * earlier rejected attempt to send early data. Since we were
+ * previously encrypting the early data we now need to reset the
+ * write record layer in order to write in plaintext again.
+ */
+ if (!ssl_set_new_record_layer(s,
+ TLS_ANY_VERSION,
+ OSSL_RECORD_DIRECTION_WRITE,
+ OSSL_RECORD_PROTECTION_LEVEL_NONE,
+ NULL, 0, NULL, 0, NULL, 0, NULL, 0,
+ NULL, 0, NID_undef, NULL, NULL,
+ NULL)) {
+ /* SSLfatal already called */
+ return WORK_ERROR;
+ }
}
break;
}
break;
- case TLS_ST_CW_END_OF_EARLY_DATA:
- /*
- * We set the enc_write_ctx back to NULL because we may end up writing
- * in cleartext again if we get a HelloRetryRequest from the server.
- */
- EVP_CIPHER_CTX_free(s->enc_write_ctx);
- s->enc_write_ctx = NULL;
- break;
-
case TLS_ST_CW_KEY_EXCH:
if (tls_client_key_exchange_post_work(s) == 0) {
/* SSLfatal() already called */
return WORK_ERROR;
}
- if (SSL_CONNECTION_IS_DTLS(s)) {
#ifndef OPENSSL_NO_SCTP
- if (s->hit) {
- /*
- * Change to new shared key of SCTP-Auth, will be ignored if
- * no SCTP used.
- */
- BIO_ctrl(SSL_get_wbio(ssl), BIO_CTRL_DGRAM_SCTP_NEXT_AUTH_KEY,
- 0, NULL);
- }
-#endif
-
- dtls1_reset_seq_numbers(s, SSL3_CC_WRITE);
+ if (SSL_CONNECTION_IS_DTLS(s) && s->hit) {
+ /*
+ * Change to new shared key of SCTP-Auth, will be ignored if
+ * no SCTP used.
+ */
+ BIO_ctrl(SSL_get_wbio(ssl), BIO_CTRL_DGRAM_SCTP_NEXT_AUTH_KEY,
+ 0, NULL);
}
+#endif
break;
case TLS_ST_CW_FINISHED:
*mt = SSL3_MT_CERTIFICATE;
break;
+#ifndef OPENSSL_NO_COMP_ALG
+ case TLS_ST_CW_COMP_CERT:
+ *confunc = tls_construct_client_compressed_certificate;
+ *mt = SSL3_MT_COMPRESSED_CERTIFICATE;
+ break;
+#endif
+
case TLS_ST_CW_KEY_EXCH:
*confunc = tls_construct_client_key_exchange;
*mt = SSL3_MT_CLIENT_KEY_EXCHANGE;
case DTLS_ST_CR_HELLO_VERIFY_REQUEST:
return HELLO_VERIFY_REQUEST_MAX_LENGTH;
+ case TLS_ST_CR_COMP_CERT:
case TLS_ST_CR_CERT:
return s->max_cert_list;
case TLS_ST_CR_CERT_VRFY:
- return SSL3_RT_MAX_PLAIN_LENGTH;
+ return CERTIFICATE_VERIFY_MAX_LENGTH;
case TLS_ST_CR_CERT_STATUS:
return SSL3_RT_MAX_PLAIN_LENGTH;
case TLS_ST_CR_CERT:
return tls_process_server_certificate(s, pkt);
+#ifndef OPENSSL_NO_COMP_ALG
+ case TLS_ST_CR_COMP_CERT:
+ return tls_process_server_compressed_certificate(s, pkt);
+#endif
+
case TLS_ST_CR_CERT_VRFY:
return tls_process_cert_verify(s, pkt);
return WORK_ERROR;
case TLS_ST_CR_CERT:
+ case TLS_ST_CR_COMP_CERT:
return tls_post_process_server_certificate(s, wst);
case TLS_ST_CR_CERT_VRFY:
}
}
-int tls_construct_client_hello(SSL_CONNECTION *s, WPACKET *pkt)
+CON_FUNC_RETURN tls_construct_client_hello(SSL_CONNECTION *s, WPACKET *pkt)
{
unsigned char *p;
size_t sess_id_len;
protverr = ssl_set_client_hello_version(s);
if (protverr != 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, protverr);
- return 0;
+ return CON_FUNC_ERROR;
}
if (sess == NULL
if (s->hello_retry_request == SSL_HRR_NONE
&& !ssl_get_new_session(s, 0)) {
/* SSLfatal() already called */
- return 0;
+ return CON_FUNC_ERROR;
}
}
/* else use the pre-loaded session */
if (i && ssl_fill_hello_random(s, 0, p, sizeof(s->s3.client_random),
DOWNGRADE_NONE) <= 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
- return 0;
+ return CON_FUNC_ERROR;
}
/*-
if (!WPACKET_put_bytes_u16(pkt, s->client_version)
|| !WPACKET_memcpy(pkt, s->s3.client_random, SSL3_RANDOM_SIZE)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
- return 0;
+ return CON_FUNC_ERROR;
}
/* Session ID */
&& RAND_bytes_ex(sctx->libctx, s->tmp_session_id,
sess_id_len, 0) <= 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
- return 0;
+ return CON_FUNC_ERROR;
}
} else {
sess_id_len = 0;
sess_id_len))
|| !WPACKET_close(pkt)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
- return 0;
+ return CON_FUNC_ERROR;
}
/* cookie stuff for DTLS */
|| !WPACKET_sub_memcpy_u8(pkt, s->d1->cookie,
s->d1->cookie_len)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
- return 0;
+ return CON_FUNC_ERROR;
}
}
/* Ciphers supported */
if (!WPACKET_start_sub_packet_u16(pkt)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
- return 0;
+ return CON_FUNC_ERROR;
}
if (!ssl_cipher_list_to_bytes(s, SSL_get_ciphers(SSL_CONNECTION_GET_SSL(s)),
pkt)) {
/* SSLfatal() already called */
- return 0;
+ return CON_FUNC_ERROR;
}
if (!WPACKET_close(pkt)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
- return 0;
+ return CON_FUNC_ERROR;
}
/* COMPRESSION */
if (!WPACKET_start_sub_packet_u8(pkt)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
- return 0;
+ return CON_FUNC_ERROR;
}
#ifndef OPENSSL_NO_COMP
if (ssl_allow_compression(s)
comp = sk_SSL_COMP_value(sctx->comp_methods, i);
if (!WPACKET_put_bytes_u8(pkt, comp->id)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
- return 0;
+ return CON_FUNC_ERROR;
}
}
}
/* Add the NULL method */
if (!WPACKET_put_bytes_u8(pkt, 0) || !WPACKET_close(pkt)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
- return 0;
+ return CON_FUNC_ERROR;
}
/* TLS extensions */
if (!tls_construct_extensions(s, pkt, SSL_EXT_CLIENT_HELLO, NULL, 0)) {
/* SSLfatal() already called */
- return 0;
+ return CON_FUNC_ERROR;
}
- return 1;
+ return CON_FUNC_SUCCESS;
}
MSG_PROCESS_RETURN dtls_process_hello_verify(SSL_CONNECTION *s, PACKET *pkt)
if (SSL_CONNECTION_IS_TLS13(s)) {
const EVP_MD *md = ssl_md(sctx, c->algorithm2);
+ if (!ossl_assert(s->session->cipher != NULL)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
/*
* In TLSv1.3 it is valid for the server to select a different
* ciphersuite as long as the hash is the same.
}
s->hello_retry_request = SSL_HRR_PENDING;
/* Tell the record layer that we know we're going to get TLSv1.3 */
- s->rrlmethod->set_protocol_version(s->rrl, s->version);
+ if (!ssl_set_record_protocol_version(s, s->version)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
hrr = 1;
if (!PACKET_forward(pkt, SSL3_RANDOM_SIZE)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_MISMATCH);
* In TLSv1.3 we have some post-processing to change cipher state, otherwise
* we're done with this message
*/
- if (SSL_CONNECTION_IS_TLS13(s)
- && (!ssl->method->ssl3_enc->setup_key_block(s)
+ if (SSL_CONNECTION_IS_TLS13(s)) {
+ if (!ssl->method->ssl3_enc->setup_key_block(s)
|| !ssl->method->ssl3_enc->change_cipher_state(s,
- SSL3_CC_HANDSHAKE | SSL3_CHANGE_CIPHER_CLIENT_READ))) {
- /* SSLfatal() already called */
- goto err;
+ SSL3_CC_HANDSHAKE | SSL3_CHANGE_CIPHER_CLIENT_READ)) {
+ /* SSLfatal() already called */
+ goto err;
+ }
+ /*
+ * If we're not doing early-data and we're not going to send a dummy CCS
+ * (i.e. no middlebox compat mode) then we can change the write keys
+ * immediately. Otherwise we have to defer this until after all possible
+ * early data is written. We could just always defer until the last
+ * moment except QUIC needs it done at the same time as the read keys
+ * are changed. Since QUIC doesn't do TLS early data or need middlebox
+ * compat this doesn't cause a problem.
+ */
+ if (s->early_data_state == SSL_EARLY_DATA_NONE
+ && (s->options & SSL_OP_ENABLE_MIDDLEBOX_COMPAT) == 0
+ && !ssl->method->ssl3_enc->change_cipher_state(s,
+ SSL3_CC_HANDSHAKE | SSL3_CHANGE_CIPHER_CLIENT_WRITE)) {
+ /* SSLfatal() already called */
+ goto err;
+ }
}
OPENSSL_free(extensions);
RAW_EXTENSION *extensions = NULL;
/*
- * If we were sending early_data then the enc_write_ctx is now invalid and
- * should not be used.
+ * If we were sending early_data then any alerts should not be sent using
+ * the old wrlmethod.
*/
- EVP_CIPHER_CTX_free(s->enc_write_ctx);
- s->enc_write_ctx = NULL;
+ if (s->early_data_state == SSL_EARLY_DATA_FINISHED_WRITING
+ && !ssl_set_new_record_layer(s,
+ TLS_ANY_VERSION,
+ OSSL_RECORD_DIRECTION_WRITE,
+ OSSL_RECORD_PROTECTION_LEVEL_NONE,
+ NULL, 0, NULL, 0, NULL, 0, NULL, 0,
+ NULL, 0, NID_undef, NULL, NULL, NULL)) {
+ /* SSLfatal already called */
+ goto err;
+ }
+ /* We are definitely going to be using TLSv1.3 */
+ s->rlayer.wrlmethod->set_protocol_version(s->rlayer.wrl, TLS1_3_VERSION);
if (!tls_collect_extensions(s, extpkt, SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST,
&extensions, NULL, 1)
return MSG_PROCESS_ERROR;
}
+MSG_PROCESS_RETURN tls_process_server_rpk(SSL_CONNECTION *sc, PACKET *pkt)
+{
+ EVP_PKEY *peer_rpk;
+
+ if (!tls_process_rpk(sc, pkt, &peer_rpk)) {
+ /* SSLfatal() already called */
+ return MSG_PROCESS_ERROR;
+ }
+
+ if (peer_rpk == NULL) {
+ SSLfatal(sc, SSL_AD_DECODE_ERROR, SSL_R_BAD_CERTIFICATE);
+ return MSG_PROCESS_ERROR;
+ }
+
+ EVP_PKEY_free(sc->session->peer_rpk);
+ sc->session->peer_rpk = peer_rpk;
+
+ return MSG_PROCESS_CONTINUE_PROCESSING;
+}
+
+static WORK_STATE tls_post_process_server_rpk(SSL_CONNECTION *sc,
+ WORK_STATE wst)
+{
+ size_t certidx;
+ const SSL_CERT_LOOKUP *clu;
+
+ if (sc->session->peer_rpk == NULL) {
+ SSLfatal(sc, SSL_AD_ILLEGAL_PARAMETER,
+ SSL_R_INVALID_RAW_PUBLIC_KEY);
+ return WORK_ERROR;
+ }
+
+ if (sc->rwstate == SSL_RETRY_VERIFY)
+ sc->rwstate = SSL_NOTHING;
+ if (ssl_verify_rpk(sc, sc->session->peer_rpk) > 0
+ && sc->rwstate == SSL_RETRY_VERIFY)
+ return WORK_MORE_A;
+
+ if ((clu = ssl_cert_lookup_by_pkey(sc->session->peer_rpk, &certidx,
+ SSL_CONNECTION_GET_CTX(sc))) == NULL) {
+ SSLfatal(sc, SSL_AD_ILLEGAL_PARAMETER, SSL_R_UNKNOWN_CERTIFICATE_TYPE);
+ return WORK_ERROR;
+ }
+
+ /*
+ * Check certificate type is consistent with ciphersuite. For TLS 1.3
+ * skip check since TLS 1.3 ciphersuites can be used with any certificate
+ * type.
+ */
+ if (!SSL_CONNECTION_IS_TLS13(sc)) {
+ if ((clu->amask & sc->s3.tmp.new_cipher->algorithm_auth) == 0) {
+ SSLfatal(sc, SSL_AD_ILLEGAL_PARAMETER, SSL_R_WRONG_RPK_TYPE);
+ return WORK_ERROR;
+ }
+ }
+
+ /* Ensure there is no peer/peer_chain */
+ X509_free(sc->session->peer);
+ sc->session->peer = NULL;
+ sk_X509_pop_free(sc->session->peer_chain, X509_free);
+ sc->session->peer_chain = NULL;
+ sc->session->verify_result = sc->verify_result;
+
+ /* Save the current hash state for when we receive the CertificateVerify */
+ if (SSL_CONNECTION_IS_TLS13(sc)
+ && !ssl_handshake_hash(sc, sc->cert_verify_hash,
+ sizeof(sc->cert_verify_hash),
+ &sc->cert_verify_hash_len)) {
+ /* SSLfatal() already called */
+ return WORK_ERROR;
+ }
+
+ return WORK_FINISHED_CONTINUE;
+}
+
/* prepare server cert verification by setting s->session->peer_chain from pkt */
MSG_PROCESS_RETURN tls_process_server_certificate(SSL_CONNECTION *s,
PACKET *pkt)
unsigned int context = 0;
SSL_CTX *sctx = SSL_CONNECTION_GET_CTX(s);
+ if (s->ext.server_cert_type == TLSEXT_cert_type_rpk)
+ return tls_process_server_rpk(s, pkt);
+ if (s->ext.server_cert_type != TLSEXT_cert_type_x509) {
+ SSLfatal(s, SSL_AD_UNSUPPORTED_CERTIFICATE,
+ SSL_R_UNKNOWN_CERTIFICATE_TYPE);
+ goto err;
+ }
+
if ((s->session->peer_chain = sk_X509_new_null()) == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_CRYPTO_LIB);
goto err;
}
certstart = certbytes;
x = X509_new_ex(sctx->libctx, sctx->propq);
if (x == NULL) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, ERR_R_MALLOC_FAILURE);
- ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, ERR_R_ASN1_LIB);
goto err;
}
if (d2i_X509(&x, (const unsigned char **)&certbytes,
}
if (!sk_X509_push(s->session->peer_chain, x)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_CRYPTO_LIB);
goto err;
}
x = NULL;
size_t certidx;
int i;
+ if (s->ext.server_cert_type == TLSEXT_cert_type_rpk)
+ return tls_post_process_server_rpk(s, wst);
+
if (s->rwstate == SSL_RETRY_VERIFY)
s->rwstate = SSL_NOTHING;
i = ssl_verify_cert_chain(s, s->session->peer_chain);
return WORK_ERROR;
}
- if ((clu = ssl_cert_lookup_by_pkey(pkey, &certidx)) == NULL) {
+ if ((clu = ssl_cert_lookup_by_pkey(pkey, &certidx,
+ SSL_CONNECTION_GET_CTX(s))) == NULL) {
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_UNKNOWN_CERTIFICATE_TYPE);
return WORK_ERROR;
}
X509_up_ref(x);
s->session->peer = x;
s->session->verify_result = s->verify_result;
+ /* Ensure there is no RPK */
+ EVP_PKEY_free(s->session->peer_rpk);
+ s->session->peer_rpk = NULL;
/* Save the current hash state for when we receive the CertificateVerify */
if (SSL_CONNECTION_IS_TLS13(s)
return WORK_FINISHED_CONTINUE;
}
+#ifndef OPENSSL_NO_COMP_ALG
+MSG_PROCESS_RETURN tls_process_server_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_server_certificate(sc, &tmppkt);
+
+ BUF_MEM_free(buf);
+ return ret;
+}
+#endif
+
static int tls_process_ske_psk_preamble(SSL_CONNECTION *s, PACKET *pkt)
{
#ifndef OPENSSL_NO_PSK
/* We must check if there is a certificate */
if (s->s3.tmp.new_cipher->algorithm_auth & (SSL_aRSA | SSL_aDSS))
- *pkey = X509_get0_pubkey(s->session->peer);
+ *pkey = tls_get_peer_pkey(s);
return 1;
#else
* public keys. We should have a less ad-hoc way of doing this
*/
if (s->s3.tmp.new_cipher->algorithm_auth & (SSL_aRSA | SSL_aDSS))
- *pkey = X509_get0_pubkey(s->session->peer);
+ *pkey = tls_get_peer_pkey(s);
/* else anonymous DH, so no certificate or pkey. */
ret = 1;
* and ECDSA.
*/
if (s->s3.tmp.new_cipher->algorithm_auth & SSL_aECDSA)
- *pkey = X509_get0_pubkey(s->session->peer);
+ *pkey = tls_get_peer_pkey(s);
else if (s->s3.tmp.new_cipher->algorithm_auth & SSL_aRSA)
- *pkey = X509_get0_pubkey(s->session->peer);
+ *pkey = tls_get_peer_pkey(s);
/* else anonymous ECDH, so no certificate or pkey. */
/* Cache the agreed upon group in the SSL_SESSION */
goto err;
}
} else if (!tls1_set_peer_legacy_sigalg(s, pkey)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_R_LEGACY_SIGALG_DISALLOWED_OR_UNSUPPORTED);
goto err;
}
md_ctx = EVP_MD_CTX_new();
if (md_ctx == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_EVP_LIB);
goto err;
}
MSG_PROCESS_RETURN tls_process_certificate_request(SSL_CONNECTION *s,
PACKET *pkt)
{
- size_t i;
-
/* Clear certificate validity flags */
- for (i = 0; i < SSL_PKEY_NUM; i++)
- s->s3.tmp.valid_flags[i] = 0;
+ if (s->s3.tmp.valid_flags != NULL)
+ memset(s->s3.tmp.valid_flags, 0, s->ssl_pkey_num * sizeof(uint32_t));
+ else
+ s->s3.tmp.valid_flags = OPENSSL_zalloc(s->ssl_pkey_num * sizeof(uint32_t));
+
+ /* Give up for good if allocation didn't work */
+ if (s->s3.tmp.valid_flags == NULL)
+ return 0;
if (SSL_CONNECTION_IS_TLS13(s)) {
PACKET reqctx, extensions;
return MSG_PROCESS_ERROR;
}
if (!tls1_process_sigalgs(s)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_SSL_LIB);
return MSG_PROCESS_ERROR;
}
}
* one
*/
if ((new_sess = ssl_session_dup(s->session, 0)) == 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_SSL_LIB);
goto err;
}
s->session = new_sess;
}
- s->session->time = time(NULL);
+ s->session->time = ossl_time_now();
ssl_session_calculate_timeout(s->session);
OPENSSL_free(s->session->ext.tick);
s->session->ext.tick = OPENSSL_malloc(ticklen);
if (s->session->ext.tick == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_CRYPTO_LIB);
goto err;
}
if (!PACKET_copy_bytes(pkt, s->session->ext.tick, ticklen)) {
s->ext.ocsp.resp = OPENSSL_malloc(resplen);
if (s->ext.ocsp.resp == NULL) {
s->ext.ocsp.resp_len = 0;
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_CRYPTO_LIB);
return 0;
}
s->ext.ocsp.resp_len = resplen;
tmppsk = OPENSSL_memdup(psk, psklen);
tmpidentity = OPENSSL_strdup(identity);
if (tmppsk == NULL || tmpidentity == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_CRYPTO_LIB);
goto err;
}
size_t pmslen = 0;
SSL_CTX *sctx = SSL_CONNECTION_GET_CTX(s);
- if (s->session->peer == NULL) {
+ if (!received_server_cert(s)) {
/*
* We should always have a server certificate with SSL_kRSA.
*/
return 0;
}
- pkey = X509_get0_pubkey(s->session->peer);
+ if ((pkey = tls_get_peer_pkey(s)) == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
if (!EVP_PKEY_is_a(pkey, "RSA")) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
pmslen = SSL_MAX_MASTER_KEY_LENGTH;
pms = OPENSSL_malloc(pmslen);
if (pms == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_CRYPTO_LIB);
return 0;
}
pms[0] = s->client_version >> 8;
pms[1] = s->client_version & 0xff;
if (RAND_bytes_ex(sctx->libctx, pms + 2, pmslen - 2, 0) <= 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_RAND_LIB);
goto err;
}
ckey = ssl_generate_pkey(s, skey);
if (ckey == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_SSL_LIB);
goto err;
}
#ifndef OPENSSL_NO_GOST
/* GOST key exchange message creation */
EVP_PKEY_CTX *pkey_ctx = NULL;
- X509 *peer_cert;
+ EVP_PKEY *pkey = NULL;
size_t msglen;
unsigned int md_len;
unsigned char shared_ukm[32], tmp[256];
/*
* Get server certificate PKEY and create ctx from it
*/
- peer_cert = s->session->peer;
- if (peer_cert == NULL) {
+ if ((pkey = tls_get_peer_pkey(s)) == NULL) {
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
SSL_R_NO_GOST_CERTIFICATE_SENT_BY_PEER);
return 0;
}
pkey_ctx = EVP_PKEY_CTX_new_from_pkey(sctx->libctx,
- X509_get0_pubkey(peer_cert),
+ pkey,
sctx->propq);
if (pkey_ctx == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_EVP_LIB);
return 0;
}
/*
pmslen = 32;
pms = OPENSSL_malloc(pmslen);
if (pms == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_CRYPTO_LIB);
goto err;
}
int ossl_gost_ukm(const SSL_CONNECTION *s, unsigned char *dgst_buf)
{
- EVP_MD_CTX * hash = NULL;
+ EVP_MD_CTX *hash = NULL;
unsigned int md_len;
SSL_CTX *sctx = SSL_CONNECTION_GET_CTX(s);
const EVP_MD *md = ssl_evp_md_fetch(sctx->libctx, NID_id_GostR3411_2012_256,
unsigned char rnd_dgst[32];
unsigned char *encdata = NULL;
EVP_PKEY_CTX *pkey_ctx = NULL;
- X509 *peer_cert;
+ EVP_PKEY *pkey;
unsigned char *pms = NULL;
size_t pmslen = 0;
size_t msglen;
pmslen = 32;
pms = OPENSSL_malloc(pmslen);
if (pms == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_CRYPTO_LIB);
goto err;
}
}
/* Get server certificate PKEY and create ctx from it */
- peer_cert = s->session->peer;
- if (peer_cert == NULL) {
+ if ((pkey = tls_get_peer_pkey(s)) == NULL) {
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
SSL_R_NO_GOST_CERTIFICATE_SENT_BY_PEER);
goto err;
}
pkey_ctx = EVP_PKEY_CTX_new_from_pkey(sctx->libctx,
- X509_get0_pubkey(peer_cert),
+ pkey,
sctx->propq);
if (pkey_ctx == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_EVP_LIB);
goto err;
}
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_MALLOC_FAILURE);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_CRYPTO_LIB);
return 0;
}
#endif
}
-int tls_construct_client_key_exchange(SSL_CONNECTION *s, WPACKET *pkt)
+CON_FUNC_RETURN tls_construct_client_key_exchange(SSL_CONNECTION *s,
+ WPACKET *pkt)
{
unsigned long alg_k;
goto err;
}
- return 1;
+ return CON_FUNC_SUCCESS;
err:
OPENSSL_clear_free(s->s3.tmp.pms, s->s3.tmp.pmslen);
s->s3.tmp.pms = NULL;
s->s3.tmp.psk = NULL;
s->s3.tmp.psklen = 0;
#endif
- return 0;
+ return CON_FUNC_ERROR;
}
int tls_client_key_exchange_post_work(SSL_CONNECTION *s)
#endif
if (pms == NULL && !(s->s3.tmp.new_cipher->algorithm_mkey & SSL_kPSK)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_PASSED_INVALID_ARGUMENT);
goto err;
}
if (!ssl_generate_master_secret(s, pms, pmslen, 1)) {
return WORK_FINISHED_CONTINUE;
} else {
s->s3.tmp.cert_req = 2;
+ s->ext.compress_certificate_from_peer[0] = TLSEXT_comp_cert_none;
if (!ssl3_digest_cached_records(s, 0)) {
/* SSLfatal() already called */
return WORK_ERROR;
}
}
+ 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;
+
if (s->post_handshake_auth == SSL_PHA_REQUESTED)
return WORK_FINISHED_STOP;
return WORK_FINISHED_CONTINUE;
return WORK_ERROR;
}
-int tls_construct_client_certificate(SSL_CONNECTION *s, WPACKET *pkt)
+CON_FUNC_RETURN tls_construct_client_certificate(SSL_CONNECTION *s,
+ WPACKET *pkt)
{
+ CERT_PKEY *cpk = NULL;
SSL *ssl = SSL_CONNECTION_GET_SSL(s);
if (SSL_CONNECTION_IS_TLS13(s)) {
/* no context available, add 0-length context */
if (!WPACKET_put_bytes_u8(pkt, 0)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
- return 0;
+ return CON_FUNC_ERROR;
}
} else if (!WPACKET_sub_memcpy_u8(pkt, s->pha_context, s->pha_context_len)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
- return 0;
+ return CON_FUNC_ERROR;
}
}
- if (!ssl3_output_cert_chain(s, pkt,
- (s->s3.tmp.cert_req == 2) ? NULL
- : s->cert->key)) {
- /* SSLfatal() already called */
- return 0;
+ if (s->s3.tmp.cert_req != 2)
+ cpk = s->cert->key;
+ switch (s->ext.client_cert_type) {
+ case TLSEXT_cert_type_rpk:
+ if (!tls_output_rpk(s, pkt, cpk)) {
+ /* SSLfatal() already called */
+ return CON_FUNC_ERROR;
+ }
+ break;
+ case TLSEXT_cert_type_x509:
+ if (!ssl3_output_cert_chain(s, pkt, cpk, 0)) {
+ /* SSLfatal() already called */
+ return CON_FUNC_ERROR;
+ }
+ break;
+ default:
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ return CON_FUNC_ERROR;
}
+ /*
+ * If we attempted to write early data or we're in middlebox compat mode
+ * then we deferred changing the handshake write keys to the last possible
+ * moment. We need to do it now.
+ */
if (SSL_CONNECTION_IS_TLS13(s)
&& SSL_IS_FIRST_HANDSHAKE(s)
+ && (s->early_data_state != SSL_EARLY_DATA_NONE
+ || (s->options & SSL_OP_ENABLE_MIDDLEBOX_COMPAT) != 0)
&& (!ssl->method->ssl3_enc->change_cipher_state(s,
SSL3_CC_HANDSHAKE | SSL3_CHANGE_CIPHER_CLIENT_WRITE))) {
/*
* state and thus ssl3_send_alert may crash.
*/
SSLfatal(s, SSL_AD_NO_ALERT, SSL_R_CANNOT_CHANGE_CIPHER);
- return 0;
+ return CON_FUNC_ERROR;
}
- return 1;
+ return CON_FUNC_SUCCESS;
+}
+
+#ifndef OPENSSL_NO_COMP_ALG
+CON_FUNC_RETURN tls_construct_client_compressed_certificate(SSL_CONNECTION *sc,
+ WPACKET *pkt)
+{
+ SSL *ssl = SSL_CONNECTION_GET_SSL(sc);
+ WPACKET tmppkt;
+ BUF_MEM *buf = NULL;
+ size_t length;
+ size_t max_length;
+ COMP_METHOD *method;
+ COMP_CTX *comp = NULL;
+ int comp_len;
+ int ret = 0;
+ int alg = sc->ext.compress_certificate_from_peer[0];
+
+ /* Note that sc->s3.tmp.cert_req == 2 is checked in write transition */
+
+ if ((buf = BUF_MEM_new()) == NULL || !WPACKET_init(&tmppkt, buf))
+ goto err;
+
+ /* Use the |tmppkt| for the to-be-compressed data */
+ if (sc->pha_context == NULL) {
+ /* no context available, add 0-length context */
+ if (!WPACKET_put_bytes_u8(&tmppkt, 0))
+ goto err;
+ } else if (!WPACKET_sub_memcpy_u8(&tmppkt, sc->pha_context, sc->pha_context_len))
+ goto err;
+
+ if (!ssl3_output_cert_chain(sc, &tmppkt, sc->cert->key, 0)) {
+ /* SSLfatal() already called */
+ goto out;
+ }
+
+ /* continue with the real |pkt| */
+ if (!WPACKET_put_bytes_u16(pkt, alg)
+ || !WPACKET_get_total_written(&tmppkt, &length)
+ || !WPACKET_put_bytes_u24(pkt, length))
+ goto err;
+
+ switch (alg) {
+ case TLSEXT_comp_cert_zlib:
+ method = COMP_zlib_oneshot();
+ break;
+ case TLSEXT_comp_cert_brotli:
+ method = COMP_brotli_oneshot();
+ break;
+ case TLSEXT_comp_cert_zstd:
+ method = COMP_zstd_oneshot();
+ break;
+ default:
+ goto err;
+ }
+ max_length = ossl_calculate_comp_expansion(alg, length);
+
+ if ((comp = COMP_CTX_new(method)) == NULL
+ || !WPACKET_start_sub_packet_u24(pkt)
+ || !WPACKET_reserve_bytes(pkt, max_length, NULL))
+ goto err;
+
+ comp_len = COMP_compress_block(comp, WPACKET_get_curr(pkt), max_length,
+ (unsigned char *)buf->data, length);
+ if (comp_len <= 0)
+ goto err;
+
+ if (!WPACKET_allocate_bytes(pkt, comp_len, NULL)
+ || !WPACKET_close(pkt))
+ goto err;
+
+ /*
+ * If we attempted to write early data or we're in middlebox compat mode
+ * then we deferred changing the handshake write keys to the last possible
+ * moment. We need to do it now.
+ */
+ if (SSL_IS_FIRST_HANDSHAKE(sc)
+ && (sc->early_data_state != SSL_EARLY_DATA_NONE
+ || (sc->options & SSL_OP_ENABLE_MIDDLEBOX_COMPAT) != 0)
+ && (!ssl->method->ssl3_enc->change_cipher_state(sc,
+ SSL3_CC_HANDSHAKE | SSL3_CHANGE_CIPHER_CLIENT_WRITE))) {
+ /*
+ * This is a fatal error, which leaves sc->enc_write_ctx in an
+ * inconsistent state and thus ssl3_send_alert may crash.
+ */
+ SSLfatal(sc, SSL_AD_NO_ALERT, SSL_R_CANNOT_CHANGE_CIPHER);
+ goto out;
+ }
+ ret = 1;
+ goto out;
+
+ err:
+ SSLfatal(sc, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ out:
+ if (buf != NULL) {
+ /* If |buf| is NULL, then |tmppkt| could not have been initialized */
+ WPACKET_cleanup(&tmppkt);
+ }
+ BUF_MEM_free(buf);
+ COMP_CTX_free(comp);
+ return ret;
}
+#endif
int ssl3_check_cert_and_algorithm(SSL_CONNECTION *s)
{
const SSL_CERT_LOOKUP *clu;
size_t idx;
long alg_k, alg_a;
+ EVP_PKEY *pkey;
alg_k = s->s3.tmp.new_cipher->algorithm_mkey;
alg_a = s->s3.tmp.new_cipher->algorithm_auth;
return 1;
/* This is the passed certificate */
- clu = ssl_cert_lookup_by_pkey(X509_get0_pubkey(s->session->peer), &idx);
+ pkey = tls_get_peer_pkey(s);
+ clu = ssl_cert_lookup_by_pkey(pkey, &idx, SSL_CONNECTION_GET_CTX(s));
/* Check certificate is recognised and suitable for cipher */
if (clu == NULL || (alg_a & clu->amask) == 0) {
return 0;
}
- if (clu->amask & SSL_aECDSA) {
- if (ssl_check_srvr_ecc_cert_and_alg(s->session->peer, s))
- return 1;
- SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_R_BAD_ECC_CERT);
- return 0;
- }
-
if (alg_k & (SSL_kRSA | SSL_kRSAPSK) && idx != SSL_PKEY_RSA) {
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
SSL_R_MISSING_RSA_ENCRYPTING_CERT);
return 0;
}
+ /* Early out to skip the checks below */
+ if (s->session->peer_rpk != NULL)
+ return 1;
+
+ if (clu->amask & SSL_aECDSA) {
+ if (ssl_check_srvr_ecc_cert_and_alg(s->session->peer, s))
+ return 1;
+ SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_R_BAD_ECC_CERT);
+ return 0;
+ }
+
return 1;
}
#ifndef OPENSSL_NO_NEXTPROTONEG
-int tls_construct_next_proto(SSL_CONNECTION *s, WPACKET *pkt)
+CON_FUNC_RETURN tls_construct_next_proto(SSL_CONNECTION *s, WPACKET *pkt)
{
size_t len, padding_len;
unsigned char *padding = NULL;
if (!WPACKET_sub_memcpy_u8(pkt, s->ext.npn, len)
|| !WPACKET_sub_allocate_bytes_u8(pkt, padding_len, &padding)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
- return 0;
+ return CON_FUNC_ERROR;
}
memset(padding, 0, padding_len);
- return 1;
+ return CON_FUNC_SUCCESS;
}
#endif
{
int i;
size_t totlen = 0, len, maxlen, maxverok = 0;
- int empty_reneg_info_scsv = !s->renegotiate;
+ int empty_reneg_info_scsv = !s->renegotiate
+ && !SSL_CONNECTION_IS_DTLS(s)
+ && ssl_security(s, SSL_SECOP_VERSION, 0, TLS1_VERSION, NULL)
+ && s->min_proto_version <= TLS1_VERSION;
SSL *ssl = SSL_CONNECTION_GET_SSL(s);
/* Set disabled masks for this session */
/* Sanity check that the maximum version we offer has ciphers enabled */
if (!maxverok) {
- if (SSL_CONNECTION_IS_DTLS(s)) {
- if (DTLS_VERSION_GE(c->max_dtls, s->s3.tmp.max_ver)
- && DTLS_VERSION_LE(c->min_dtls, s->s3.tmp.max_ver))
- maxverok = 1;
- } else {
- if (c->max_tls >= s->s3.tmp.max_ver
- && c->min_tls <= s->s3.tmp.max_ver)
- maxverok = 1;
- }
+ int minproto = SSL_CONNECTION_IS_DTLS(s) ? c->min_dtls : c->min_tls;
+ int maxproto = SSL_CONNECTION_IS_DTLS(s) ? c->max_dtls : c->max_tls;
+
+ if (ssl_version_cmp(s, maxproto, s->s3.tmp.max_ver) >= 0
+ && ssl_version_cmp(s, minproto, s->s3.tmp.max_ver) <= 0)
+ maxverok = 1;
}
totlen += len;
if (totlen != 0) {
if (empty_reneg_info_scsv) {
- static SSL_CIPHER scsv = {
+ static const SSL_CIPHER scsv = {
0, NULL, NULL, SSL3_CK_SCSV, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
if (!ssl->method->put_cipher_by_char(&scsv, pkt, &len)) {
}
}
if (s->mode & SSL_MODE_SEND_FALLBACK_SCSV) {
- static SSL_CIPHER scsv = {
+ static const SSL_CIPHER scsv = {
0, NULL, NULL, SSL3_CK_FALLBACK_SCSV, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
if (!ssl->method->put_cipher_by_char(&scsv, pkt, &len)) {
return 1;
}
-int tls_construct_end_of_early_data(SSL_CONNECTION *s, WPACKET *pkt)
+CON_FUNC_RETURN tls_construct_end_of_early_data(SSL_CONNECTION *s, WPACKET *pkt)
{
if (s->early_data_state != SSL_EARLY_DATA_WRITE_RETRY
&& s->early_data_state != SSL_EARLY_DATA_FINISHED_WRITING) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
- return 0;
+ return CON_FUNC_ERROR;
}
s->early_data_state = SSL_EARLY_DATA_FINISHED_WRITING;
- return 1;
+ return CON_FUNC_SUCCESS;
}