libtls: enforce correct signature scheme for ECDSA keys

This commit is contained in:
Andreas Steffen 2022-08-23 23:52:39 +02:00
parent 77a15f55be
commit a417703301

View File

@ -1789,11 +1789,12 @@ METHOD(tls_crypto_t, sign, bool,
const chunk_t hashsig_def = chunk_from_chars(0x02, 0x01, 0x02, 0x03);
signature_params_t *params;
key_type_t type;
uint16_t scheme;
uint16_t scheme = 0, hashsig_scheme;
bio_reader_t *reader;
chunk_t sig;
bool done = FALSE;
if (this->tls->get_version_max(this->tls) >= TLS_1_3)
{
chunk_t transcript_hash;
@ -1817,29 +1818,75 @@ METHOD(tls_crypto_t, sign, bool,
{ /* fallback if none given */
hashsig = hashsig_def;
}
/* Determine TLS signature scheme if unique */
type = key->get_type(key);
switch (type)
{
case KEY_ED448:
scheme = TLS_SIG_ED448;
break;
case KEY_ED25519:
scheme = TLS_SIG_ED25519;
break;
case KEY_ECDSA:
switch (key->get_keysize(key))
{
case 256:
scheme = TLS_SIG_ECDSA_SHA256;
break;
case 384:
scheme = TLS_SIG_ECDSA_SHA384;
break;
case 521:
scheme = TLS_SIG_ECDSA_SHA512;
break;
default:
DBG1(DBG_TLS, "%d bit ECDSA private key size not supported",
key->get_keysize(key));
return FALSE;
}
break;
case KEY_RSA:
/* Several TLS signature schemes possible, select later on */
break;
default:
DBG1(DBG_TLS, "%N private key type not supported",
key_type_names, type);
return FALSE;
}
reader = bio_reader_create(hashsig);
while (reader->remaining(reader) >= 2)
{
if (reader->read_uint16(reader, &scheme))
if (reader->read_uint16(reader, &hashsig_scheme))
{
params = params_for_scheme(scheme, TRUE);
if (params &&
type == key_type_from_signature_scheme(params->scheme) &&
key->sign(key, params->scheme, params->params, data, &sig))
params = params_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 (key->sign(key, params->scheme, params->params, data, &sig))
{
done = TRUE;
scheme = hashsig_scheme;
break;
}
}
}
}
reader->destroy(reader);
if (!done)
{
DBG1(DBG_TLS, "none of the proposed hash/sig algorithms supported");
return FALSE;
}
DBG2(DBG_TLS, "created signature with %N", tls_signature_scheme_names,
DBG1(DBG_TLS, "created signature with %N", tls_signature_scheme_names,
scheme);
writer->write_uint16(writer, scheme);
writer->write_data16(writer, sig);