/*
- * 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_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;
}
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) {
- if (s->ext.compress_certificate_from_peer[0] != TLSEXT_comp_cert_none)
+ if (do_compressed_cert(s))
st->hand_state = TLS_ST_CW_COMP_CERT;
else
st->hand_state = TLS_ST_CW_CERT;
st->hand_state = TLS_ST_CW_CHANGE;
else if (s->s3.tmp.cert_req == 0)
st->hand_state = TLS_ST_CW_FINISHED;
- else if (s->ext.compress_certificate_from_peer[0] != TLSEXT_comp_cert_none)
+ else if (do_compressed_cert(s))
st->hand_state = TLS_ST_CW_COMP_CERT;
else
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_CHANGE:
if (s->s3.tmp.cert_req == 0)
st->hand_state = TLS_ST_CW_FINISHED;
- else if (s->ext.compress_certificate_from_peer[0] != TLSEXT_comp_cert_none)
+ else if (do_compressed_cert(s))
st->hand_state = TLS_ST_CW_COMP_CERT;
else
st->hand_state = TLS_ST_CW_CERT;
* 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
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_increment_epoch(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:
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;
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.
* 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);
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_CRYPTO_LIB);
goto err;
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);
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)
/* 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 */
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;
#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_EVP_LIB);
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;
}
/* 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_EVP_LIB);
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)) {
return CON_FUNC_ERROR;
}
}
- if (!ssl3_output_cert_chain(s, pkt,
- (s->s3.tmp.cert_req == 2) ? NULL
- : s->cert->key, 0)) {
- /* SSLfatal() already called */
+ 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))) {
/*
|| !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))) {
/*
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,
- SSL_CONNECTION_GET_CTX(s));
+ 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;
}
{
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)) {