#define SSL_EXT_TLS1_3_CERTIFICATE 0x1000
#define SSL_EXT_TLS1_3_NEW_SESSION_TICKET 0x2000
#define SSL_EXT_TLS1_3_CERTIFICATE_REQUEST 0x4000
+#define SSL_EXT_TLS1_3_CERTIFICATE_COMPRESSION 0x8000
/* Typedefs for handling custom extensions */
WPACKET tmppkt;
BUF_MEM buf = { 0 };
size_t ret = 0;
- const SSL_METHOD *method = NULL;
if (sc == NULL
|| cpk == NULL
goto out;
/*
- * ssl3_output_cert_chain() may generate an SSLfata() error,
- * for this case, we want to ignore it
+ * ssl3_output_cert_chain() may generate an SSLfatal() error,
+ * for this case, we want to ignore it, argument for_comp = 1
*/
- sc->statem.ignore_fatal = 1;
- ERR_set_mark();
- /* Must get the certificate as TLSv1.3, restore before returning */
- method = SSL_get_ssl_method(ssl);
- if (!SSL_set_ssl_method(ssl, tlsv1_3_server_method()))
- goto out;
-
- if (!ssl3_output_cert_chain(sc, &tmppkt, cpk))
+ if (!ssl3_output_cert_chain(sc, &tmppkt, cpk, 1))
goto out;
WPACKET_get_total_written(&tmppkt, &ret);
out:
- /* Don't leave errors in the queue */
- ERR_pop_to_mark();
- sc->statem.ignore_fatal = 0;
- if (method != NULL && !SSL_set_ssl_method(ssl, method))
- ret = 0;
WPACKET_cleanup(&tmppkt);
if (ret != 0 && data != NULL)
*data = (unsigned char *)buf.data;
size_t len);
void ssl3_free_digest_list(SSL_CONNECTION *s);
__owur unsigned long ssl3_output_cert_chain(SSL_CONNECTION *s, WPACKET *pkt,
- CERT_PKEY *cpk);
+ CERT_PKEY *cpk, int for_comp);
__owur const SSL_CIPHER *ssl3_choose_cipher(SSL_CONNECTION *s,
STACK_OF(SSL_CIPHER) *clnt,
STACK_OF(SSL_CIPHER) *srvr);
size_t i;
int min_version, max_version = 0, reason;
const EXTENSION_DEFINITION *thisexd;
+ int for_comp = (context & SSL_EXT_TLS1_3_CERTIFICATE_COMPRESSION) != 0;
if (!WPACKET_start_sub_packet_u16(pkt)
/*
|| ((context &
(SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO)) != 0
&& !WPACKET_set_flags(pkt,
- WPACKET_FLAGS_ABANDON_ON_ZERO_LENGTH))) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ WPACKET_FLAGS_ABANDON_ON_ZERO_LENGTH))) {
+ if (!for_comp)
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
if ((context & SSL_EXT_CLIENT_HELLO) != 0) {
reason = ssl_get_min_max_version(s, &min_version, &max_version, NULL);
if (reason != 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, reason);
+ if (!for_comp)
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, reason);
return 0;
}
}
}
if (!WPACKET_close(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ if (!for_comp)
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
custom_ext_method *meth;
size_t i;
int al;
+ int for_comp = (context & SSL_EXT_TLS1_3_CERTIFICATE_COMPRESSION) != 0;
for (i = 0; i < exts->meths_count; i++) {
const unsigned char *out = NULL;
meth->add_arg);
if (cb_retval < 0) {
- SSLfatal(s, al, SSL_R_CALLBACK_FAILED);
+ if (!for_comp)
+ SSLfatal(s, al, SSL_R_CALLBACK_FAILED);
return 0; /* error */
}
if (cb_retval == 0)
|| !WPACKET_start_sub_packet_u16(pkt)
|| (outlen > 0 && !WPACKET_memcpy(pkt, out, outlen))
|| !WPACKET_close(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ if (!for_comp)
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
if ((context & SSL_EXT_CLIENT_HELLO) != 0) {
* We can't send duplicates: code logic should prevent this.
*/
if (!ossl_assert((meth->ext_flags & SSL_EXT_FLAG_SENT) == 0)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ if (!for_comp)
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
/*
s->statem.hand_state = TLS_ST_BEFORE;
ossl_statem_set_in_init(s, 1);
s->statem.no_cert_verify = 0;
- s->statem.ignore_fatal = 0;
}
/*
void ossl_statem_send_fatal(SSL_CONNECTION *s, int al)
{
- /*
- * Some public APIs may call internal functions that fatal error,
- * which doesn't make sense outside the state machine. Those APIs
- * that can handle a failure set this flag to avoid errors sending
- * alerts. Example: getting a wire-formatted certificate for
- * compression.
- */
- if (s->statem.ignore_fatal)
- return;
/* We shouldn't call SSLfatal() twice. Once is enough */
if (s->statem.in_init && s->statem.state == MSG_FLOW_ERROR)
return;
OSSL_HANDSHAKE_STATE request_state;
int in_init;
int read_state_first_init;
- int ignore_fatal;
/* true when we are actually in SSL_accept() or SSL_connect() */
int in_handshake;
/*
}
if (!ssl3_output_cert_chain(s, pkt,
(s->s3.tmp.cert_req == 2) ? NULL
- : s->cert->key)) {
+ : s->cert->key, 0)) {
/* SSLfatal() already called */
return CON_FUNC_ERROR;
}
} 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)) {
+ if (!ssl3_output_cert_chain(sc, &tmppkt, sc->cert->key, 0)) {
/* SSLfatal() already called */
goto out;
}
/* Add a certificate to the WPACKET */
static int ssl_add_cert_to_wpacket(SSL_CONNECTION *s, WPACKET *pkt,
- X509 *x, int chain)
+ X509 *x, int chain, int for_comp)
{
int len;
unsigned char *outbytes;
+ int context = SSL_EXT_TLS1_3_CERTIFICATE;
+
+ if (for_comp)
+ context |= SSL_EXT_TLS1_3_CERTIFICATE_COMPRESSION;
len = i2d_X509(x, NULL);
if (len < 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_BUF_LIB);
+ if (!for_comp)
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_BUF_LIB);
return 0;
}
if (!WPACKET_sub_allocate_bytes_u24(pkt, len, &outbytes)
|| i2d_X509(x, &outbytes) != len) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ if (!for_comp)
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
- if (SSL_CONNECTION_IS_TLS13(s)
- && !tls_construct_extensions(s, pkt, SSL_EXT_TLS1_3_CERTIFICATE, x,
- chain)) {
+ if ((SSL_CONNECTION_IS_TLS13(s) || for_comp)
+ && !tls_construct_extensions(s, pkt, context, x, chain)) {
/* SSLfatal() already called */
return 0;
}
}
/* Add certificate chain to provided WPACKET */
-static int ssl_add_cert_chain(SSL_CONNECTION *s, WPACKET *pkt, CERT_PKEY *cpk)
+static int ssl_add_cert_chain(SSL_CONNECTION *s, WPACKET *pkt, CERT_PKEY *cpk, int for_comp)
{
int i, chain_count;
X509 *x;
sctx->propq);
if (xs_ctx == NULL) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_X509_LIB);
+ if (!for_comp)
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_X509_LIB);
return 0;
}
if (!X509_STORE_CTX_init(xs_ctx, chain_store, x, NULL)) {
X509_STORE_CTX_free(xs_ctx);
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_X509_LIB);
+ if (!for_comp)
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_X509_LIB);
return 0;
}
/*
ERR_raise(ERR_LIB_SSL, SSL_R_CA_MD_TOO_WEAK);
#endif
X509_STORE_CTX_free(xs_ctx);
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, i);
+ if (!for_comp)
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, i);
return 0;
}
chain_count = sk_X509_num(chain);
for (i = 0; i < chain_count; i++) {
x = sk_X509_value(chain, i);
- if (!ssl_add_cert_to_wpacket(s, pkt, x, i)) {
+ if (!ssl_add_cert_to_wpacket(s, pkt, x, i, for_comp)) {
/* SSLfatal() already called */
X509_STORE_CTX_free(xs_ctx);
return 0;
} else {
i = ssl_security_cert_chain(s, extra_certs, x, 0);
if (i != 1) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, i);
+ if (!for_comp)
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, i);
return 0;
}
- if (!ssl_add_cert_to_wpacket(s, pkt, x, 0)) {
+ if (!ssl_add_cert_to_wpacket(s, pkt, x, 0, for_comp)) {
/* SSLfatal() already called */
return 0;
}
for (i = 0; i < sk_X509_num(extra_certs); i++) {
x = sk_X509_value(extra_certs, i);
- if (!ssl_add_cert_to_wpacket(s, pkt, x, i + 1)) {
+ if (!ssl_add_cert_to_wpacket(s, pkt, x, i + 1, for_comp)) {
/* SSLfatal() already called */
return 0;
}
}
unsigned long ssl3_output_cert_chain(SSL_CONNECTION *s, WPACKET *pkt,
- CERT_PKEY *cpk)
+ CERT_PKEY *cpk, int for_comp)
{
if (!WPACKET_start_sub_packet_u24(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ if (!for_comp)
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
- if (!ssl_add_cert_chain(s, pkt, cpk))
+ if (!ssl_add_cert_chain(s, pkt, cpk, for_comp))
return 0;
if (!WPACKET_close(pkt)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ if (!for_comp)
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return CON_FUNC_ERROR;
}
- if (!ssl3_output_cert_chain(s, pkt, cpk)) {
+ if (!ssl3_output_cert_chain(s, pkt, cpk, 0)) {
/* SSLfatal() already called */
return CON_FUNC_ERROR;
}