proposal: Add method to check if two proposals match
Similar to select() but does not return a proposal and does not log anything.
This commit is contained in:
parent
90f5fe1ca9
commit
f72aa13a29
|
@ -335,22 +335,16 @@ METHOD(proposal_t, strip_dh, void,
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Select a matching proposal from this and other, insert into selected.
|
* Select a matching proposal from this and other.
|
||||||
*/
|
*/
|
||||||
static bool select_algo(private_proposal_t *this, proposal_t *other,
|
static bool select_algo(private_proposal_t *this, proposal_t *other,
|
||||||
proposal_t *selected, transform_type_t type, bool priv)
|
transform_type_t type, bool priv, bool log,
|
||||||
|
uint16_t *alg, uint16_t *ks)
|
||||||
{
|
{
|
||||||
enumerator_t *e1, *e2;
|
enumerator_t *e1, *e2;
|
||||||
uint16_t alg1, alg2, ks1, ks2;
|
uint16_t alg1, alg2, ks1, ks2;
|
||||||
bool found = FALSE, optional = FALSE;
|
bool found = FALSE, optional = FALSE;
|
||||||
|
|
||||||
if (type == INTEGRITY_ALGORITHM &&
|
|
||||||
selected->get_algorithm(selected, ENCRYPTION_ALGORITHM, &alg1, NULL) &&
|
|
||||||
encryption_algorithm_is_aead(alg1))
|
|
||||||
{
|
|
||||||
/* no integrity algorithm required, we have an AEAD */
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
if (type == DIFFIE_HELLMAN_GROUP)
|
if (type == DIFFIE_HELLMAN_GROUP)
|
||||||
{
|
{
|
||||||
optional = this->protocol == PROTO_ESP || this->protocol == PROTO_AH;
|
optional = this->protocol == PROTO_ESP || this->protocol == PROTO_AH;
|
||||||
|
@ -398,36 +392,86 @@ static bool select_algo(private_proposal_t *this, proposal_t *other,
|
||||||
{
|
{
|
||||||
if (!priv && alg1 >= 1024)
|
if (!priv && alg1 >= 1024)
|
||||||
{
|
{
|
||||||
/* accept private use algorithms only if requested */
|
if (log)
|
||||||
DBG1(DBG_CFG, "an algorithm from private space would match, "
|
{
|
||||||
"but peer implementation is unknown, skipped");
|
DBG1(DBG_CFG, "an algorithm from private space would "
|
||||||
|
"match, but peer implementation is unknown, "
|
||||||
|
"skipped");
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
selected->add_algorithm(selected, type, alg1, ks1);
|
*alg = alg1;
|
||||||
|
*ks = ks1;
|
||||||
found = TRUE;
|
found = TRUE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* no match in all comparisons */
|
|
||||||
e1->destroy(e1);
|
e1->destroy(e1);
|
||||||
e2->destroy(e2);
|
e2->destroy(e2);
|
||||||
|
|
||||||
if (!found)
|
|
||||||
{
|
|
||||||
DBG2(DBG_CFG, " no acceptable %N found", transform_type_names, type);
|
|
||||||
}
|
|
||||||
return found;
|
return found;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Select algorithms from the given proposals, if selected is given, the result
|
||||||
|
* is stored there and errors are logged.
|
||||||
|
*/
|
||||||
|
static bool select_algos(private_proposal_t *this, proposal_t *other,
|
||||||
|
proposal_t *selected, bool private)
|
||||||
|
{
|
||||||
|
transform_type_t type;
|
||||||
|
array_t *types;
|
||||||
|
bool skip_integrity = FALSE;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
types = merge_types(this, (private_proposal_t*)other);
|
||||||
|
for (i = 0; i < array_count(types); i++)
|
||||||
|
{
|
||||||
|
uint16_t alg = 0, ks = 0;
|
||||||
|
|
||||||
|
array_get(types, i, &type);
|
||||||
|
if (type == INTEGRITY_ALGORITHM && skip_integrity)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (select_algo(this, other, type, private, selected != NULL, &alg, &ks))
|
||||||
|
{
|
||||||
|
if (alg == 0 && type != EXTENDED_SEQUENCE_NUMBERS)
|
||||||
|
{ /* 0 is "valid" for extended sequence numbers, for other
|
||||||
|
* transforms it either means NONE or is reserved */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (selected)
|
||||||
|
{
|
||||||
|
selected->add_algorithm(selected, type, alg, ks);
|
||||||
|
}
|
||||||
|
if (type == ENCRYPTION_ALGORITHM &&
|
||||||
|
encryption_algorithm_is_aead(alg))
|
||||||
|
{
|
||||||
|
/* no integrity algorithm required, we have an AEAD */
|
||||||
|
skip_integrity = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (selected)
|
||||||
|
{
|
||||||
|
DBG2(DBG_CFG, " no acceptable %N found", transform_type_names,
|
||||||
|
type);
|
||||||
|
}
|
||||||
|
array_destroy(types);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
array_destroy(types);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
METHOD(proposal_t, select_proposal, proposal_t*,
|
METHOD(proposal_t, select_proposal, proposal_t*,
|
||||||
private_proposal_t *this, proposal_t *other, bool other_remote,
|
private_proposal_t *this, proposal_t *other, bool other_remote,
|
||||||
bool private)
|
bool private)
|
||||||
{
|
{
|
||||||
proposal_t *selected;
|
proposal_t *selected;
|
||||||
transform_type_t type;
|
|
||||||
array_t *types;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
DBG2(DBG_CFG, "selecting proposal:");
|
DBG2(DBG_CFG, "selecting proposal:");
|
||||||
|
|
||||||
|
@ -448,23 +492,25 @@ METHOD(proposal_t, select_proposal, proposal_t*,
|
||||||
selected->set_spi(selected, this->spi);
|
selected->set_spi(selected, this->spi);
|
||||||
}
|
}
|
||||||
|
|
||||||
types = merge_types(this, (private_proposal_t*)other);
|
if (!select_algos(this, other, selected, private))
|
||||||
for (i = 0; i < array_count(types); i++)
|
|
||||||
{
|
{
|
||||||
array_get(types, i, &type);
|
selected->destroy(selected);
|
||||||
if (!select_algo(this, other, selected, type, private))
|
return NULL;
|
||||||
{
|
|
||||||
selected->destroy(selected);
|
|
||||||
array_destroy(types);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
array_destroy(types);
|
|
||||||
|
|
||||||
DBG2(DBG_CFG, " proposal matches");
|
DBG2(DBG_CFG, " proposal matches");
|
||||||
return selected;
|
return selected;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
METHOD(proposal_t, matches, bool,
|
||||||
|
private_proposal_t *this, proposal_t *other, bool private)
|
||||||
|
{
|
||||||
|
if (this->protocol != other->get_protocol(other))
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
return select_algos(this, other, NULL, private);
|
||||||
|
}
|
||||||
|
|
||||||
METHOD(proposal_t, get_protocol, protocol_id_t,
|
METHOD(proposal_t, get_protocol, protocol_id_t,
|
||||||
private_proposal_t *this)
|
private_proposal_t *this)
|
||||||
{
|
{
|
||||||
|
@ -910,6 +956,7 @@ proposal_t *proposal_create(protocol_id_t protocol, u_int number)
|
||||||
.promote_dh_group = _promote_dh_group,
|
.promote_dh_group = _promote_dh_group,
|
||||||
.strip_dh = _strip_dh,
|
.strip_dh = _strip_dh,
|
||||||
.select = _select_proposal,
|
.select = _select_proposal,
|
||||||
|
.matches = _matches,
|
||||||
.get_protocol = _get_protocol,
|
.get_protocol = _get_protocol,
|
||||||
.set_spi = _set_spi,
|
.set_spi = _set_spi,
|
||||||
.get_spi = _get_spi,
|
.get_spi = _get_spi,
|
||||||
|
|
|
@ -34,7 +34,6 @@ typedef struct proposal_t proposal_t;
|
||||||
#include <crypto/crypters/crypter.h>
|
#include <crypto/crypters/crypter.h>
|
||||||
#include <crypto/signers/signer.h>
|
#include <crypto/signers/signer.h>
|
||||||
#include <crypto/diffie_hellman.h>
|
#include <crypto/diffie_hellman.h>
|
||||||
#include <selectors/traffic_selector.h>
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Protocol ID of a proposal.
|
* Protocol ID of a proposal.
|
||||||
|
@ -143,6 +142,17 @@ struct proposal_t {
|
||||||
proposal_t *(*select)(proposal_t *this, proposal_t *other,
|
proposal_t *(*select)(proposal_t *this, proposal_t *other,
|
||||||
bool other_remote, bool private);
|
bool other_remote, bool private);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the given proposal matches this proposal.
|
||||||
|
*
|
||||||
|
* This is similar to select, but no resulting proposal is selected.
|
||||||
|
*
|
||||||
|
* @param other proposal to compare against
|
||||||
|
* @param private accepts algorithms allocated in a private range
|
||||||
|
* @return TRUE if the proposals match
|
||||||
|
*/
|
||||||
|
bool (*matches)(proposal_t *this, proposal_t *other, bool private);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the protocol ID of the proposal.
|
* Get the protocol ID of the proposal.
|
||||||
*
|
*
|
||||||
|
|
|
@ -102,7 +102,12 @@ static struct {
|
||||||
{ PROTO_ESP, "aes128-sha256-modp3072-modpnone", "aes128-sha256", "aes128-sha256" },
|
{ PROTO_ESP, "aes128-sha256-modp3072-modpnone", "aes128-sha256", "aes128-sha256" },
|
||||||
{ PROTO_ESP, "aes128-sha256", "aes128-sha256-modp3072-modpnone", "aes128-sha256" },
|
{ PROTO_ESP, "aes128-sha256", "aes128-sha256-modp3072-modpnone", "aes128-sha256" },
|
||||||
{ PROTO_ESP, "aes128-sha256-modp3072-modpnone", "aes128-sha256-modpnone-modp3072", "aes128-sha256-modp3072" },
|
{ PROTO_ESP, "aes128-sha256-modp3072-modpnone", "aes128-sha256-modpnone-modp3072", "aes128-sha256-modp3072" },
|
||||||
{ PROTO_ESP, "aes128-sha256-modpnone-modp3072", "aes128-sha256-modp3072-modpnone", "aes128-sha256-modpnone" },
|
{ PROTO_ESP, "aes128-sha256-modpnone-modp3072", "aes128-sha256-modp3072-modpnone", "aes128-sha256" },
|
||||||
|
{ PROTO_ESP, "aes128-sha256-esn", "aes128-sha256-esn", "aes128-sha256-esn" },
|
||||||
|
{ PROTO_ESP, "aes128-sha256-noesn", "aes128-sha256-esn", NULL },
|
||||||
|
{ PROTO_ESP, "aes128-sha256-noesn-esn", "aes128-sha256-esn", "aes128-sha256-esn" },
|
||||||
|
{ PROTO_ESP, "aes128-sha256-noesn-esn", "aes128-sha256", "aes128-sha256" },
|
||||||
|
{ PROTO_ESP, "aes128-sha256-esn-noesn", "aes128-sha256-noesn-esn", "aes128-sha256-esn" },
|
||||||
{ PROTO_IKE, "aes128-sha256-modp3072", "aes128-sha256-modp3072", "aes128-sha256-modp3072" },
|
{ PROTO_IKE, "aes128-sha256-modp3072", "aes128-sha256-modp3072", "aes128-sha256-modp3072" },
|
||||||
{ PROTO_IKE, "aes128-sha256-modp3072", "aes128-sha256-modp3072-modpnone", "aes128-sha256-modp3072" },
|
{ PROTO_IKE, "aes128-sha256-modp3072", "aes128-sha256-modp3072-modpnone", "aes128-sha256-modp3072" },
|
||||||
{ PROTO_IKE, "aes128-sha256-modp3072-modpnone", "aes128-sha256-modp3072", "aes128-sha256-modp3072" },
|
{ PROTO_IKE, "aes128-sha256-modp3072-modpnone", "aes128-sha256-modp3072", "aes128-sha256-modp3072" },
|
||||||
|
@ -159,6 +164,29 @@ START_TEST(test_select_spi)
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST(test_matches)
|
||||||
|
{
|
||||||
|
proposal_t *self, *other;
|
||||||
|
|
||||||
|
self = proposal_create_from_string(select_data[_i].proto,
|
||||||
|
select_data[_i].self);
|
||||||
|
other = proposal_create_from_string(select_data[_i].proto,
|
||||||
|
select_data[_i].other);
|
||||||
|
if (select_data[_i].expected)
|
||||||
|
{
|
||||||
|
ck_assert(self->matches(self, other, FALSE));
|
||||||
|
ck_assert(other->matches(other, self, FALSE));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ck_assert(!self->matches(self, other, FALSE));
|
||||||
|
ck_assert(!other->matches(other, self, FALSE));
|
||||||
|
}
|
||||||
|
other->destroy(other);
|
||||||
|
self->destroy(self);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
START_TEST(test_promote_dh_group)
|
START_TEST(test_promote_dh_group)
|
||||||
{
|
{
|
||||||
proposal_t *proposal;
|
proposal_t *proposal;
|
||||||
|
@ -312,6 +340,10 @@ Suite *proposal_suite_create()
|
||||||
tcase_add_test(tc, test_select_spi);
|
tcase_add_test(tc, test_select_spi);
|
||||||
suite_add_tcase(s, tc);
|
suite_add_tcase(s, tc);
|
||||||
|
|
||||||
|
tc = tcase_create("matches");
|
||||||
|
tcase_add_loop_test(tc, test_matches, 0, countof(select_data));
|
||||||
|
suite_add_tcase(s, tc);
|
||||||
|
|
||||||
tc = tcase_create("promote_dh_group");
|
tc = tcase_create("promote_dh_group");
|
||||||
tcase_add_test(tc, test_promote_dh_group);
|
tcase_add_test(tc, test_promote_dh_group);
|
||||||
tcase_add_test(tc, test_promote_dh_group_already_front);
|
tcase_add_test(tc, test_promote_dh_group_already_front);
|
||||||
|
|
Loading…
Reference in New Issue