Merge commit 'derived-keys'
Adds new listener hooks that work similar to the existing ike|child_keys hooks but receive the derived IKE and CHILD_SA keys.
This commit is contained in:
+68
-1
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2011-2015 Tobias Brunner
|
* Copyright (C) 2011-2016 Tobias Brunner
|
||||||
* Copyright (C) 2006 Martin Willi
|
* Copyright (C) 2006 Martin Willi
|
||||||
* Hochschule fuer Technik Rapperswil
|
* Hochschule fuer Technik Rapperswil
|
||||||
*
|
*
|
||||||
@@ -601,6 +601,38 @@ METHOD(bus_t, ike_keys, void,
|
|||||||
this->mutex->unlock(this->mutex);
|
this->mutex->unlock(this->mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
METHOD(bus_t, ike_derived_keys, void,
|
||||||
|
private_bus_t *this, chunk_t sk_ei, chunk_t sk_er, chunk_t sk_ai,
|
||||||
|
chunk_t sk_ar)
|
||||||
|
{
|
||||||
|
enumerator_t *enumerator;
|
||||||
|
ike_sa_t *ike_sa;
|
||||||
|
entry_t *entry;
|
||||||
|
bool keep;
|
||||||
|
|
||||||
|
ike_sa = this->thread_sa->get(this->thread_sa);
|
||||||
|
|
||||||
|
this->mutex->lock(this->mutex);
|
||||||
|
enumerator = this->listeners->create_enumerator(this->listeners);
|
||||||
|
while (enumerator->enumerate(enumerator, &entry))
|
||||||
|
{
|
||||||
|
if (entry->calling || !entry->listener->ike_derived_keys)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
entry->calling++;
|
||||||
|
keep = entry->listener->ike_derived_keys(entry->listener, ike_sa, sk_ei,
|
||||||
|
sk_er, sk_ai, sk_ar);
|
||||||
|
entry->calling--;
|
||||||
|
if (!keep)
|
||||||
|
{
|
||||||
|
unregister_listener(this, entry, enumerator);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
enumerator->destroy(enumerator);
|
||||||
|
this->mutex->unlock(this->mutex);
|
||||||
|
}
|
||||||
|
|
||||||
METHOD(bus_t, child_keys, void,
|
METHOD(bus_t, child_keys, void,
|
||||||
private_bus_t *this, child_sa_t *child_sa, bool initiator,
|
private_bus_t *this, child_sa_t *child_sa, bool initiator,
|
||||||
diffie_hellman_t *dh, chunk_t nonce_i, chunk_t nonce_r)
|
diffie_hellman_t *dh, chunk_t nonce_i, chunk_t nonce_r)
|
||||||
@@ -633,6 +665,39 @@ METHOD(bus_t, child_keys, void,
|
|||||||
this->mutex->unlock(this->mutex);
|
this->mutex->unlock(this->mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
METHOD(bus_t, child_derived_keys, void,
|
||||||
|
private_bus_t *this, child_sa_t *child_sa, bool initiator,
|
||||||
|
chunk_t encr_i, chunk_t encr_r, chunk_t integ_i, chunk_t integ_r)
|
||||||
|
{
|
||||||
|
enumerator_t *enumerator;
|
||||||
|
ike_sa_t *ike_sa;
|
||||||
|
entry_t *entry;
|
||||||
|
bool keep;
|
||||||
|
|
||||||
|
ike_sa = this->thread_sa->get(this->thread_sa);
|
||||||
|
|
||||||
|
this->mutex->lock(this->mutex);
|
||||||
|
enumerator = this->listeners->create_enumerator(this->listeners);
|
||||||
|
while (enumerator->enumerate(enumerator, &entry))
|
||||||
|
{
|
||||||
|
if (entry->calling || !entry->listener->child_derived_keys)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
entry->calling++;
|
||||||
|
keep = entry->listener->child_derived_keys(entry->listener, ike_sa,
|
||||||
|
child_sa, initiator, encr_i, encr_r,
|
||||||
|
integ_i, integ_r);
|
||||||
|
entry->calling--;
|
||||||
|
if (!keep)
|
||||||
|
{
|
||||||
|
unregister_listener(this, entry, enumerator);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
enumerator->destroy(enumerator);
|
||||||
|
this->mutex->unlock(this->mutex);
|
||||||
|
}
|
||||||
|
|
||||||
METHOD(bus_t, child_updown, void,
|
METHOD(bus_t, child_updown, void,
|
||||||
private_bus_t *this, child_sa_t *child_sa, bool up)
|
private_bus_t *this, child_sa_t *child_sa, bool up)
|
||||||
{
|
{
|
||||||
@@ -1069,7 +1134,9 @@ bus_t *bus_create()
|
|||||||
.child_state_change = _child_state_change,
|
.child_state_change = _child_state_change,
|
||||||
.message = _message,
|
.message = _message,
|
||||||
.ike_keys = _ike_keys,
|
.ike_keys = _ike_keys,
|
||||||
|
.ike_derived_keys = _ike_derived_keys,
|
||||||
.child_keys = _child_keys,
|
.child_keys = _child_keys,
|
||||||
|
.child_derived_keys = _child_derived_keys,
|
||||||
.ike_updown = _ike_updown,
|
.ike_updown = _ike_updown,
|
||||||
.ike_rekey = _ike_rekey,
|
.ike_rekey = _ike_rekey,
|
||||||
.ike_update = _ike_update,
|
.ike_update = _ike_update,
|
||||||
|
|||||||
+30
-5
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2012-2015 Tobias Brunner
|
* Copyright (C) 2012-2016 Tobias Brunner
|
||||||
* Copyright (C) 2006-2009 Martin Willi
|
* Copyright (C) 2006-2009 Martin Willi
|
||||||
* Hochschule fuer Technik Rapperswil
|
* Hochschule fuer Technik Rapperswil
|
||||||
*
|
*
|
||||||
@@ -349,8 +349,8 @@ struct bus_t {
|
|||||||
* @param ike_sa IKE_SA this keymat belongs to
|
* @param ike_sa IKE_SA this keymat belongs to
|
||||||
* @param dh diffie hellman shared secret
|
* @param dh diffie hellman shared secret
|
||||||
* @param dh_other others DH public value (IKEv1 only)
|
* @param dh_other others DH public value (IKEv1 only)
|
||||||
* @param nonce_i initiators nonce
|
* @param nonce_i initiator's nonce
|
||||||
* @param nonce_r responders nonce
|
* @param nonce_r responder's nonce
|
||||||
* @param rekey IKE_SA we are rekeying, if any (IKEv2 only)
|
* @param rekey IKE_SA we are rekeying, if any (IKEv2 only)
|
||||||
* @param shared shared key used for key derivation (IKEv1-PSK only)
|
* @param shared shared key used for key derivation (IKEv1-PSK only)
|
||||||
*/
|
*/
|
||||||
@@ -358,18 +358,43 @@ struct bus_t {
|
|||||||
chunk_t dh_other, chunk_t nonce_i, chunk_t nonce_r,
|
chunk_t dh_other, chunk_t nonce_i, chunk_t nonce_r,
|
||||||
ike_sa_t *rekey, shared_key_t *shared);
|
ike_sa_t *rekey, shared_key_t *shared);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IKE_SA derived keys hook.
|
||||||
|
*
|
||||||
|
* @param sk_ei SK_ei, or Ka for IKEv1
|
||||||
|
* @param sk_er SK_er
|
||||||
|
* @param sk_ai SK_ai, or SKEYID_a for IKEv1
|
||||||
|
* @param sk_ar SK_ar
|
||||||
|
*/
|
||||||
|
void (*ike_derived_keys)(bus_t *this, chunk_t sk_ei, chunk_t sk_er,
|
||||||
|
chunk_t sk_ai, chunk_t sk_ar);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CHILD_SA keymat hook.
|
* CHILD_SA keymat hook.
|
||||||
*
|
*
|
||||||
* @param child_sa CHILD_SA this keymat is used for
|
* @param child_sa CHILD_SA this keymat is used for
|
||||||
* @param initiator initiator of the CREATE_CHILD_SA exchange
|
* @param initiator initiator of the CREATE_CHILD_SA exchange
|
||||||
* @param dh diffie hellman shared secret
|
* @param dh diffie hellman shared secret
|
||||||
* @param nonce_i initiators nonce
|
* @param nonce_i initiator's nonce
|
||||||
* @param nonce_r responders nonce
|
* @param nonce_r responder's nonce
|
||||||
*/
|
*/
|
||||||
void (*child_keys)(bus_t *this, child_sa_t *child_sa, bool initiator,
|
void (*child_keys)(bus_t *this, child_sa_t *child_sa, bool initiator,
|
||||||
diffie_hellman_t *dh, chunk_t nonce_i, chunk_t nonce_r);
|
diffie_hellman_t *dh, chunk_t nonce_i, chunk_t nonce_r);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CHILD_SA derived keys hook.
|
||||||
|
*
|
||||||
|
* @param child_sa CHILD_SA these keys are used for
|
||||||
|
* @param initiator initiator of the CREATE_CHILD_SA exchange
|
||||||
|
* @param encr_i initiator's encryption key
|
||||||
|
* @param encr_o responder's encryption key
|
||||||
|
* @param integ_i initiator's integrity key
|
||||||
|
* @param integ_r responder's integrity key
|
||||||
|
*/
|
||||||
|
void (*child_derived_keys)(bus_t *this, child_sa_t *child_sa,
|
||||||
|
bool initiator, chunk_t encr_i, chunk_t encr_r,
|
||||||
|
chunk_t integ_i, chunk_t integ_r);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* IKE_SA up/down hook.
|
* IKE_SA up/down hook.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2011-2015 Tobias Brunner
|
* Copyright (C) 2011-2016 Tobias Brunner
|
||||||
* Copyright (C) 2009 Martin Willi
|
* Copyright (C) 2009 Martin Willi
|
||||||
* Hochschule fuer Technik Rapperswil
|
* Hochschule fuer Technik Rapperswil
|
||||||
*
|
*
|
||||||
@@ -84,8 +84,8 @@ struct listener_t {
|
|||||||
* @param ike_sa IKE_SA this keymat belongs to
|
* @param ike_sa IKE_SA this keymat belongs to
|
||||||
* @param dh diffie hellman shared secret
|
* @param dh diffie hellman shared secret
|
||||||
* @param dh_other others DH public value (IKEv1 only)
|
* @param dh_other others DH public value (IKEv1 only)
|
||||||
* @param nonce_i initiators nonce
|
* @param nonce_i initiator's nonce
|
||||||
* @param nonce_r responders nonce
|
* @param nonce_r responder's nonce
|
||||||
* @param rekey IKE_SA we are rekeying, if any (IKEv2 only)
|
* @param rekey IKE_SA we are rekeying, if any (IKEv2 only)
|
||||||
* @param shared shared key used for key derivation (IKEv1-PSK only)
|
* @param shared shared key used for key derivation (IKEv1-PSK only)
|
||||||
* @return TRUE to stay registered, FALSE to unregister
|
* @return TRUE to stay registered, FALSE to unregister
|
||||||
@@ -94,6 +94,18 @@ struct listener_t {
|
|||||||
chunk_t dh_other, chunk_t nonce_i, chunk_t nonce_r,
|
chunk_t dh_other, chunk_t nonce_i, chunk_t nonce_r,
|
||||||
ike_sa_t *rekey, shared_key_t *shared);
|
ike_sa_t *rekey, shared_key_t *shared);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hook called with derived IKE_SA keys.
|
||||||
|
*
|
||||||
|
* @param ike_sa IKE_SA these keys belong to
|
||||||
|
* @param sk_ei SK_ei, or Ka for IKEv1
|
||||||
|
* @param sk_er SK_er
|
||||||
|
* @param sk_ai SK_ai, or SKEYID_a for IKEv1
|
||||||
|
* @param sk_ar SK_ar
|
||||||
|
*/
|
||||||
|
bool (*ike_derived_keys)(listener_t *this, ike_sa_t *ike_sa, chunk_t sk_ei,
|
||||||
|
chunk_t sk_er, chunk_t sk_ai, chunk_t sk_ar);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hook called with CHILD_SA key material.
|
* Hook called with CHILD_SA key material.
|
||||||
*
|
*
|
||||||
@@ -101,14 +113,30 @@ struct listener_t {
|
|||||||
* @param child_sa CHILD_SA this keymat is used for
|
* @param child_sa CHILD_SA this keymat is used for
|
||||||
* @param initiator initiator of the CREATE_CHILD_SA exchange
|
* @param initiator initiator of the CREATE_CHILD_SA exchange
|
||||||
* @param dh diffie hellman shared secret
|
* @param dh diffie hellman shared secret
|
||||||
* @param nonce_i initiators nonce
|
* @param nonce_i initiator's nonce
|
||||||
* @param nonce_r responders nonce
|
* @param nonce_r responder's nonce
|
||||||
* @return TRUE to stay registered, FALSE to unregister
|
* @return TRUE to stay registered, FALSE to unregister
|
||||||
*/
|
*/
|
||||||
bool (*child_keys)(listener_t *this, ike_sa_t *ike_sa, child_sa_t *child_sa,
|
bool (*child_keys)(listener_t *this, ike_sa_t *ike_sa, child_sa_t *child_sa,
|
||||||
bool initiator, diffie_hellman_t *dh,
|
bool initiator, diffie_hellman_t *dh,
|
||||||
chunk_t nonce_i, chunk_t nonce_r);
|
chunk_t nonce_i, chunk_t nonce_r);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hook called with derived CHILD_SA keys.
|
||||||
|
*
|
||||||
|
* @param ike_sa IKE_SA the child sa belongs to
|
||||||
|
* @param child_sa CHILD_SA these keys are used for
|
||||||
|
* @param initiator initiator of the CREATE_CHILD_SA exchange
|
||||||
|
* @param encr_i initiator's encryption key
|
||||||
|
* @param encr_o responder's encryption key
|
||||||
|
* @param integ_i initiator's integrity key
|
||||||
|
* @param integ_r responder's integrity key
|
||||||
|
*/
|
||||||
|
bool (*child_derived_keys)(listener_t *this, ike_sa_t *ike_sa,
|
||||||
|
child_sa_t *child_sa, bool initiator,
|
||||||
|
chunk_t encr_i, chunk_t encr_r,
|
||||||
|
chunk_t integ_i, chunk_t integ_r);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hook called if an IKE_SA gets up or down.
|
* Hook called if an IKE_SA gets up or down.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -74,11 +74,6 @@ struct private_keymat_v1_t {
|
|||||||
*/
|
*/
|
||||||
hasher_t *hasher;
|
hasher_t *hasher;
|
||||||
|
|
||||||
/**
|
|
||||||
* Key used for authentication during main mode
|
|
||||||
*/
|
|
||||||
chunk_t skeyid;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Key to derive key material from for non-ISAKMP SAs, rekeying
|
* Key to derive key material from for non-ISAKMP SAs, rekeying
|
||||||
*/
|
*/
|
||||||
@@ -269,12 +264,12 @@ static bool expand_skeyid_e(chunk_t skeyid_e, size_t key_size, prf_t *prf,
|
|||||||
* Create a simple implementation of the aead_t interface which only encrypts
|
* Create a simple implementation of the aead_t interface which only encrypts
|
||||||
* or decrypts data.
|
* or decrypts data.
|
||||||
*/
|
*/
|
||||||
static aead_t *create_aead(proposal_t *proposal, prf_t *prf, chunk_t skeyid_e)
|
static aead_t *create_aead(proposal_t *proposal, prf_t *prf, chunk_t skeyid_e,
|
||||||
|
chunk_t *ka)
|
||||||
{
|
{
|
||||||
private_aead_t *this;
|
private_aead_t *this;
|
||||||
uint16_t alg, key_size;
|
uint16_t alg, key_size;
|
||||||
crypter_t *crypter;
|
crypter_t *crypter;
|
||||||
chunk_t ka;
|
|
||||||
|
|
||||||
if (!proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM, &alg,
|
if (!proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM, &alg,
|
||||||
&key_size))
|
&key_size))
|
||||||
@@ -292,17 +287,16 @@ static aead_t *create_aead(proposal_t *proposal, prf_t *prf, chunk_t skeyid_e)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
key_size = crypter->get_key_size(crypter);
|
key_size = crypter->get_key_size(crypter);
|
||||||
if (!expand_skeyid_e(skeyid_e, crypter->get_key_size(crypter), prf, &ka))
|
if (!expand_skeyid_e(skeyid_e, crypter->get_key_size(crypter), prf, ka))
|
||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
DBG4(DBG_IKE, "encryption key Ka %B", &ka);
|
DBG4(DBG_IKE, "encryption key Ka %B", ka);
|
||||||
if (!crypter->set_key(crypter, ka))
|
if (!crypter->set_key(crypter, *ka))
|
||||||
{
|
{
|
||||||
chunk_clear(&ka);
|
chunk_clear(ka);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
chunk_clear(&ka);
|
|
||||||
|
|
||||||
INIT(this,
|
INIT(this,
|
||||||
.aead = {
|
.aead = {
|
||||||
@@ -392,7 +386,7 @@ METHOD(keymat_v1_t, derive_ike_keys, bool,
|
|||||||
auth_method_t auth, shared_key_t *shared_key)
|
auth_method_t auth, shared_key_t *shared_key)
|
||||||
{
|
{
|
||||||
chunk_t g_xy, g_xi, g_xr, dh_me, spi_i, spi_r, nonces, data, skeyid_e;
|
chunk_t g_xy, g_xi, g_xr, dh_me, spi_i, spi_r, nonces, data, skeyid_e;
|
||||||
chunk_t skeyid;
|
chunk_t skeyid, ka;
|
||||||
uint16_t alg;
|
uint16_t alg;
|
||||||
|
|
||||||
spi_i = chunk_alloca(sizeof(uint64_t));
|
spi_i = chunk_alloca(sizeof(uint64_t));
|
||||||
@@ -550,11 +544,14 @@ METHOD(keymat_v1_t, derive_ike_keys, bool,
|
|||||||
}
|
}
|
||||||
chunk_clear(&skeyid);
|
chunk_clear(&skeyid);
|
||||||
|
|
||||||
this->aead = create_aead(proposal, this->prf, skeyid_e);
|
this->aead = create_aead(proposal, this->prf, skeyid_e, &ka);
|
||||||
if (!this->aead)
|
if (!this->aead)
|
||||||
{
|
{
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
charon->bus->ike_derived_keys(charon->bus, ka, chunk_empty, this->skeyid_a,
|
||||||
|
chunk_empty);
|
||||||
|
chunk_clear(&ka);
|
||||||
if (!this->hasher && !this->public.create_hasher(&this->public, proposal))
|
if (!this->hasher && !this->public.create_hasher(&this->public, proposal))
|
||||||
{
|
{
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|||||||
@@ -348,10 +348,6 @@ static bool install(private_quick_mode_t *this)
|
|||||||
this->initiator, FALSE, FALSE, tsr, tsi);
|
this->initiator, FALSE, FALSE, tsr, tsi);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
chunk_clear(&integ_i);
|
|
||||||
chunk_clear(&integ_r);
|
|
||||||
chunk_clear(&encr_i);
|
|
||||||
chunk_clear(&encr_r);
|
|
||||||
|
|
||||||
if (status_i != SUCCESS || status_o != SUCCESS)
|
if (status_i != SUCCESS || status_o != SUCCESS)
|
||||||
{
|
{
|
||||||
@@ -361,22 +357,38 @@ static bool install(private_quick_mode_t *this)
|
|||||||
(status_o != SUCCESS) ? "outbound " : "");
|
(status_o != SUCCESS) ? "outbound " : "");
|
||||||
tsi->destroy_offset(tsi, offsetof(traffic_selector_t, destroy));
|
tsi->destroy_offset(tsi, offsetof(traffic_selector_t, destroy));
|
||||||
tsr->destroy_offset(tsr, offsetof(traffic_selector_t, destroy));
|
tsr->destroy_offset(tsr, offsetof(traffic_selector_t, destroy));
|
||||||
return FALSE;
|
status = FAILED;
|
||||||
}
|
|
||||||
|
|
||||||
if (this->initiator)
|
|
||||||
{
|
|
||||||
status = this->child_sa->add_policies(this->child_sa, tsi, tsr);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
status = this->child_sa->add_policies(this->child_sa, tsr, tsi);
|
if (this->initiator)
|
||||||
|
{
|
||||||
|
status = this->child_sa->add_policies(this->child_sa, tsi, tsr);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
status = this->child_sa->add_policies(this->child_sa, tsr, tsi);
|
||||||
|
}
|
||||||
|
tsi->destroy_offset(tsi, offsetof(traffic_selector_t, destroy));
|
||||||
|
tsr->destroy_offset(tsr, offsetof(traffic_selector_t, destroy));
|
||||||
|
if (status != SUCCESS)
|
||||||
|
{
|
||||||
|
DBG1(DBG_IKE, "unable to install IPsec policies (SPD) in kernel");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
charon->bus->child_derived_keys(charon->bus, this->child_sa,
|
||||||
|
this->initiator, encr_i, encr_r,
|
||||||
|
integ_i, integ_r);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
tsi->destroy_offset(tsi, offsetof(traffic_selector_t, destroy));
|
chunk_clear(&integ_i);
|
||||||
tsr->destroy_offset(tsr, offsetof(traffic_selector_t, destroy));
|
chunk_clear(&integ_r);
|
||||||
|
chunk_clear(&encr_i);
|
||||||
|
chunk_clear(&encr_r);
|
||||||
|
|
||||||
if (status != SUCCESS)
|
if (status != SUCCESS)
|
||||||
{
|
{
|
||||||
DBG1(DBG_IKE, "unable to install IPsec policies (SPD) in kernel");
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -103,7 +103,7 @@ static bool derive_ike_aead(private_keymat_v2_t *this, uint16_t alg,
|
|||||||
uint16_t key_size, prf_plus_t *prf_plus)
|
uint16_t key_size, prf_plus_t *prf_plus)
|
||||||
{
|
{
|
||||||
aead_t *aead_i, *aead_r;
|
aead_t *aead_i, *aead_r;
|
||||||
chunk_t key = chunk_empty;
|
chunk_t sk_ei = chunk_empty, sk_er = chunk_empty;
|
||||||
u_int salt_size;
|
u_int salt_size;
|
||||||
|
|
||||||
switch (alg)
|
switch (alg)
|
||||||
@@ -146,23 +146,22 @@ static bool derive_ike_aead(private_keymat_v2_t *this, uint16_t alg,
|
|||||||
{
|
{
|
||||||
goto failure;
|
goto failure;
|
||||||
}
|
}
|
||||||
if (!prf_plus->allocate_bytes(prf_plus, key_size, &key))
|
if (!prf_plus->allocate_bytes(prf_plus, key_size, &sk_ei))
|
||||||
{
|
{
|
||||||
goto failure;
|
goto failure;
|
||||||
}
|
}
|
||||||
DBG4(DBG_IKE, "Sk_ei secret %B", &key);
|
DBG4(DBG_IKE, "Sk_ei secret %B", &sk_ei);
|
||||||
if (!aead_i->set_key(aead_i, key))
|
if (!aead_i->set_key(aead_i, sk_ei))
|
||||||
{
|
{
|
||||||
goto failure;
|
goto failure;
|
||||||
}
|
}
|
||||||
chunk_clear(&key);
|
|
||||||
|
|
||||||
if (!prf_plus->allocate_bytes(prf_plus, key_size, &key))
|
if (!prf_plus->allocate_bytes(prf_plus, key_size, &sk_er))
|
||||||
{
|
{
|
||||||
goto failure;
|
goto failure;
|
||||||
}
|
}
|
||||||
DBG4(DBG_IKE, "Sk_er secret %B", &key);
|
DBG4(DBG_IKE, "Sk_er secret %B", &sk_er);
|
||||||
if (!aead_r->set_key(aead_r, key))
|
if (!aead_r->set_key(aead_r, sk_er))
|
||||||
{
|
{
|
||||||
goto failure;
|
goto failure;
|
||||||
}
|
}
|
||||||
@@ -178,11 +177,14 @@ static bool derive_ike_aead(private_keymat_v2_t *this, uint16_t alg,
|
|||||||
this->aead_out = aead_r;
|
this->aead_out = aead_r;
|
||||||
}
|
}
|
||||||
aead_i = aead_r = NULL;
|
aead_i = aead_r = NULL;
|
||||||
|
charon->bus->ike_derived_keys(charon->bus, sk_ei, sk_er, chunk_empty,
|
||||||
|
chunk_empty);
|
||||||
|
|
||||||
failure:
|
failure:
|
||||||
DESTROY_IF(aead_i);
|
DESTROY_IF(aead_i);
|
||||||
DESTROY_IF(aead_r);
|
DESTROY_IF(aead_r);
|
||||||
chunk_clear(&key);
|
chunk_clear(&sk_ei);
|
||||||
|
chunk_clear(&sk_er);
|
||||||
return this->aead_in && this->aead_out;
|
return this->aead_in && this->aead_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -196,7 +198,8 @@ static bool derive_ike_traditional(private_keymat_v2_t *this, uint16_t enc_alg,
|
|||||||
signer_t *signer_i, *signer_r;
|
signer_t *signer_i, *signer_r;
|
||||||
iv_gen_t *ivg_i, *ivg_r;
|
iv_gen_t *ivg_i, *ivg_r;
|
||||||
size_t key_size;
|
size_t key_size;
|
||||||
chunk_t key = chunk_empty;
|
chunk_t sk_ei = chunk_empty, sk_er = chunk_empty,
|
||||||
|
sk_ai = chunk_empty, sk_ar = chunk_empty;
|
||||||
|
|
||||||
signer_i = lib->crypto->create_signer(lib->crypto, int_alg);
|
signer_i = lib->crypto->create_signer(lib->crypto, int_alg);
|
||||||
signer_r = lib->crypto->create_signer(lib->crypto, int_alg);
|
signer_r = lib->crypto->create_signer(lib->crypto, int_alg);
|
||||||
@@ -220,48 +223,45 @@ static bool derive_ike_traditional(private_keymat_v2_t *this, uint16_t enc_alg,
|
|||||||
/* SK_ai/SK_ar used for integrity protection */
|
/* SK_ai/SK_ar used for integrity protection */
|
||||||
key_size = signer_i->get_key_size(signer_i);
|
key_size = signer_i->get_key_size(signer_i);
|
||||||
|
|
||||||
if (!prf_plus->allocate_bytes(prf_plus, key_size, &key))
|
if (!prf_plus->allocate_bytes(prf_plus, key_size, &sk_ai))
|
||||||
{
|
{
|
||||||
goto failure;
|
goto failure;
|
||||||
}
|
}
|
||||||
DBG4(DBG_IKE, "Sk_ai secret %B", &key);
|
DBG4(DBG_IKE, "Sk_ai secret %B", &sk_ai);
|
||||||
if (!signer_i->set_key(signer_i, key))
|
if (!signer_i->set_key(signer_i, sk_ai))
|
||||||
{
|
{
|
||||||
goto failure;
|
goto failure;
|
||||||
}
|
}
|
||||||
chunk_clear(&key);
|
|
||||||
|
|
||||||
if (!prf_plus->allocate_bytes(prf_plus, key_size, &key))
|
if (!prf_plus->allocate_bytes(prf_plus, key_size, &sk_ar))
|
||||||
{
|
{
|
||||||
goto failure;
|
goto failure;
|
||||||
}
|
}
|
||||||
DBG4(DBG_IKE, "Sk_ar secret %B", &key);
|
DBG4(DBG_IKE, "Sk_ar secret %B", &sk_ar);
|
||||||
if (!signer_r->set_key(signer_r, key))
|
if (!signer_r->set_key(signer_r, sk_ar))
|
||||||
{
|
{
|
||||||
goto failure;
|
goto failure;
|
||||||
}
|
}
|
||||||
chunk_clear(&key);
|
|
||||||
|
|
||||||
/* SK_ei/SK_er used for encryption */
|
/* SK_ei/SK_er used for encryption */
|
||||||
key_size = crypter_i->get_key_size(crypter_i);
|
key_size = crypter_i->get_key_size(crypter_i);
|
||||||
|
|
||||||
if (!prf_plus->allocate_bytes(prf_plus, key_size, &key))
|
if (!prf_plus->allocate_bytes(prf_plus, key_size, &sk_ei))
|
||||||
{
|
{
|
||||||
goto failure;
|
goto failure;
|
||||||
}
|
}
|
||||||
DBG4(DBG_IKE, "Sk_ei secret %B", &key);
|
DBG4(DBG_IKE, "Sk_ei secret %B", &sk_ei);
|
||||||
if (!crypter_i->set_key(crypter_i, key))
|
if (!crypter_i->set_key(crypter_i, sk_ei))
|
||||||
{
|
{
|
||||||
goto failure;
|
goto failure;
|
||||||
}
|
}
|
||||||
chunk_clear(&key);
|
|
||||||
|
|
||||||
if (!prf_plus->allocate_bytes(prf_plus, key_size, &key))
|
if (!prf_plus->allocate_bytes(prf_plus, key_size, &sk_er))
|
||||||
{
|
{
|
||||||
goto failure;
|
goto failure;
|
||||||
}
|
}
|
||||||
DBG4(DBG_IKE, "Sk_er secret %B", &key);
|
DBG4(DBG_IKE, "Sk_er secret %B", &sk_er);
|
||||||
if (!crypter_r->set_key(crypter_r, key))
|
if (!crypter_r->set_key(crypter_r, sk_er))
|
||||||
{
|
{
|
||||||
goto failure;
|
goto failure;
|
||||||
}
|
}
|
||||||
@@ -284,9 +284,13 @@ static bool derive_ike_traditional(private_keymat_v2_t *this, uint16_t enc_alg,
|
|||||||
}
|
}
|
||||||
signer_i = signer_r = NULL;
|
signer_i = signer_r = NULL;
|
||||||
crypter_i = crypter_r = NULL;
|
crypter_i = crypter_r = NULL;
|
||||||
|
charon->bus->ike_derived_keys(charon->bus, sk_ei, sk_er, sk_ai, sk_ar);
|
||||||
|
|
||||||
failure:
|
failure:
|
||||||
chunk_clear(&key);
|
chunk_clear(&sk_ai);
|
||||||
|
chunk_clear(&sk_ar);
|
||||||
|
chunk_clear(&sk_ei);
|
||||||
|
chunk_clear(&sk_er);
|
||||||
DESTROY_IF(signer_i);
|
DESTROY_IF(signer_i);
|
||||||
DESTROY_IF(signer_r);
|
DESTROY_IF(signer_r);
|
||||||
DESTROY_IF(crypter_i);
|
DESTROY_IF(crypter_i);
|
||||||
|
|||||||
@@ -666,10 +666,6 @@ static status_t select_and_install(private_child_create_t *this,
|
|||||||
FALSE, this->tfcv3, my_ts, other_ts);
|
FALSE, this->tfcv3, my_ts, other_ts);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
chunk_clear(&integ_i);
|
|
||||||
chunk_clear(&integ_r);
|
|
||||||
chunk_clear(&encr_i);
|
|
||||||
chunk_clear(&encr_r);
|
|
||||||
|
|
||||||
if (status_i != SUCCESS || status_o != SUCCESS)
|
if (status_i != SUCCESS || status_o != SUCCESS)
|
||||||
{
|
{
|
||||||
@@ -679,41 +675,62 @@ static status_t select_and_install(private_child_create_t *this,
|
|||||||
(status_o != SUCCESS) ? "outbound " : "");
|
(status_o != SUCCESS) ? "outbound " : "");
|
||||||
charon->bus->alert(charon->bus, ALERT_INSTALL_CHILD_SA_FAILED,
|
charon->bus->alert(charon->bus, ALERT_INSTALL_CHILD_SA_FAILED,
|
||||||
this->child_sa);
|
this->child_sa);
|
||||||
return FAILED;
|
status = FAILED;
|
||||||
}
|
|
||||||
|
|
||||||
if (this->initiator)
|
|
||||||
{
|
|
||||||
status = this->child_sa->add_policies(this->child_sa, my_ts, other_ts);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* use a copy of the traffic selectors, as the POST hook should not
|
if (this->initiator)
|
||||||
* change payloads */
|
|
||||||
my_ts = this->tsr->clone_offset(this->tsr,
|
|
||||||
offsetof(traffic_selector_t, clone));
|
|
||||||
other_ts = this->tsi->clone_offset(this->tsi,
|
|
||||||
offsetof(traffic_selector_t, clone));
|
|
||||||
charon->bus->narrow(charon->bus, this->child_sa,
|
|
||||||
NARROW_RESPONDER_POST, my_ts, other_ts);
|
|
||||||
if (my_ts->get_count(my_ts) == 0 || other_ts->get_count(other_ts) == 0)
|
|
||||||
{
|
{
|
||||||
status = FAILED;
|
status = this->child_sa->add_policies(this->child_sa,
|
||||||
|
my_ts, other_ts);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
status = this->child_sa->add_policies(this->child_sa,
|
/* use a copy of the traffic selectors, as the POST hook should not
|
||||||
my_ts, other_ts);
|
* change payloads */
|
||||||
|
my_ts = this->tsr->clone_offset(this->tsr,
|
||||||
|
offsetof(traffic_selector_t, clone));
|
||||||
|
other_ts = this->tsi->clone_offset(this->tsi,
|
||||||
|
offsetof(traffic_selector_t, clone));
|
||||||
|
charon->bus->narrow(charon->bus, this->child_sa,
|
||||||
|
NARROW_RESPONDER_POST, my_ts, other_ts);
|
||||||
|
if (my_ts->get_count(my_ts) == 0 ||
|
||||||
|
other_ts->get_count(other_ts) == 0)
|
||||||
|
{
|
||||||
|
status = FAILED;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
status = this->child_sa->add_policies(this->child_sa,
|
||||||
|
my_ts, other_ts);
|
||||||
|
}
|
||||||
|
my_ts->destroy_offset(my_ts,
|
||||||
|
offsetof(traffic_selector_t, destroy));
|
||||||
|
other_ts->destroy_offset(other_ts,
|
||||||
|
offsetof(traffic_selector_t, destroy));
|
||||||
|
}
|
||||||
|
if (status != SUCCESS)
|
||||||
|
{
|
||||||
|
DBG1(DBG_IKE, "unable to install IPsec policies (SPD) in kernel");
|
||||||
|
charon->bus->alert(charon->bus, ALERT_INSTALL_CHILD_POLICY_FAILED,
|
||||||
|
this->child_sa);
|
||||||
|
status = NOT_FOUND;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
charon->bus->child_derived_keys(charon->bus, this->child_sa,
|
||||||
|
this->initiator, encr_i, encr_r,
|
||||||
|
integ_i, integ_r);
|
||||||
}
|
}
|
||||||
my_ts->destroy_offset(my_ts, offsetof(traffic_selector_t, destroy));
|
|
||||||
other_ts->destroy_offset(other_ts, offsetof(traffic_selector_t, destroy));
|
|
||||||
}
|
}
|
||||||
|
chunk_clear(&integ_i);
|
||||||
|
chunk_clear(&integ_r);
|
||||||
|
chunk_clear(&encr_i);
|
||||||
|
chunk_clear(&encr_r);
|
||||||
|
|
||||||
if (status != SUCCESS)
|
if (status != SUCCESS)
|
||||||
{
|
{
|
||||||
DBG1(DBG_IKE, "unable to install IPsec policies (SPD) in kernel");
|
return status;
|
||||||
charon->bus->alert(charon->bus, ALERT_INSTALL_CHILD_POLICY_FAILED,
|
|
||||||
this->child_sa);
|
|
||||||
return NOT_FOUND;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
charon->bus->child_keys(charon->bus, this->child_sa, this->initiator,
|
charon->bus->child_keys(charon->bus, this->child_sa, this->initiator,
|
||||||
|
|||||||
Reference in New Issue
Block a user