tls-peer: Use private key enumeration also in TLS versions < 1.2

Until now, key selection was based on tls_client_certificate_type_t and now
uses a simple mapping from these types to tls_signature_scheme_t.
This commit is contained in:
Pascal Knecht 2020-11-17 17:54:55 +01:00 committed by Tobias Brunner
parent d8e42a3d4e
commit d41d8b0039
1 changed files with 30 additions and 37 deletions

View File

@ -1350,42 +1350,36 @@ static status_t send_client_hello(private_tls_peer_t *this,
}
/**
* Find a private key suitable to sign Certificate Verify
* Convert certificate types to signature schemes so TLS version <= 1.1 can use
* the same private key enumeration as newer TLS versions.
*/
static private_key_t *find_private_key(private_tls_peer_t *this)
static void convert_cert_types(private_tls_peer_t *this)
{
private_key_t *key = NULL;
bio_reader_t *reader;
key_type_t type;
uint8_t cert;
bio_writer_t *writer;
uint8_t type;
if (!this->peer)
{
return NULL;
}
reader = bio_reader_create(this->cert_types);
while (reader->remaining(reader) && reader->read_uint8(reader, &cert))
writer = bio_writer_create(0);
while (reader->remaining(reader) && reader->read_uint8(reader, &type))
{
switch (cert)
/* each certificate type is mapped to one signature scheme, which is not
* ideal but serves our needs in legacy TLS versions */
switch (type)
{
case TLS_RSA_SIGN:
type = KEY_RSA;
writer->write_uint16(writer, TLS_SIG_RSA_PKCS1_SHA256);
break;
case TLS_ECDSA_SIGN:
type = KEY_ECDSA;
writer->write_uint16(writer, TLS_SIG_ECDSA_SHA256);
break;
default:
continue;
}
key = lib->credmgr->get_private(lib->credmgr, type,
this->peer, this->peer_auth);
if (key)
{
break;
}
}
reader->destroy(reader);
return key;
this->hashsig = writer->extract_buf(writer);
writer->destroy(writer);
}
/**
@ -1405,33 +1399,32 @@ static status_t send_certificate(private_tls_peer_t *this,
version_min = this->tls->get_version_min(this->tls);
version_max = this->tls->get_version_max(this->tls);
if (version_max > TLS_1_1)
if (!this->hashsig.len)
{
convert_cert_types(this);
}
enumerator = tls_create_private_key_enumerator(version_min, version_max,
this->hashsig, this->peer);
if (!enumerator || !enumerator->enumerate(enumerator, &key, &auth))
{
enumerator = tls_create_private_key_enumerator(version_min, version_max,
this->hashsig, this->peer);
if (!enumerator)
{
DBG1(DBG_TLS, "no common signature algorithms found");
return FALSE;
}
if (enumerator->enumerate(enumerator, &key, &auth))
else
{
this->private = key->get_ref(key);
this->peer_auth->merge(this->peer_auth, auth, FALSE);
DBG1(DBG_TLS, "no usable TLS client certificate found for '%Y'",
this->peer);
}
enumerator->destroy(enumerator);
}
else
{
this->private = find_private_key(this);
}
if (!this->private)
{
DBG1(DBG_TLS, "no usable TLS client certificate found for '%Y'",
this->peer);
this->peer->destroy(this->peer);
this->peer = NULL;
}
else
{
this->private = key->get_ref(key);
this->peer_auth->merge(this->peer_auth, auth, FALSE);
}
DESTROY_IF(enumerator);
/* generate certificate payload */
certs = bio_writer_create(256);