summaryrefslogtreecommitdiff
path: root/src/libcharon/config/proposal.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libcharon/config/proposal.c')
-rw-r--r--src/libcharon/config/proposal.c127
1 files changed, 101 insertions, 26 deletions
diff --git a/src/libcharon/config/proposal.c b/src/libcharon/config/proposal.c
index a83acec23..011c0b8b0 100644
--- a/src/libcharon/config/proposal.c
+++ b/src/libcharon/config/proposal.c
@@ -420,24 +420,40 @@ static const struct {
};
/**
+ * Remove all entries of the given transform type
+ */
+static void remove_transform(private_proposal_t *this, transform_type_t type)
+{
+ enumerator_t *e;
+ entry_t *entry;
+
+ e = array_create_enumerator(this->transforms);
+ while (e->enumerate(e, &entry))
+ {
+ if (entry->type == type)
+ {
+ array_remove_at(this->transforms, e);
+ }
+ }
+ e->destroy(e);
+}
+
+/**
* Checks the proposal read from a string.
*/
-static void check_proposal(private_proposal_t *this)
+static bool check_proposal(private_proposal_t *this)
{
enumerator_t *e;
entry_t *entry;
uint16_t alg, ks;
- bool all_aead = TRUE;
+ bool all_aead = TRUE, any_aead = FALSE, any_enc = FALSE;
int i;
if (this->protocol == PROTO_IKE)
{
- e = create_enumerator(this, PSEUDO_RANDOM_FUNCTION);
- if (!e->enumerate(e, &alg, &ks))
- {
- /* No explicit PRF found. We assume the same algorithm as used
- * for integrity checking */
- e->destroy(e);
+ if (!get_algorithm(this, PSEUDO_RANDOM_FUNCTION, NULL, NULL))
+ { /* No explicit PRF found. We assume the same algorithm as used
+ * for integrity checking. */
e = create_enumerator(this, INTEGRITY_ALGORITHM);
while (e->enumerate(e, &alg, &ks))
{
@@ -451,8 +467,13 @@ static void check_proposal(private_proposal_t *this)
}
}
}
+ e->destroy(e);
+ }
+ if (!get_algorithm(this, PSEUDO_RANDOM_FUNCTION, NULL, NULL))
+ {
+ DBG1(DBG_CFG, "a PRF algorithm is mandatory in IKE proposals");
+ return FALSE;
}
- e->destroy(e);
/* remove MODP_NONE from IKE proposal */
e = array_create_enumerator(this->transforms);
while (e->enumerate(e, &entry))
@@ -463,48 +484,103 @@ static void check_proposal(private_proposal_t *this)
}
}
e->destroy(e);
+ if (!get_algorithm(this, DIFFIE_HELLMAN_GROUP, NULL, NULL))
+ {
+ DBG1(DBG_CFG, "a DH group is mandatory in IKE proposals");
+ return FALSE;
+ }
+ }
+ else
+ { /* remove PRFs from ESP/AH proposals */
+ remove_transform(this, PSEUDO_RANDOM_FUNCTION);
}
- if (this->protocol == PROTO_ESP)
+ if (this->protocol == PROTO_IKE || this->protocol == PROTO_ESP)
{
e = create_enumerator(this, ENCRYPTION_ALGORITHM);
while (e->enumerate(e, &alg, &ks))
{
- if (!encryption_algorithm_is_aead(alg))
+ any_enc = TRUE;
+ if (encryption_algorithm_is_aead(alg))
{
- all_aead = FALSE;
- break;
+ any_aead = TRUE;
+ continue;
}
+ all_aead = FALSE;
}
e->destroy(e);
- if (all_aead)
+ if (!any_enc)
+ {
+ DBG1(DBG_CFG, "an encryption algorithm is mandatory in %N proposals",
+ protocol_id_names, this->protocol);
+ return FALSE;
+ }
+ else if (any_aead && !all_aead)
{
- /* if all encryption algorithms in the proposal are AEADs,
+ DBG1(DBG_CFG, "classic and combined-mode (AEAD) encryption "
+ "algorithms can't be contained in the same %N proposal",
+ protocol_id_names, this->protocol);
+ return FALSE;
+ }
+ else if (all_aead)
+ { /* if all encryption algorithms in the proposal are AEADs,
* we MUST NOT propose any integrity algorithms */
- e = array_create_enumerator(this->transforms);
- while (e->enumerate(e, &entry))
+ remove_transform(this, INTEGRITY_ALGORITHM);
+ }
+ }
+ else
+ { /* AES-GMAC is parsed as encryption algorithm, so we map that to the
+ * proper integrity algorithm */
+ e = array_create_enumerator(this->transforms);
+ while (e->enumerate(e, &entry))
+ {
+ if (entry->type == ENCRYPTION_ALGORITHM)
{
- if (entry->type == INTEGRITY_ALGORITHM)
+ if (entry->alg == ENCR_NULL_AUTH_AES_GMAC)
{
- array_remove_at(this->transforms, e);
+ entry->type = INTEGRITY_ALGORITHM;
+ ks = entry->key_size;
+ entry->key_size = 0;
+ switch (ks)
+ {
+ case 128:
+ entry->alg = AUTH_AES_128_GMAC;
+ continue;
+ case 192:
+ entry->alg = AUTH_AES_192_GMAC;
+ continue;
+ case 256:
+ entry->alg = AUTH_AES_256_GMAC;
+ continue;
+ default:
+ break;
+ }
}
+ /* remove all other encryption algorithms */
+ array_remove_at(this->transforms, e);
}
- e->destroy(e);
+ }
+ e->destroy(e);
+
+ if (!get_algorithm(this, INTEGRITY_ALGORITHM, NULL, NULL))
+ {
+ DBG1(DBG_CFG, "an integrity algorithm is mandatory in AH "
+ "proposals");
+ return FALSE;
}
}
if (this->protocol == PROTO_AH || this->protocol == PROTO_ESP)
{
- e = create_enumerator(this, EXTENDED_SEQUENCE_NUMBERS);
- if (!e->enumerate(e, NULL, NULL))
+ if (!get_algorithm(this, EXTENDED_SEQUENCE_NUMBERS, NULL, NULL))
{ /* ESN not specified, assume not supported */
add_algorithm(this, EXTENDED_SEQUENCE_NUMBERS, NO_EXT_SEQ_NUMBERS, 0);
}
- e->destroy(e);
}
array_compress(this->transforms);
+ return TRUE;
}
/**
@@ -842,6 +918,7 @@ static bool proposal_add_supported_ike(private_proposal_t *this, bool aead)
case NTRU_128_BIT:
case NTRU_192_BIT:
case NTRU_256_BIT:
+ case NH_128_BIT:
add_algorithm(this, DIFFIE_HELLMAN_GROUP, group, 0);
break;
default:
@@ -999,13 +1076,11 @@ proposal_t *proposal_create_from_string(protocol_id_t protocol, const char *algs
}
enumerator->destroy(enumerator);
- if (failed)
+ if (failed || !check_proposal(this))
{
destroy(this);
return NULL;
}
- check_proposal(this);
-
return &this->public;
}