summaryrefslogtreecommitdiff
path: root/src/libcharon/sa/ikev2
diff options
context:
space:
mode:
Diffstat (limited to 'src/libcharon/sa/ikev2')
-rw-r--r--src/libcharon/sa/ikev2/keymat_v2.c7
-rw-r--r--src/libcharon/sa/ikev2/tasks/child_create.c81
-rw-r--r--src/libcharon/sa/ikev2/tasks/child_delete.c1
-rw-r--r--src/libcharon/sa/ikev2/tasks/child_rekey.c62
4 files changed, 103 insertions, 48 deletions
diff --git a/src/libcharon/sa/ikev2/keymat_v2.c b/src/libcharon/sa/ikev2/keymat_v2.c
index 70dacd1dc..0c41c68d0 100644
--- a/src/libcharon/sa/ikev2/keymat_v2.c
+++ b/src/libcharon/sa/ikev2/keymat_v2.c
@@ -342,10 +342,13 @@ METHOD(keymat_v2_t, derive_ike_keys, bool,
* the nonces. */
switch (alg)
{
+ case PRF_AES128_CMAC:
+ /* while variable keys may be used according to RFC 4615, RFC 7296
+ * explicitly limits the key size to 128 bit for this application */
case PRF_AES128_XCBC:
- /* while rfc4434 defines variable keys for AES-XCBC, rfc3664 does
+ /* while RFC 4434 defines variable keys for AES-XCBC, RFC 3664 does
* not and therefore fixed key semantics apply to XCBC for key
- * derivation. */
+ * derivation, which is also reinforced by RFC 7296 */
case PRF_CAMELLIA128_XCBC:
/* draft-kanno-ipsecme-camellia-xcbc refers to rfc 4434, we
* assume fixed key length. */
diff --git a/src/libcharon/sa/ikev2/tasks/child_create.c b/src/libcharon/sa/ikev2/tasks/child_create.c
index 896cabb2b..cac3bc0a2 100644
--- a/src/libcharon/sa/ikev2/tasks/child_create.c
+++ b/src/libcharon/sa/ikev2/tasks/child_create.c
@@ -478,6 +478,7 @@ static status_t select_and_install(private_child_create_t *this,
bool no_dh, bool ike_auth)
{
status_t status, status_i, status_o;
+ child_sa_outbound_state_t out_state;
chunk_t nonce_i, nonce_r;
chunk_t encr_i = chunk_empty, encr_r = chunk_empty;
chunk_t integ_i = chunk_empty, integ_r = chunk_empty;
@@ -678,29 +679,42 @@ static status_t select_and_install(private_child_create_t *this,
status_i = this->child_sa->install(this->child_sa, encr_r, integ_r,
this->my_spi, this->my_cpi, this->initiator,
TRUE, this->tfcv3);
- status_o = this->child_sa->install(this->child_sa, encr_i, integ_i,
- this->other_spi, this->other_cpi, this->initiator,
- FALSE, this->tfcv3);
}
- else if (!this->rekey)
+ else
{
status_i = this->child_sa->install(this->child_sa, encr_i, integ_i,
this->my_spi, this->my_cpi, this->initiator,
TRUE, this->tfcv3);
- status_o = this->child_sa->install(this->child_sa, encr_r, integ_r,
+ }
+ if (this->rekey)
+ { /* during rekeyings we install the outbound SA and/or policies
+ * separately: as responder when we receive the delete for the old
+ * SA, as initiator pretty much immediately in the ike-rekey task,
+ * unless there was a rekey collision that we lost */
+ if (this->initiator)
+ {
+ status_o = this->child_sa->register_outbound(this->child_sa,
+ encr_i, integ_i, this->other_spi, this->other_cpi,
+ this->tfcv3);
+ }
+ else
+ {
+ status_o = this->child_sa->register_outbound(this->child_sa,
+ encr_r, integ_r, this->other_spi, this->other_cpi,
+ this->tfcv3);
+ }
+ }
+ else if (this->initiator)
+ {
+ status_o = this->child_sa->install(this->child_sa, encr_i, integ_i,
this->other_spi, this->other_cpi, this->initiator,
FALSE, this->tfcv3);
}
else
- { /* as responder during a rekeying we only install the inbound
- * SA now, the outbound SA and policies are installed when we
- * receive the delete for the old SA */
- status_i = this->child_sa->install(this->child_sa, encr_i, integ_i,
- this->my_spi, this->my_cpi, this->initiator,
- TRUE, this->tfcv3);
- this->child_sa->register_outbound(this->child_sa, encr_r, integ_r,
- this->other_spi, this->other_cpi, this->tfcv3);
- status_o = SUCCESS;
+ {
+ status_o = this->child_sa->install(this->child_sa, encr_r, integ_r,
+ this->other_spi, this->other_cpi, this->initiator,
+ FALSE, this->tfcv3);
}
}
@@ -745,20 +759,15 @@ static status_t select_and_install(private_child_create_t *this,
charon->bus->child_keys(charon->bus, this->child_sa, this->initiator,
this->dh, nonce_i, nonce_r);
- this->child_sa->set_state(this->child_sa, CHILD_INSTALLED);
- this->ike_sa->add_child_sa(this->ike_sa, this->child_sa);
- this->established = TRUE;
-
- schedule_inactivity_timeout(this);
-
my_ts = linked_list_create_from_enumerator(
this->child_sa->create_ts_enumerator(this->child_sa, TRUE));
other_ts = linked_list_create_from_enumerator(
this->child_sa->create_ts_enumerator(this->child_sa, FALSE));
+ out_state = this->child_sa->get_outbound_state(this->child_sa);
DBG0(DBG_IKE, "%sCHILD_SA %s{%d} established "
"with SPIs %.8x_i %.8x_o and TS %#R === %#R",
- this->rekey && !this->initiator ? "inbound " : "",
+ (out_state == CHILD_OUTBOUND_INSTALLED) ? "" : "inbound ",
this->child_sa->get_name(this->child_sa),
this->child_sa->get_unique_id(this->child_sa),
ntohl(this->child_sa->get_spi(this->child_sa, TRUE)),
@@ -767,6 +776,12 @@ static status_t select_and_install(private_child_create_t *this,
my_ts->destroy(my_ts);
other_ts->destroy(other_ts);
+
+ this->child_sa->set_state(this->child_sa, CHILD_INSTALLED);
+ this->ike_sa->add_child_sa(this->ike_sa, this->child_sa);
+ this->established = TRUE;
+
+ schedule_inactivity_timeout(this);
return SUCCESS;
}
@@ -1007,17 +1022,6 @@ METHOD(task_t, build_i, status_t,
break;
}
- if (this->reqid)
- {
- DBG0(DBG_IKE, "establishing CHILD_SA %s{%d}",
- this->config->get_name(this->config), this->reqid);
- }
- else
- {
- DBG0(DBG_IKE, "establishing CHILD_SA %s",
- this->config->get_name(this->config));
- }
-
/* check if we want a virtual IP, but don't have one */
list = linked_list_create();
peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
@@ -1070,6 +1074,19 @@ METHOD(task_t, build_i, status_t,
this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY),
this->mark_in, this->mark_out);
+ if (this->reqid)
+ {
+ DBG0(DBG_IKE, "establishing CHILD_SA %s{%d} reqid %d",
+ this->child_sa->get_name(this->child_sa),
+ this->child_sa->get_unique_id(this->child_sa), this->reqid);
+ }
+ else
+ {
+ DBG0(DBG_IKE, "establishing CHILD_SA %s{%d}",
+ this->child_sa->get_name(this->child_sa),
+ this->child_sa->get_unique_id(this->child_sa));
+ }
+
if (!allocate_spi(this))
{
DBG1(DBG_IKE, "unable to allocate SPIs from kernel");
diff --git a/src/libcharon/sa/ikev2/tasks/child_delete.c b/src/libcharon/sa/ikev2/tasks/child_delete.c
index 626796383..2217295b6 100644
--- a/src/libcharon/sa/ikev2/tasks/child_delete.c
+++ b/src/libcharon/sa/ikev2/tasks/child_delete.c
@@ -196,7 +196,6 @@ static void install_outbound(private_child_delete_t *this,
/* FIXME: delete the new child_sa? */
return;
}
- child_sa->set_state(child_sa, CHILD_INSTALLED);
my_ts = linked_list_create_from_enumerator(
child_sa->create_ts_enumerator(child_sa, TRUE));
diff --git a/src/libcharon/sa/ikev2/tasks/child_rekey.c b/src/libcharon/sa/ikev2/tasks/child_rekey.c
index 761c860e7..b67e9b80f 100644
--- a/src/libcharon/sa/ikev2/tasks/child_rekey.c
+++ b/src/libcharon/sa/ikev2/tasks/child_rekey.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2016 Tobias Brunner
+ * Copyright (C) 2009-2017 Tobias Brunner
* Copyright (C) 2005-2007 Martin Willi
* Copyright (C) 2005 Jan Hutter
* HSR Hochschule fuer Technik Rapperswil
@@ -283,7 +283,8 @@ METHOD(task_t, build_r, status_t,
/**
* Handle a rekey collision
*/
-static child_sa_t *handle_collision(private_child_rekey_t *this)
+static child_sa_t *handle_collision(private_child_rekey_t *this,
+ child_sa_t **to_install)
{
child_sa_t *to_delete;
@@ -302,8 +303,11 @@ static child_sa_t *handle_collision(private_child_rekey_t *this)
{
child_sa_t *child_sa;
- DBG1(DBG_IKE, "CHILD_SA rekey collision won, deleting old child");
+ *to_install = this->child_create->get_child(this->child_create);
to_delete = this->child_sa;
+ DBG1(DBG_IKE, "CHILD_SA rekey collision won, deleting old child "
+ "%s{%d}", to_delete->get_name(to_delete),
+ to_delete->get_unique_id(to_delete));
/* don't touch child other created, it has already been deleted */
if (!this->other_child_destroyed)
{
@@ -321,9 +325,10 @@ static child_sa_t *handle_collision(private_child_rekey_t *this)
}
else
{
- DBG1(DBG_IKE, "CHILD_SA rekey collision lost, "
- "deleting rekeyed child");
to_delete = this->child_create->get_child(this->child_create);
+ DBG1(DBG_IKE, "CHILD_SA rekey collision lost, deleting redundant "
+ "child %s{%d}", to_delete->get_name(to_delete),
+ to_delete->get_unique_id(to_delete));
}
}
else
@@ -334,15 +339,17 @@ static child_sa_t *handle_collision(private_child_rekey_t *this)
* the CHILD_SA the other is not deleting. */
if (del->get_child(del) != this->child_sa)
{
- DBG1(DBG_IKE, "CHILD_SA rekey/delete collision, "
- "deleting rekeyed child");
to_delete = this->child_sa;
+ DBG1(DBG_IKE, "CHILD_SA rekey/delete collision, deleting old child "
+ "%s{%d}", to_delete->get_name(to_delete),
+ to_delete->get_unique_id(to_delete));
}
else
{
- DBG1(DBG_IKE, "CHILD_SA rekey/delete collision, "
- "deleting redundant child");
to_delete = this->child_create->get_child(this->child_create);
+ DBG1(DBG_IKE, "CHILD_SA rekey/delete collision, deleting redundant "
+ "child %s{%d}", to_delete->get_name(to_delete),
+ to_delete->get_unique_id(to_delete));
}
}
return to_delete;
@@ -353,7 +360,7 @@ METHOD(task_t, process_i, status_t,
{
protocol_id_t protocol;
uint32_t spi;
- child_sa_t *to_delete;
+ child_sa_t *to_delete, *to_install = NULL;
if (message->get_notify(message, NO_ADDITIONAL_SAS))
{
@@ -415,19 +422,48 @@ METHOD(task_t, process_i, status_t,
/* check for rekey collisions */
if (this->collision)
{
- to_delete = handle_collision(this);
+ to_delete = handle_collision(this, &to_install);
}
else
{
+ to_install = this->child_create->get_child(this->child_create);
to_delete = this->child_sa;
}
-
+ if (to_install)
+ {
+ if (to_install->install_outbound(to_install) != SUCCESS)
+ {
+ DBG1(DBG_IKE, "unable to install outbound IPsec SA (SAD) in kernel");
+ charon->bus->alert(charon->bus, ALERT_INSTALL_CHILD_SA_FAILED,
+ to_install);
+ /* FIXME: delete the child_sa? fail the task? */
+ }
+ else
+ {
+ linked_list_t *my_ts, *other_ts;
+
+ my_ts = linked_list_create_from_enumerator(
+ to_install->create_ts_enumerator(to_install, TRUE));
+ other_ts = linked_list_create_from_enumerator(
+ to_install->create_ts_enumerator(to_install, FALSE));
+
+ DBG0(DBG_IKE, "outbound CHILD_SA %s{%d} established "
+ "with SPIs %.8x_i %.8x_o and TS %#R === %#R",
+ to_install->get_name(to_install),
+ to_install->get_unique_id(to_install),
+ ntohl(to_install->get_spi(to_install, TRUE)),
+ ntohl(to_install->get_spi(to_install, FALSE)),
+ my_ts, other_ts);
+
+ my_ts->destroy(my_ts);
+ other_ts->destroy(other_ts);
+ }
+ }
if (to_delete != this->child_create->get_child(this->child_create))
{ /* invoke rekey hook if rekeying successful */
charon->bus->child_rekey(charon->bus, this->child_sa,
this->child_create->get_child(this->child_create));
}
-
if (to_delete == NULL)
{
return SUCCESS;