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; bio_reader_t *reader;
key_type_t type; bio_writer_t *writer;
uint8_t cert; uint8_t type;
if (!this->peer)
{
return NULL;
}
reader = bio_reader_create(this->cert_types); 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: case TLS_RSA_SIGN:
type = KEY_RSA; writer->write_uint16(writer, TLS_SIG_RSA_PKCS1_SHA256);
break; break;
case TLS_ECDSA_SIGN: case TLS_ECDSA_SIGN:
type = KEY_ECDSA; writer->write_uint16(writer, TLS_SIG_ECDSA_SHA256);
break; break;
default: default:
continue; continue;
} }
key = lib->credmgr->get_private(lib->credmgr, type,
this->peer, this->peer_auth);
if (key)
{
break;
}
} }
reader->destroy(reader); 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_min = this->tls->get_version_min(this->tls);
version_max = this->tls->get_version_max(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) if (!enumerator)
{ {
DBG1(DBG_TLS, "no common signature algorithms found"); DBG1(DBG_TLS, "no common signature algorithms found");
return FALSE;
} }
if (enumerator->enumerate(enumerator, &key, &auth)) else
{ {
this->private = key->get_ref(key); DBG1(DBG_TLS, "no usable TLS client certificate found for '%Y'",
this->peer_auth->merge(this->peer_auth, auth, FALSE); 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->destroy(this->peer);
this->peer = NULL; 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 */ /* generate certificate payload */
certs = bio_writer_create(256); certs = bio_writer_create(256);