tls-peer: Refactor writing of extensions and use less hard-coded DH group

Note that this breaks connecting to many TLS 1.3 servers until we support
HelloRetryRequest as we now send a key_share for ECP_256 while still
proposing other groups, so many servers request to use CURVE_25519.
This commit is contained in:
Tobias Brunner
2021-02-12 11:45:44 +01:00
parent de31646a09
commit 851b605e21
+44 -33
View File
@@ -1034,17 +1034,18 @@ METHOD(tls_handshake_t, process, status_t,
* Send a client hello * Send a client hello
*/ */
static status_t send_client_hello(private_tls_peer_t *this, static status_t send_client_hello(private_tls_peer_t *this,
tls_handshake_type_t *type, bio_writer_t *writer) tls_handshake_type_t *type,
bio_writer_t *writer)
{ {
tls_cipher_suite_t *suites; tls_cipher_suite_t *suites;
bio_writer_t *extensions, *curves = NULL; bio_writer_t *extensions, *curves = NULL, *versions, *key_share;
tls_version_t version_max, version_min; tls_version_t version_max, version_min;
tls_named_group_t curve; diffie_hellman_group_t group;
tls_named_group_t curve, selected_curve = 0;
enumerator_t *enumerator; enumerator_t *enumerator;
int count, i, v; int count, i, v;
rng_t *rng; rng_t *rng;
chunk_t pub; chunk_t pub;
uint8_t nof_tls_versions;
htoun32(&this->client_random, time(NULL)); htoun32(&this->client_random, time(NULL));
rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK); rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
@@ -1059,9 +1060,6 @@ static status_t send_client_hello(private_tls_peer_t *this,
} }
rng->destroy(rng); rng->destroy(rng);
/* client key generation */
this->dh = lib->crypto->create_dh(lib->crypto, CURVE_25519);
/* TLS version_max in handshake protocol */ /* TLS version_max in handshake protocol */
version_max = this->tls->get_version_max(this->tls); version_max = this->tls->get_version_max(this->tls);
version_min = this->tls->get_version_min(this->tls); version_min = this->tls->get_version_min(this->tls);
@@ -1112,22 +1110,27 @@ static status_t send_client_hello(private_tls_peer_t *this,
DBG2(DBG_TLS, "sending extension: %N", DBG2(DBG_TLS, "sending extension: %N",
tls_extension_names, TLS_EXT_SUPPORTED_GROUPS); tls_extension_names, TLS_EXT_SUPPORTED_GROUPS);
enumerator = this->crypto->create_ec_enumerator(this->crypto); enumerator = this->crypto->create_ec_enumerator(this->crypto);
while (enumerator->enumerate(enumerator, NULL, &curve)) while (enumerator->enumerate(enumerator, &group, &curve))
{ {
if (!curves) if (!curves)
{ {
extensions->write_uint16(extensions, TLS_EXT_SUPPORTED_GROUPS); extensions->write_uint16(extensions, TLS_EXT_SUPPORTED_GROUPS);
curves = bio_writer_create(16); curves = bio_writer_create(16);
} }
if (!this->dh)
{
this->dh = lib->crypto->create_dh(lib->crypto, group);
if (!this->dh)
{
continue;
}
selected_curve = curve;
}
curves->write_uint16(curves, curve); curves->write_uint16(curves, curve);
} }
enumerator->destroy(enumerator); enumerator->destroy(enumerator);
if (curves) if (curves)
{ {
if (version_max == TLS_1_3)
{
curves->write_uint16(curves, TLS_CURVE25519);
}
curves->wrap16(curves); curves->wrap16(curves);
extensions->write_data16(extensions, curves->get_buf(curves)); extensions->write_data16(extensions, curves->get_buf(curves));
curves->destroy(curves); curves->destroy(curves);
@@ -1139,16 +1142,19 @@ static status_t send_client_hello(private_tls_peer_t *this,
extensions->write_uint8(extensions, TLS_EC_POINT_UNCOMPRESSED); extensions->write_uint8(extensions, TLS_EC_POINT_UNCOMPRESSED);
} }
DBG2(DBG_TLS, "sending extension: %N", if (version_max >= TLS_1_3)
tls_extension_names, TLS_EXT_SUPPORTED_VERSIONS);
nof_tls_versions = (version_max - version_min + 1)*2;
extensions->write_uint16(extensions, TLS_EXT_SUPPORTED_VERSIONS);
extensions->write_uint16(extensions, nof_tls_versions+1);
extensions->write_uint8(extensions, nof_tls_versions);
for (v = version_max; v >= version_min; v--)
{ {
extensions->write_uint16(extensions, v); DBG2(DBG_TLS, "sending extension: %N",
nof_tls_versions += 2; tls_extension_names, TLS_EXT_SUPPORTED_VERSIONS);
extensions->write_uint16(extensions, TLS_EXT_SUPPORTED_VERSIONS);
versions = bio_writer_create(0);
for (v = version_max; v >= version_min; v--)
{
versions->write_uint16(versions, v);
}
versions->wrap8(versions);
extensions->write_data16(extensions, versions->get_buf(versions));
versions->destroy(versions);
} }
DBG2(DBG_TLS, "sending extension: %N", DBG2(DBG_TLS, "sending extension: %N",
@@ -1156,20 +1162,25 @@ static status_t send_client_hello(private_tls_peer_t *this,
extensions->write_uint16(extensions, TLS_EXT_SIGNATURE_ALGORITHMS); extensions->write_uint16(extensions, TLS_EXT_SIGNATURE_ALGORITHMS);
this->crypto->get_signature_algorithms(this->crypto, extensions); this->crypto->get_signature_algorithms(this->crypto, extensions);
DBG2(DBG_TLS, "sending extension: %N", if (this->dh)
tls_extension_names, TLS_EXT_KEY_SHARE);
if (!this->dh->get_my_public_value(this->dh, &pub))
{ {
this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR); DBG2(DBG_TLS, "sending extension: %N",
return NEED_MORE; tls_extension_names, TLS_EXT_KEY_SHARE);
if (!this->dh->get_my_public_value(this->dh, &pub))
{
this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR);
extensions->destroy(extensions);
return NEED_MORE;
}
extensions->write_uint16(extensions, TLS_EXT_KEY_SHARE);
key_share = bio_writer_create(pub.len + 6);
key_share->write_uint16(key_share, selected_curve);
key_share->write_data16(key_share, pub);
key_share->wrap16(key_share);
extensions->write_data16(extensions, key_share->get_buf(key_share));
key_share->destroy(key_share);
free(pub.ptr);
} }
extensions->write_uint16(extensions, TLS_EXT_KEY_SHARE);
extensions->write_uint16(extensions, pub.len+6);
extensions->write_uint16(extensions, pub.len+4);
extensions->write_uint16(extensions, TLS_CURVE25519);
extensions->write_uint16(extensions, pub.len);
extensions->write_data(extensions, pub);
free(pub.ptr);
writer->write_data16(writer, extensions->get_buf(extensions)); writer->write_data16(writer, extensions->get_buf(extensions));
extensions->destroy(extensions); extensions->destroy(extensions);