Use a dynamic curve enumerator to list/convert TLS named curves
This commit is contained in:
+47
-11
@@ -839,17 +839,53 @@ METHOD(tls_crypto_t, get_signature_algorithms, void,
|
|||||||
supported->destroy(supported);
|
supported->destroy(supported);
|
||||||
}
|
}
|
||||||
|
|
||||||
METHOD(tls_crypto_t, get_curves, void,
|
/**
|
||||||
private_tls_crypto_t *this, tls_writer_t *writer)
|
* Mapping groups to TLS named curves
|
||||||
|
*/
|
||||||
|
static struct {
|
||||||
|
diffie_hellman_group_t group;
|
||||||
|
tls_named_curve_t curve;
|
||||||
|
} curves[] = {
|
||||||
|
{ ECP_256_BIT, TLS_SECP256R1},
|
||||||
|
{ ECP_384_BIT, TLS_SECP384R1},
|
||||||
|
{ ECP_521_BIT, TLS_SECP521R1},
|
||||||
|
{ ECP_224_BIT, TLS_SECP224R1},
|
||||||
|
{ ECP_192_BIT, TLS_SECP192R1},
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filter EC groups, add TLS curve
|
||||||
|
*/
|
||||||
|
static bool group_filter(void *null,
|
||||||
|
diffie_hellman_group_t *in, diffie_hellman_group_t *out,
|
||||||
|
void* dummy1, tls_named_curve_t *curve)
|
||||||
{
|
{
|
||||||
u_int16_t curves[] = {
|
int i;
|
||||||
htons(TLS_SECP256R1),
|
|
||||||
htons(TLS_SECP384R1),
|
for (i = 0; i < countof(curves); i++)
|
||||||
htons(TLS_SECP521R1),
|
{
|
||||||
htons(TLS_SECP192R1),
|
if (curves[i].group == *in)
|
||||||
htons(TLS_SECP224R1),
|
{
|
||||||
};
|
if (out)
|
||||||
writer->write_data16(writer, chunk_from_thing(curves));
|
{
|
||||||
|
*out = curves[i].group;
|
||||||
|
}
|
||||||
|
if (curve)
|
||||||
|
{
|
||||||
|
*curve = curves[i].curve;
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
METHOD(tls_crypto_t, create_ec_enumerator, enumerator_t*,
|
||||||
|
private_tls_crypto_t *this)
|
||||||
|
{
|
||||||
|
return enumerator_create_filter(
|
||||||
|
lib->crypto->create_dh_enumerator(lib->crypto),
|
||||||
|
(void*)group_filter, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
METHOD(tls_crypto_t, set_protection, void,
|
METHOD(tls_crypto_t, set_protection, void,
|
||||||
@@ -1310,7 +1346,7 @@ tls_crypto_t *tls_crypto_create(tls_t *tls)
|
|||||||
.select_cipher_suite = _select_cipher_suite,
|
.select_cipher_suite = _select_cipher_suite,
|
||||||
.get_dh_group = _get_dh_group,
|
.get_dh_group = _get_dh_group,
|
||||||
.get_signature_algorithms = _get_signature_algorithms,
|
.get_signature_algorithms = _get_signature_algorithms,
|
||||||
.get_curves = _get_curves,
|
.create_ec_enumerator = _create_ec_enumerator,
|
||||||
.set_protection = _set_protection,
|
.set_protection = _set_protection,
|
||||||
.append_handshake = _append_handshake,
|
.append_handshake = _append_handshake,
|
||||||
.sign = _sign,
|
.sign = _sign,
|
||||||
|
|||||||
@@ -398,11 +398,13 @@ struct tls_crypto_t {
|
|||||||
void (*get_signature_algorithms)(tls_crypto_t *this, tls_writer_t *writer);
|
void (*get_signature_algorithms)(tls_crypto_t *this, tls_writer_t *writer);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Write the list of supported elliptic curves to writer.
|
* Create an enumerator over supported ECDH groups.
|
||||||
*
|
*
|
||||||
* @param writer writer to write elliptic curves to
|
* Enumerates over (diffie_hellman_group_t, tls_named_curve_t)
|
||||||
|
*
|
||||||
|
* @return enumerator
|
||||||
*/
|
*/
|
||||||
void (*get_curves)(tls_crypto_t *this, tls_writer_t *writer);
|
enumerator_t* (*create_ec_enumerator)(tls_crypto_t *this);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the protection layer of the TLS stack to control it.
|
* Set the protection layer of the TLS stack to control it.
|
||||||
|
|||||||
+49
-24
@@ -352,6 +352,28 @@ static status_t process_modp_key_exchange(private_tls_peer_t *this,
|
|||||||
return NEED_MORE;
|
return NEED_MORE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the EC group for a TLS named curve
|
||||||
|
*/
|
||||||
|
static diffie_hellman_group_t curve_to_ec_group(private_tls_peer_t *this,
|
||||||
|
tls_named_curve_t curve)
|
||||||
|
{
|
||||||
|
diffie_hellman_group_t group;
|
||||||
|
tls_named_curve_t current;
|
||||||
|
enumerator_t *enumerator;
|
||||||
|
|
||||||
|
enumerator = this->crypto->create_ec_enumerator(this->crypto);
|
||||||
|
while (enumerator->enumerate(enumerator, &group, ¤t))
|
||||||
|
{
|
||||||
|
if (current == curve)
|
||||||
|
{
|
||||||
|
enumerator->destroy(enumerator);
|
||||||
|
return group;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
enumerator->destroy(enumerator);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Process a Key Exchange message using EC Diffie Hellman
|
* Process a Key Exchange message using EC Diffie Hellman
|
||||||
@@ -386,28 +408,14 @@ static status_t process_ec_key_exchange(private_tls_peer_t *this,
|
|||||||
this->alert->add(this->alert, TLS_FATAL, TLS_DECODE_ERROR);
|
this->alert->add(this->alert, TLS_FATAL, TLS_DECODE_ERROR);
|
||||||
return NEED_MORE;
|
return NEED_MORE;
|
||||||
}
|
}
|
||||||
switch (curve)
|
|
||||||
|
group = curve_to_ec_group(this, curve);
|
||||||
|
if (!group)
|
||||||
{
|
{
|
||||||
case TLS_SECP256R1:
|
DBG1(DBG_TLS, "ECDH curve %N not supported",
|
||||||
group = ECP_256_BIT;
|
tls_named_curve_names, curve);
|
||||||
break;
|
this->alert->add(this->alert, TLS_FATAL, TLS_HANDSHAKE_FAILURE);
|
||||||
case TLS_SECP384R1:
|
return NEED_MORE;
|
||||||
group = ECP_384_BIT;
|
|
||||||
break;
|
|
||||||
case TLS_SECP521R1:
|
|
||||||
group = ECP_521_BIT;
|
|
||||||
break;
|
|
||||||
case TLS_SECP192R1:
|
|
||||||
group = ECP_192_BIT;
|
|
||||||
break;
|
|
||||||
case TLS_SECP224R1:
|
|
||||||
group = ECP_224_BIT;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
DBG1(DBG_TLS, "ECDH curve %N not supported",
|
|
||||||
tls_named_curve_names, curve);
|
|
||||||
this->alert->add(this->alert, TLS_FATAL, TLS_HANDSHAKE_FAILURE);
|
|
||||||
return NEED_MORE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public = find_public_key(this);
|
public = find_public_key(this);
|
||||||
@@ -656,8 +664,10 @@ static status_t send_client_hello(private_tls_peer_t *this,
|
|||||||
tls_handshake_type_t *type, tls_writer_t *writer)
|
tls_handshake_type_t *type, tls_writer_t *writer)
|
||||||
{
|
{
|
||||||
tls_cipher_suite_t *suites;
|
tls_cipher_suite_t *suites;
|
||||||
tls_writer_t *extensions;
|
tls_writer_t *extensions, *curves = NULL;
|
||||||
tls_version_t version;
|
tls_version_t version;
|
||||||
|
tls_named_curve_t curve;
|
||||||
|
enumerator_t *enumerator;
|
||||||
int count, i;
|
int count, i;
|
||||||
rng_t *rng;
|
rng_t *rng;
|
||||||
|
|
||||||
@@ -697,8 +707,23 @@ 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);
|
||||||
|
|
||||||
extensions->write_uint16(extensions, TLS_EXT_ELLIPTIC_CURVES);
|
/* add supported Elliptic Curves, if any */
|
||||||
this->crypto->get_curves(this->crypto, extensions);
|
enumerator = this->crypto->create_ec_enumerator(this->crypto);
|
||||||
|
while (enumerator->enumerate(enumerator, NULL, &curve))
|
||||||
|
{
|
||||||
|
if (!curves)
|
||||||
|
{
|
||||||
|
extensions->write_uint16(extensions, TLS_EXT_ELLIPTIC_CURVES);
|
||||||
|
curves = tls_writer_create(16);
|
||||||
|
}
|
||||||
|
curves->write_uint16(curves, curve);
|
||||||
|
}
|
||||||
|
enumerator->destroy(enumerator);
|
||||||
|
if (curves)
|
||||||
|
{
|
||||||
|
extensions->write_data16(extensions, curves->get_buf(curves));
|
||||||
|
curves->destroy(curves);
|
||||||
|
}
|
||||||
|
|
||||||
writer->write_data16(writer, extensions->get_buf(extensions));
|
writer->write_data16(writer, extensions->get_buf(extensions));
|
||||||
extensions->destroy(extensions);
|
extensions->destroy(extensions);
|
||||||
|
|||||||
+34
-36
@@ -730,39 +730,38 @@ static status_t send_certificate_request(private_tls_server_t *this,
|
|||||||
/**
|
/**
|
||||||
* Get the TLS curve of a given EC DH group
|
* Get the TLS curve of a given EC DH group
|
||||||
*/
|
*/
|
||||||
static tls_named_curve_t ec_group_to_curve(diffie_hellman_group_t group)
|
static tls_named_curve_t ec_group_to_curve(private_tls_server_t *this,
|
||||||
|
diffie_hellman_group_t group)
|
||||||
{
|
{
|
||||||
switch (group)
|
diffie_hellman_group_t current;
|
||||||
|
tls_named_curve_t curve;
|
||||||
|
enumerator_t *enumerator;
|
||||||
|
|
||||||
|
enumerator = this->crypto->create_ec_enumerator(this->crypto);
|
||||||
|
while (enumerator->enumerate(enumerator, ¤t, &curve))
|
||||||
{
|
{
|
||||||
case ECP_256_BIT:
|
if (current == group)
|
||||||
return TLS_SECP256R1;
|
{
|
||||||
case ECP_384_BIT:
|
enumerator->destroy(enumerator);
|
||||||
return TLS_SECP384R1;
|
return curve;
|
||||||
case ECP_521_BIT:
|
}
|
||||||
return TLS_SECP521R1;
|
|
||||||
case ECP_192_BIT:
|
|
||||||
return TLS_SECP192R1;
|
|
||||||
case ECP_224_BIT:
|
|
||||||
return TLS_SECP224R1;
|
|
||||||
default:
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
enumerator->destroy(enumerator);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if the peer supports a given TLS EC group
|
* Check if the peer supports a given TLS curve
|
||||||
*/
|
*/
|
||||||
bool peer_supports_ec_group(private_tls_server_t *this,
|
bool peer_supports_curve(private_tls_server_t *this, tls_named_curve_t curve)
|
||||||
diffie_hellman_group_t group)
|
|
||||||
{
|
{
|
||||||
tls_reader_t *reader;
|
tls_reader_t *reader;
|
||||||
u_int16_t curve, current;
|
u_int16_t current;
|
||||||
|
|
||||||
if (!this->curves_received)
|
if (!this->curves_received)
|
||||||
{ /* none received, assume yes */
|
{ /* none received, assume yes */
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
curve = ec_group_to_curve(group);
|
|
||||||
reader = tls_reader_create(this->curves);
|
reader = tls_reader_create(this->curves);
|
||||||
while (reader->remaining(reader) && reader->read_uint16(reader, ¤t))
|
while (reader->remaining(reader) && reader->read_uint16(reader, ¤t))
|
||||||
{
|
{
|
||||||
@@ -777,28 +776,25 @@ bool peer_supports_ec_group(private_tls_server_t *this,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Try to find a group supported by both, client and server
|
* Try to find a curve supported by both, client and server
|
||||||
*/
|
*/
|
||||||
static bool find_supported_group(private_tls_server_t *this,
|
static bool find_supported_curve(private_tls_server_t *this,
|
||||||
diffie_hellman_group_t *group)
|
tls_named_curve_t *curve)
|
||||||
{
|
{
|
||||||
diffie_hellman_group_t groups[] = {
|
tls_named_curve_t current;
|
||||||
ECP_256_BIT,
|
enumerator_t *enumerator;
|
||||||
ECP_384_BIT,
|
|
||||||
ECP_521_BIT,
|
|
||||||
ECP_224_BIT,
|
|
||||||
ECP_192_BIT,
|
|
||||||
};
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < countof(groups); i++)
|
enumerator = this->crypto->create_ec_enumerator(this->crypto);
|
||||||
|
while (enumerator->enumerate(enumerator, NULL, ¤t))
|
||||||
{
|
{
|
||||||
if (peer_supports_ec_group(this, groups[i]))
|
if (peer_supports_curve(this, current))
|
||||||
{
|
{
|
||||||
*group = groups[i];
|
*curve = current;
|
||||||
|
enumerator->destroy(enumerator);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
enumerator->destroy(enumerator);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -810,19 +806,21 @@ static status_t send_server_key_exchange(private_tls_server_t *this,
|
|||||||
diffie_hellman_group_t group)
|
diffie_hellman_group_t group)
|
||||||
{
|
{
|
||||||
diffie_hellman_params_t *params = NULL;
|
diffie_hellman_params_t *params = NULL;
|
||||||
|
tls_named_curve_t curve;
|
||||||
chunk_t chunk;
|
chunk_t chunk;
|
||||||
|
|
||||||
if (diffie_hellman_group_is_ec(group))
|
if (diffie_hellman_group_is_ec(group))
|
||||||
{
|
{
|
||||||
if (!peer_supports_ec_group(this, group) &&
|
curve = ec_group_to_curve(this, group);
|
||||||
!find_supported_group(this, &group))
|
if (!curve || (!peer_supports_curve(this, curve) &&
|
||||||
|
!find_supported_curve(this, &curve)))
|
||||||
{
|
{
|
||||||
DBG1(DBG_TLS, "no EC group supported by client and server");
|
DBG1(DBG_TLS, "no EC group supported by client and server");
|
||||||
this->alert->add(this->alert, TLS_FATAL, TLS_HANDSHAKE_FAILURE);
|
this->alert->add(this->alert, TLS_FATAL, TLS_HANDSHAKE_FAILURE);
|
||||||
return NEED_MORE;
|
return NEED_MORE;
|
||||||
}
|
}
|
||||||
writer->write_uint8(writer, TLS_ECC_NAMED_CURVE);
|
writer->write_uint8(writer, TLS_ECC_NAMED_CURVE);
|
||||||
writer->write_uint16(writer, ec_group_to_curve(group));
|
writer->write_uint16(writer, curve);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user