tls-crypto: Reject signature schemes not actually defined for current TLS version

Also adds a filter for the locally configured signature schemes that are
already used when sending the supported schemes.
This commit is contained in:
Tobias Brunner
2026-07-24 08:47:36 +02:00
parent c720ae2307
commit 5e89dd5c4d
+36 -15
View File
@@ -1497,10 +1497,9 @@ METHOD(tls_crypto_t, get_signature_algorithms, void,
}
/**
* Get the signature parameters from a TLS signature scheme
* Get the signature config entry from a TLS signature scheme
*/
static signature_params_t *params_for_scheme(tls_signature_scheme_t sig,
bool sign)
static scheme_algs_t *config_for_scheme(tls_signature_scheme_t sig, bool sign)
{
int i;
@@ -1516,12 +1515,25 @@ static signature_params_t *params_for_scheme(tls_signature_scheme_t sig,
}
if (schemes[i].sig == sig)
{
return &schemes[i].params;
return &schemes[i];
}
}
return NULL;
}
/**
* Check whether the given signature scheme is valid for the negotiated version
* and the local config.
*/
static bool is_scheme_valid(private_tls_crypto_t *this, scheme_algs_t *scheme)
{
tls_version_t version;
version = this->tls->get_version_max(this->tls);
return scheme->min_version <= version && scheme->max_version >= version &&
filter_signature_scheme_config(scheme->sig);
}
/**
* Mapping groups to TLS named curves
*/
@@ -1787,7 +1799,7 @@ METHOD(tls_crypto_t, sign, bool,
{
/* fallback to SHA1/RSA and SHA1/ECDSA */
const chunk_t hashsig_def = chunk_from_chars(0x02, 0x01, 0x02, 0x03);
signature_params_t *params;
scheme_algs_t *config;
key_type_t type;
uint16_t scheme = 0, hashsig_scheme;
bio_reader_t *reader;
@@ -1861,17 +1873,19 @@ METHOD(tls_crypto_t, sign, bool,
{
if (reader->read_uint16(reader, &hashsig_scheme))
{
params = params_for_scheme(hashsig_scheme, TRUE);
config = config_for_scheme(hashsig_scheme, TRUE);
/**
* All key types except RSA have a single fixed signature scheme
* RSA signature schemes are tried until sign() is successful
*/
if (params && (scheme == hashsig_scheme ||
(!scheme &&
type == key_type_from_signature_scheme(params->scheme))))
if (config && is_scheme_valid(this, config) &&
(scheme == hashsig_scheme ||
(!scheme &&
type == key_type_from_signature_scheme(config->params.scheme))))
{
if (key->sign(key, params->scheme, params->params, data, &sig))
if (key->sign(key, config->params.scheme,
config->params.params, data, &sig))
{
done = TRUE;
scheme = hashsig_scheme;
@@ -1949,7 +1963,7 @@ METHOD(tls_crypto_t, verify, bool,
{
if (this->tls->get_version_max(this->tls) >= TLS_1_2)
{
signature_params_t *params;
scheme_algs_t *config;
uint16_t scheme;
chunk_t sig;
@@ -1959,13 +1973,19 @@ METHOD(tls_crypto_t, verify, bool,
DBG1(DBG_TLS, "received invalid signature");
return FALSE;
}
params = params_for_scheme(scheme, FALSE);
if (!params)
config = config_for_scheme(scheme, FALSE);
if (!config)
{
DBG1(DBG_TLS, "signature algorithms %N not supported",
DBG1(DBG_TLS, "signature algorithm %N not supported",
tls_signature_scheme_names, scheme);
return FALSE;
}
if (!is_scheme_valid(this, config))
{
DBG1(DBG_TLS, "signature algorithm %N not valid for version or "
"config", tls_signature_scheme_names, scheme);
return FALSE;
}
if (this->tls->get_version_max(this->tls) >= TLS_1_3)
{
chunk_t transcript_hash;
@@ -1985,7 +2005,8 @@ METHOD(tls_crypto_t, verify, bool,
data = chunk_cata("cm", tls13_sig_data_server, transcript_hash);
}
}
if (!key->verify(key, params->scheme, params->params, data, sig))
if (!key->verify(key, config->params.scheme, config->params.params,
data, sig))
{
DBG1(DBG_TLS, "signature verification with %N failed",
tls_signature_scheme_names, scheme);