aboutsummaryrefslogtreecommitdiff
path: root/ssl/ssl_conf.c
diff options
context:
space:
mode:
Diffstat (limited to 'ssl/ssl_conf.c')
-rw-r--r--ssl/ssl_conf.c178
1 files changed, 138 insertions, 40 deletions
diff --git a/ssl/ssl_conf.c b/ssl/ssl_conf.c
index 698280288e9d..946d20be527c 100644
--- a/ssl/ssl_conf.c
+++ b/ssl/ssl_conf.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2012-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2012-2025 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@@ -7,6 +7,8 @@
* https://www.openssl.org/source/license.html
*/
+#include "internal/e_os.h"
+
#include <stdio.h>
#include "ssl_local.h"
#include <openssl/conf.h>
@@ -14,6 +16,7 @@
#include <openssl/decoder.h>
#include <openssl/core_dispatch.h>
#include "internal/nelem.h"
+#include "internal/ssl_unwrap.h"
/*
* structure holding name tables. This is used for permitted elements in lists
@@ -86,7 +89,9 @@ struct ssl_conf_ctx_st {
/* Pointer to SSL or SSL_CTX options field or NULL if none */
uint64_t *poptions;
/* Certificate filenames for each type */
- char *cert_filename[SSL_PKEY_NUM];
+ char **cert_filename;
+ /* Number of elements in the cert_filename array */
+ size_t num_cert_filename;
/* Pointer to SSL or SSL_CTX cert_flags or NULL if none */
uint32_t *pcert_flags;
/* Pointer to SSL or SSL_CTX verify_mode or NULL if none */
@@ -241,7 +246,7 @@ static int cmd_ECDHParameters(SSL_CONF_CTX *cctx, const char *value)
return 1;
/* ECDHParameters accepts a single group name */
- if (strstr(value, ":") != NULL)
+ if (strchr(value, ':') != NULL)
return 0;
if (cctx->ctx)
@@ -337,7 +342,7 @@ static int min_max_proto(SSL_CONF_CTX *cctx, const char *value, int *bound)
if (cctx->ctx != NULL)
method_version = cctx->ctx->method->version;
else if (cctx->ssl != NULL)
- method_version = cctx->ssl->ctx->method->version;
+ method_version = cctx->ssl->defltmeth->version;
else
return 0;
if ((new_version = protocol_from_string(value)) < 0)
@@ -391,12 +396,18 @@ static int cmd_Options(SSL_CONF_CTX *cctx, const char *value)
SSL_FLAG_TBL_INV("EncryptThenMac", SSL_OP_NO_ENCRYPT_THEN_MAC),
SSL_FLAG_TBL("NoRenegotiation", SSL_OP_NO_RENEGOTIATION),
SSL_FLAG_TBL("AllowNoDHEKEX", SSL_OP_ALLOW_NO_DHE_KEX),
+ SSL_FLAG_TBL("PreferNoDHEKEX", SSL_OP_PREFER_NO_DHE_KEX),
SSL_FLAG_TBL("PrioritizeChaCha", SSL_OP_PRIORITIZE_CHACHA),
SSL_FLAG_TBL("MiddleboxCompat", SSL_OP_ENABLE_MIDDLEBOX_COMPAT),
SSL_FLAG_TBL_INV("AntiReplay", SSL_OP_NO_ANTI_REPLAY),
SSL_FLAG_TBL_INV("ExtendedMasterSecret", SSL_OP_NO_EXTENDED_MASTER_SECRET),
SSL_FLAG_TBL_INV("CANames", SSL_OP_DISABLE_TLSEXT_CA_NAMES),
- SSL_FLAG_TBL("KTLS", SSL_OP_ENABLE_KTLS)
+ SSL_FLAG_TBL("KTLS", SSL_OP_ENABLE_KTLS),
+ SSL_FLAG_TBL_CERT("StrictCertCheck", SSL_CERT_FLAG_TLS_STRICT),
+ SSL_FLAG_TBL_INV("TxCertificateCompression", SSL_OP_NO_TX_CERTIFICATE_COMPRESSION),
+ SSL_FLAG_TBL_INV("RxCertificateCompression", SSL_OP_NO_RX_CERTIFICATE_COMPRESSION),
+ SSL_FLAG_TBL("KTLSTxZerocopySendfile", SSL_OP_ENABLE_KTLS_TX_ZEROCOPY_SENDFILE),
+ SSL_FLAG_TBL("IgnoreUnexpectedEOF", SSL_OP_IGNORE_UNEXPECTED_EOF),
};
if (value == NULL)
return -3;
@@ -430,20 +441,33 @@ static int cmd_Certificate(SSL_CONF_CTX *cctx, const char *value)
{
int rv = 1;
CERT *c = NULL;
- if (cctx->ctx) {
+ if (cctx->ctx != NULL) {
rv = SSL_CTX_use_certificate_chain_file(cctx->ctx, value);
c = cctx->ctx->cert;
}
- if (cctx->ssl) {
- rv = SSL_use_certificate_chain_file(cctx->ssl, value);
- c = cctx->ssl->cert;
+ if (cctx->ssl != NULL) {
+ SSL_CONNECTION *sc = SSL_CONNECTION_FROM_SSL(cctx->ssl);
+
+ if (sc != NULL) {
+ rv = SSL_use_certificate_chain_file(cctx->ssl, value);
+ c = sc->cert;
+ } else {
+ rv = 0;
+ }
}
- if (rv > 0 && c && cctx->flags & SSL_CONF_FLAG_REQUIRE_PRIVATE) {
- char **pfilename = &cctx->cert_filename[c->key - c->pkeys];
- OPENSSL_free(*pfilename);
- *pfilename = OPENSSL_strdup(value);
- if (*pfilename == NULL)
+ if (rv > 0 && c != NULL && cctx->flags & SSL_CONF_FLAG_REQUIRE_PRIVATE) {
+ size_t fileidx = c->key - c->pkeys;
+
+ if (fileidx >= cctx->num_cert_filename) {
rv = 0;
+ } else {
+ char **pfilename = &cctx->cert_filename[c->key - c->pkeys];
+
+ OPENSSL_free(*pfilename);
+ *pfilename = OPENSSL_strdup(value);
+ if (*pfilename == NULL)
+ rv = 0;
+ }
}
return rv > 0;
@@ -483,7 +507,12 @@ static int do_store(SSL_CONF_CTX *cctx,
cert = cctx->ctx->cert;
ctx = cctx->ctx;
} else if (cctx->ssl != NULL) {
- cert = cctx->ssl->cert;
+ SSL_CONNECTION *sc = SSL_CONNECTION_FROM_SSL(cctx->ssl);
+
+ if (sc == NULL)
+ return 0;
+
+ cert = sc->cert;
ctx = cctx->ssl->ctx;
} else {
return 1;
@@ -631,21 +660,47 @@ static int cmd_DHParameters(SSL_CONF_CTX *cctx, const char *value)
return rv > 0;
}
+/*
+ * |value| input is "<number[,number]>"
+ * where the first number is the padding block size for
+ * application data, and the optional second is the
+ * padding block size for handshake messages
+ */
static int cmd_RecordPadding(SSL_CONF_CTX *cctx, const char *value)
{
int rv = 0;
- int block_size = atoi(value);
+ unsigned long block_padding = 0, hs_padding = 0;
+ char *commap = NULL, *copy = NULL;
+ char *endptr = NULL;
+
+ copy = OPENSSL_strdup(value);
+ if (copy == NULL)
+ goto out;
+ commap = strstr(copy, ",");
+ if (commap != NULL) {
+ *commap = '\0';
+ if (*(commap + 1) == '\0')
+ goto out;
+ if (!OPENSSL_strtoul(commap + 1, &endptr, 0, &hs_padding))
+ goto out;
+ }
+ if (!OPENSSL_strtoul(copy, &endptr, 0, &block_padding))
+ goto out;
+ if (commap == NULL)
+ hs_padding = block_padding;
/*
- * All we care about is a non-negative value,
+ * All we care about are non-negative values,
* the setters check the range
*/
- if (block_size >= 0) {
- if (cctx->ctx)
- rv = SSL_CTX_set_block_padding(cctx->ctx, block_size);
- if (cctx->ssl)
- rv = SSL_set_block_padding(cctx->ssl, block_size);
- }
+ if (cctx->ctx)
+ rv = SSL_CTX_set_block_padding_ex(cctx->ctx, (size_t)block_padding,
+ (size_t)hs_padding);
+ if (cctx->ssl)
+ rv = SSL_set_block_padding_ex(cctx->ssl, (size_t)block_padding,
+ (size_t)hs_padding);
+out:
+ OPENSSL_free(copy);
return rv;
}
@@ -694,6 +749,10 @@ static const ssl_conf_cmd_tbl ssl_conf_cmds[] = {
SSL_CONF_CMD_SWITCH("bugs", 0),
SSL_CONF_CMD_SWITCH("no_comp", 0),
SSL_CONF_CMD_SWITCH("comp", 0),
+ SSL_CONF_CMD_SWITCH("no_tx_cert_comp", 0),
+ SSL_CONF_CMD_SWITCH("tx_cert_comp", 0),
+ SSL_CONF_CMD_SWITCH("no_rx_cert_comp", 0),
+ SSL_CONF_CMD_SWITCH("rx_cert_comp", 0),
SSL_CONF_CMD_SWITCH("ecdh_single", SSL_CONF_FLAG_SERVER),
SSL_CONF_CMD_SWITCH("no_ticket", 0),
SSL_CONF_CMD_SWITCH("serverpref", SSL_CONF_FLAG_SERVER),
@@ -704,12 +763,14 @@ static const ssl_conf_cmd_tbl ssl_conf_cmds[] = {
SSL_CONF_CMD_SWITCH("no_resumption_on_reneg", SSL_CONF_FLAG_SERVER),
SSL_CONF_CMD_SWITCH("no_legacy_server_connect", SSL_CONF_FLAG_CLIENT),
SSL_CONF_CMD_SWITCH("allow_no_dhe_kex", 0),
+ SSL_CONF_CMD_SWITCH("prefer_no_dhe_kex", 0),
SSL_CONF_CMD_SWITCH("prioritize_chacha", SSL_CONF_FLAG_SERVER),
SSL_CONF_CMD_SWITCH("strict", 0),
SSL_CONF_CMD_SWITCH("no_middlebox", 0),
SSL_CONF_CMD_SWITCH("anti_replay", SSL_CONF_FLAG_SERVER),
SSL_CONF_CMD_SWITCH("no_anti_replay", SSL_CONF_FLAG_SERVER),
SSL_CONF_CMD_SWITCH("no_etm", 0),
+ SSL_CONF_CMD_SWITCH("no_ems", 0),
SSL_CONF_CMD_STRING(SignatureAlgorithms, "sigalgs", 0),
SSL_CONF_CMD_STRING(ClientSignatureAlgorithms, "client_sigalgs", 0),
SSL_CONF_CMD_STRING(Curves, "curves", 0),
@@ -773,6 +834,10 @@ static const ssl_switch_tbl ssl_cmd_switches[] = {
{SSL_OP_ALL, 0}, /* bugs */
{SSL_OP_NO_COMPRESSION, 0}, /* no_comp */
{SSL_OP_NO_COMPRESSION, SSL_TFLAG_INV}, /* comp */
+ {SSL_OP_NO_TX_CERTIFICATE_COMPRESSION, 0}, /* no_tx_cert_comp */
+ {SSL_OP_NO_TX_CERTIFICATE_COMPRESSION, SSL_TFLAG_INV}, /* tx_cert_comp */
+ {SSL_OP_NO_RX_CERTIFICATE_COMPRESSION, 0}, /* no_rx_cert_comp */
+ {SSL_OP_NO_RX_CERTIFICATE_COMPRESSION, SSL_TFLAG_INV}, /* rx_cert_comp */
{SSL_OP_SINGLE_ECDH_USE, 0}, /* ecdh_single */
{SSL_OP_NO_TICKET, 0}, /* no_ticket */
{SSL_OP_CIPHER_SERVER_PREFERENCE, 0}, /* serverpref */
@@ -790,6 +855,8 @@ static const ssl_switch_tbl ssl_cmd_switches[] = {
{SSL_OP_LEGACY_SERVER_CONNECT, SSL_TFLAG_INV},
/* allow_no_dhe_kex */
{SSL_OP_ALLOW_NO_DHE_KEX, 0},
+ /* prefer_no_dhe_kex */
+ {SSL_OP_PREFER_NO_DHE_KEX, 0},
/* chacha reprioritization */
{SSL_OP_PRIORITIZE_CHACHA, 0},
{SSL_CERT_FLAG_TLS_STRICT, SSL_TFLAG_CERT}, /* strict */
@@ -801,6 +868,8 @@ static const ssl_switch_tbl ssl_cmd_switches[] = {
{SSL_OP_NO_ANTI_REPLAY, 0},
/* no Encrypt-then-Mac */
{SSL_OP_NO_ENCRYPT_THEN_MAC, 0},
+ /* no Extended master secret */
+ {SSL_OP_NO_EXTENDED_MASTER_SECRET, 0},
};
static int ssl_conf_cmd_skip_prefix(SSL_CONF_CTX *cctx, const char **pcmd)
@@ -827,7 +896,7 @@ static int ssl_conf_cmd_skip_prefix(SSL_CONF_CTX *cctx, const char **pcmd)
}
/* Determine if a command is allowed according to cctx flags */
-static int ssl_conf_cmd_allowed(SSL_CONF_CTX *cctx, const ssl_conf_cmd_tbl * t)
+static int ssl_conf_cmd_allowed(SSL_CONF_CTX *cctx, const ssl_conf_cmd_tbl *t)
{
unsigned int tfl = t->flags;
unsigned int cfl = cctx->flags;
@@ -865,7 +934,7 @@ static const ssl_conf_cmd_tbl *ssl_conf_cmd_lookup(SSL_CONF_CTX *cctx,
return NULL;
}
-static int ctrl_switch_option(SSL_CONF_CTX *cctx, const ssl_conf_cmd_tbl * cmd)
+static int ctrl_switch_option(SSL_CONF_CTX *cctx, const ssl_conf_cmd_tbl *cmd)
{
/* Find index of command in table */
size_t idx = cmd - ssl_conf_cmds;
@@ -981,17 +1050,23 @@ int SSL_CONF_CTX_finish(SSL_CONF_CTX *cctx)
/* See if any certificates are missing private keys */
size_t i;
CERT *c = NULL;
- if (cctx->ctx)
+
+ if (cctx->ctx != NULL) {
c = cctx->ctx->cert;
- else if (cctx->ssl)
- c = cctx->ssl->cert;
- if (c && cctx->flags & SSL_CONF_FLAG_REQUIRE_PRIVATE) {
- for (i = 0; i < SSL_PKEY_NUM; i++) {
+ } else if (cctx->ssl != NULL) {
+ SSL_CONNECTION *sc = SSL_CONNECTION_FROM_SSL(cctx->ssl);
+
+ if (sc != NULL)
+ c = sc->cert;
+ }
+ if (c != NULL && cctx->flags & SSL_CONF_FLAG_REQUIRE_PRIVATE) {
+ for (i = 0; i < cctx->num_cert_filename; i++) {
const char *p = cctx->cert_filename[i];
+
/*
* If missing private key try to load one from certificate file
*/
- if (p && !c->pkeys[i].privatekey) {
+ if (p != NULL && c->pkeys[i].privatekey == NULL) {
if (!cmd_PrivateKey(cctx, p))
return 0;
}
@@ -1009,12 +1084,21 @@ int SSL_CONF_CTX_finish(SSL_CONF_CTX *cctx)
return 1;
}
+static void free_cert_filename(SSL_CONF_CTX *cctx)
+{
+ size_t i;
+
+ for (i = 0; i < cctx->num_cert_filename; i++)
+ OPENSSL_free(cctx->cert_filename[i]);
+ OPENSSL_free(cctx->cert_filename);
+ cctx->cert_filename = NULL;
+ cctx->num_cert_filename = 0;
+}
+
void SSL_CONF_CTX_free(SSL_CONF_CTX *cctx)
{
if (cctx) {
- size_t i;
- for (i = 0; i < SSL_PKEY_NUM; i++)
- OPENSSL_free(cctx->cert_filename[i]);
+ free_cert_filename(cctx);
OPENSSL_free(cctx->prefix);
sk_X509_NAME_pop_free(cctx->canames, X509_NAME_free);
OPENSSL_free(cctx);
@@ -1054,12 +1138,21 @@ void SSL_CONF_CTX_set_ssl(SSL_CONF_CTX *cctx, SSL *ssl)
{
cctx->ssl = ssl;
cctx->ctx = NULL;
- if (ssl) {
- cctx->poptions = &ssl->options;
- cctx->min_version = &ssl->min_proto_version;
- cctx->max_version = &ssl->max_proto_version;
- cctx->pcert_flags = &ssl->cert->cert_flags;
- cctx->pvfy_flags = &ssl->verify_mode;
+ free_cert_filename(cctx);
+ if (ssl != NULL) {
+ SSL_CONNECTION *sc = SSL_CONNECTION_FROM_SSL(ssl);
+
+ if (sc == NULL)
+ return;
+ cctx->poptions = &sc->options;
+ cctx->min_version = &sc->min_proto_version;
+ cctx->max_version = &sc->max_proto_version;
+ cctx->pcert_flags = &sc->cert->cert_flags;
+ cctx->pvfy_flags = &sc->verify_mode;
+ cctx->cert_filename = OPENSSL_zalloc(sc->ssl_pkey_num
+ * sizeof(*cctx->cert_filename));
+ if (cctx->cert_filename != NULL)
+ cctx->num_cert_filename = sc->ssl_pkey_num;
} else {
cctx->poptions = NULL;
cctx->min_version = NULL;
@@ -1073,12 +1166,17 @@ void SSL_CONF_CTX_set_ssl_ctx(SSL_CONF_CTX *cctx, SSL_CTX *ctx)
{
cctx->ctx = ctx;
cctx->ssl = NULL;
+ free_cert_filename(cctx);
if (ctx) {
cctx->poptions = &ctx->options;
cctx->min_version = &ctx->min_proto_version;
cctx->max_version = &ctx->max_proto_version;
cctx->pcert_flags = &ctx->cert->cert_flags;
cctx->pvfy_flags = &ctx->verify_mode;
+ cctx->cert_filename = OPENSSL_zalloc((SSL_PKEY_NUM + ctx->sigalg_list_len)
+ * sizeof(*cctx->cert_filename));
+ if (cctx->cert_filename != NULL)
+ cctx->num_cert_filename = SSL_PKEY_NUM + ctx->sigalg_list_len;
} else {
cctx->poptions = NULL;
cctx->min_version = NULL;