- refactored ike proposal
- uses now proposal_t, wich is also used by child proposals - ike key derivation refactored - crypter_t api has get_key_size now - some other improvements here and there
This commit is contained in:
@@ -116,6 +116,7 @@ static chunk_t allocate_octets(private_authenticator_t *this,
|
||||
id_payload_t *my_id,
|
||||
bool initiator)
|
||||
{
|
||||
prf_t *prf;
|
||||
chunk_t id_chunk = my_id->get_data(my_id);
|
||||
u_int8_t id_with_header[4 + id_chunk.len];
|
||||
/*
|
||||
@@ -139,23 +140,22 @@ static chunk_t allocate_octets(private_authenticator_t *this,
|
||||
|
||||
if (initiator)
|
||||
{
|
||||
this->prf->set_key(this->prf,this->ike_sa->get_key_pi(this->ike_sa));
|
||||
prf = this->ike_sa->get_prf_auth_i(this->ike_sa);
|
||||
}
|
||||
else
|
||||
{
|
||||
this->prf->set_key(this->prf,this->ike_sa->get_key_pr(this->ike_sa));
|
||||
prf = this->ike_sa->get_prf_auth_r(this->ike_sa);
|
||||
}
|
||||
|
||||
|
||||
/* 4 bytes are id type and reserved fields of id payload */
|
||||
octets.len = last_message.len + other_nonce.len + this->prf->get_block_size(this->prf);
|
||||
octets.len = last_message.len + other_nonce.len + prf->get_block_size(prf);
|
||||
octets.ptr = allocator_alloc(octets.len);
|
||||
current_pos = octets.ptr;
|
||||
memcpy(current_pos,last_message.ptr,last_message.len);
|
||||
current_pos += last_message.len;
|
||||
memcpy(current_pos,other_nonce.ptr,other_nonce.len);
|
||||
current_pos += other_nonce.len;
|
||||
this->prf->get_bytes(this->prf,id_with_header_chunk,current_pos);
|
||||
prf->get_bytes(prf, id_with_header_chunk, current_pos);
|
||||
|
||||
this->logger->log_chunk(this->logger,RAW | LEVEL2, "Octets (Mesage + Nonce + prf(Sk_px,Idx)",&octets);
|
||||
return octets;
|
||||
|
||||
@@ -70,7 +70,7 @@ static void destroy(private_child_sa_t *this)
|
||||
/*
|
||||
* Described in header.
|
||||
*/
|
||||
child_sa_t * child_sa_create(child_proposal_t *proposal, prf_plus_t *prf_plus)
|
||||
child_sa_t * child_sa_create(proposal_t *proposal, prf_plus_t *prf_plus)
|
||||
{
|
||||
private_child_sa_t *this = allocator_alloc_thing(private_child_sa_t);
|
||||
u_int i;
|
||||
|
||||
@@ -67,6 +67,6 @@ struct child_sa_t {
|
||||
* @return child_sa_t object
|
||||
* @ingroup sa
|
||||
*/
|
||||
child_sa_t * child_sa_create(child_proposal_t *proposal, prf_plus_t *prf_plus);
|
||||
child_sa_t * child_sa_create(proposal_t *proposal, prf_plus_t *prf_plus);
|
||||
|
||||
#endif /*_CHILD_SA_H_*/
|
||||
|
||||
+202
-255
@@ -57,15 +57,6 @@ struct private_ike_sa_t {
|
||||
* Protected part of a ike_sa_t object.
|
||||
*/
|
||||
protected_ike_sa_t protected;
|
||||
|
||||
/**
|
||||
* Resends the last sent reply.
|
||||
*
|
||||
* @param this calling object
|
||||
*/
|
||||
status_t (*resend_last_reply) (private_ike_sa_t *this);
|
||||
|
||||
/* private values */
|
||||
|
||||
/**
|
||||
* Identifier for the current IKE_SA.
|
||||
@@ -152,112 +143,43 @@ struct private_ike_sa_t {
|
||||
|
||||
/**
|
||||
* Crypter object for initiator.
|
||||
*
|
||||
* Gets set in states:
|
||||
* - IKE_SA_INIT_REQUESTED
|
||||
* - RESPONDER_INIT
|
||||
*
|
||||
* Available in states:
|
||||
* - IKE_SA_INIT_RESPONDED
|
||||
* - IKE_AUTH_REQUESTED
|
||||
* -IKE_SA_ESTABLISHED
|
||||
*/
|
||||
crypter_t *crypter_initiator;
|
||||
|
||||
/**
|
||||
* Crypter object for responder.
|
||||
*
|
||||
* Gets set in states:
|
||||
* - IKE_SA_INIT_REQUESTED
|
||||
* - RESPONDER_INIT
|
||||
*
|
||||
* Available in states:
|
||||
* - IKE_SA_INIT_RESPONDED
|
||||
* - IKE_AUTH_REQUESTED
|
||||
* -IKE_SA_ESTABLISHED
|
||||
*/
|
||||
crypter_t *crypter_responder;
|
||||
|
||||
/**
|
||||
* Signer object for initiator.
|
||||
*
|
||||
* Gets set in states:
|
||||
* - IKE_SA_INIT_REQUESTED
|
||||
* - RESPONDER_INIT
|
||||
*
|
||||
* Available in states:
|
||||
* - IKE_SA_INIT_RESPONDED
|
||||
* - IKE_AUTH_REQUESTED
|
||||
* -IKE_SA_ESTABLISHED
|
||||
*/
|
||||
signer_t *signer_initiator;
|
||||
|
||||
/**
|
||||
* Signer object for responder.
|
||||
*
|
||||
* Gets set in states:
|
||||
* - IKE_SA_INIT_REQUESTED
|
||||
* - RESPONDER_INIT
|
||||
*
|
||||
* Available in states:
|
||||
* - IKE_SA_INIT_RESPONDED
|
||||
* - IKE_AUTH_REQUESTED
|
||||
* -IKE_SA_ESTABLISHED
|
||||
*/
|
||||
signer_t *signer_responder;
|
||||
|
||||
/**
|
||||
* Prf function.
|
||||
*
|
||||
* Gets set in states:
|
||||
* - IKE_SA_INIT_REQUESTED
|
||||
* - RESPONDER_INIT
|
||||
*
|
||||
* Available in states:
|
||||
* - IKE_SA_INIT_RESPONDED
|
||||
* - IKE_AUTH_REQUESTED
|
||||
* -IKE_SA_ESTABLISHED
|
||||
* Multi purpose prf, set key, use it, forget it
|
||||
*/
|
||||
prf_t *prf;
|
||||
|
||||
/**
|
||||
* Prf function for derivating keymat child SAs
|
||||
*
|
||||
* Gets set in states:
|
||||
* - IKE_SA_INIT_REQUESTED
|
||||
* - RESPONDER_INIT
|
||||
*
|
||||
* Available in states:
|
||||
* - IKE_SA_INIT_RESPONDED
|
||||
* - IKE_AUTH_REQUESTED
|
||||
* -IKE_SA_ESTABLISHED
|
||||
*/
|
||||
prf_t *child_prf;
|
||||
|
||||
/**
|
||||
* Shared secrets which have to be stored.
|
||||
*
|
||||
* Are getting set in states:
|
||||
* - IKE_SA_INIT_REQUESTED
|
||||
* - RESPONDER_INIT
|
||||
*
|
||||
* Available in states:
|
||||
* - IKE_SA_INIT_RESPONDED
|
||||
* - IKE_AUTH_REQUESTED
|
||||
* -IKE_SA_ESTABLISHED
|
||||
* PRF, with key set to pi_key, used for authentication
|
||||
*/
|
||||
struct {
|
||||
/**
|
||||
* Key for generating auth payload (initiator)
|
||||
*/
|
||||
chunk_t pi_key;
|
||||
prf_t *prf_auth_i;
|
||||
|
||||
/**
|
||||
* Key for generating auth payload (responder)
|
||||
*/
|
||||
chunk_t pr_key;
|
||||
|
||||
} secrets;
|
||||
/**
|
||||
* PRF, with key set to pr_key, used for authentication
|
||||
*/
|
||||
prf_t *prf_auth_r;
|
||||
|
||||
/**
|
||||
* Next message id to receive.
|
||||
@@ -278,6 +200,13 @@ struct private_ike_sa_t {
|
||||
* A logger for this IKE_SA.
|
||||
*/
|
||||
logger_t *logger;
|
||||
|
||||
/**
|
||||
* Resends the last sent reply.
|
||||
*
|
||||
* @param this calling object
|
||||
*/
|
||||
status_t (*resend_last_reply) (private_ike_sa_t *this);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -440,103 +369,6 @@ static ike_sa_id_t* get_id(private_ike_sa_t *this)
|
||||
return this->ike_sa_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of protected_ike_sa_t.compute_secrets.
|
||||
*/
|
||||
static void compute_secrets(private_ike_sa_t *this,
|
||||
chunk_t dh_shared_secret,
|
||||
chunk_t initiator_nonce,
|
||||
chunk_t responder_nonce)
|
||||
{
|
||||
u_int8_t d_buffer[this->child_prf->get_block_size(this->child_prf)];
|
||||
chunk_t d_key = {ptr: d_buffer, len: sizeof(d_buffer)};
|
||||
u_int8_t ei_buffer[this->crypter_initiator->get_block_size(this->crypter_initiator)];
|
||||
chunk_t ei_key = {ptr: ei_buffer, len: sizeof(ei_buffer)};
|
||||
u_int8_t er_buffer[this->crypter_responder->get_block_size(this->crypter_responder)];
|
||||
chunk_t er_key = {ptr: er_buffer, len: sizeof(er_buffer)};
|
||||
u_int8_t ai_buffer[this->signer_initiator->get_key_size(this->signer_initiator)];
|
||||
chunk_t ai_key = {ptr: ai_buffer, len: sizeof(ai_buffer)};
|
||||
u_int8_t ar_buffer[this->signer_responder->get_key_size(this->signer_responder)];
|
||||
chunk_t ar_key = {ptr: ar_buffer, len: sizeof(ar_buffer)};
|
||||
u_int8_t concatenated_nonces_buffer[initiator_nonce.len + responder_nonce.len];
|
||||
chunk_t concatenated_nonces = {ptr: concatenated_nonces_buffer, len : sizeof(concatenated_nonces_buffer)};
|
||||
u_int8_t skeyseed_buffer[this->prf->get_block_size(this->prf)];
|
||||
chunk_t skeyseed = {ptr: skeyseed_buffer, len: sizeof(skeyseed_buffer)};
|
||||
u_int64_t initiator_spi;
|
||||
u_int64_t responder_spi;
|
||||
chunk_t prf_plus_seed;
|
||||
prf_plus_t *prf_plus;
|
||||
|
||||
/* first is initiator */
|
||||
memcpy(concatenated_nonces.ptr,initiator_nonce.ptr,initiator_nonce.len);
|
||||
/* second is responder */
|
||||
memcpy(concatenated_nonces.ptr + initiator_nonce.len,responder_nonce.ptr,responder_nonce.len);
|
||||
|
||||
this->logger->log_chunk(this->logger, RAW | LEVEL2, "Nonce data", &concatenated_nonces);
|
||||
|
||||
/* Status of set_key is not checked */
|
||||
this->prf->set_key(this->prf,concatenated_nonces);
|
||||
|
||||
this->prf->get_bytes(this->prf,dh_shared_secret,skeyseed_buffer);
|
||||
|
||||
prf_plus_seed.len = (initiator_nonce.len + responder_nonce.len + 16);
|
||||
prf_plus_seed.ptr = allocator_alloc(prf_plus_seed.len);
|
||||
|
||||
/* first is initiator */
|
||||
memcpy(prf_plus_seed.ptr,initiator_nonce.ptr,initiator_nonce.len);
|
||||
/* second is responder */
|
||||
memcpy(prf_plus_seed.ptr + initiator_nonce.len,responder_nonce.ptr,responder_nonce.len);
|
||||
/* third is initiator spi */
|
||||
initiator_spi = this->ike_sa_id->get_initiator_spi(this->ike_sa_id);
|
||||
memcpy(prf_plus_seed.ptr + initiator_nonce.len + responder_nonce.len,&initiator_spi,8);
|
||||
/* fourth is responder spi */
|
||||
responder_spi = this->ike_sa_id->get_responder_spi(this->ike_sa_id);
|
||||
memcpy(prf_plus_seed.ptr + initiator_nonce.len + responder_nonce.len + 8,&responder_spi,8);
|
||||
|
||||
this->logger->log_chunk(this->logger, PRIVATE | LEVEL1, "Keyseed", &skeyseed);
|
||||
this->logger->log_chunk(this->logger, PRIVATE | LEVEL1, "PRF+ Seed", &prf_plus_seed);
|
||||
|
||||
this->logger->log(this->logger, CONTROL | LEVEL2, "Set new key of prf object");
|
||||
this->prf->set_key(this->prf,skeyseed);
|
||||
|
||||
this->logger->log(this->logger, CONTROL | LEVEL2, "Create new prf+ object");
|
||||
prf_plus = prf_plus_create(this->prf, prf_plus_seed);
|
||||
allocator_free_chunk(&prf_plus_seed);
|
||||
|
||||
|
||||
prf_plus->get_bytes(prf_plus,d_key.len,d_buffer);
|
||||
this->logger->log_chunk(this->logger, PRIVATE, "Sk_d secret", &(d_key));
|
||||
this->child_prf->set_key(this->child_prf, d_key);
|
||||
|
||||
prf_plus->get_bytes(prf_plus,ai_key.len,ai_buffer);
|
||||
this->logger->log_chunk(this->logger, PRIVATE, "Sk_ai secret", &(ai_key));
|
||||
this->signer_initiator->set_key(this->signer_initiator,ai_key);
|
||||
|
||||
prf_plus->get_bytes(prf_plus,ar_key.len,ar_buffer);
|
||||
this->logger->log_chunk(this->logger, PRIVATE, "Sk_ar secret", &(ar_key));
|
||||
this->signer_responder->set_key(this->signer_responder,ar_key);
|
||||
|
||||
prf_plus->get_bytes(prf_plus,ei_key.len,ei_buffer);
|
||||
this->logger->log_chunk(this->logger, PRIVATE, "Sk_ei secret", &(ei_key));
|
||||
this->crypter_initiator->set_key(this->crypter_initiator,ei_key);
|
||||
|
||||
prf_plus->get_bytes(prf_plus,er_key.len,er_buffer);
|
||||
this->logger->log_chunk(this->logger, PRIVATE, "Sk_er secret", &(er_key));
|
||||
this->crypter_responder->set_key(this->crypter_responder,er_key);
|
||||
|
||||
prf_plus->allocate_bytes(prf_plus,
|
||||
this->crypter_responder->get_block_size(this->crypter_responder),
|
||||
&(this->secrets.pi_key));
|
||||
this->logger->log_chunk(this->logger, PRIVATE, "Sk_pi secret", &(this->secrets.pi_key));
|
||||
|
||||
prf_plus->allocate_bytes(prf_plus,
|
||||
this->crypter_responder->get_block_size(this->crypter_responder),
|
||||
&(this->secrets.pr_key));
|
||||
this->logger->log_chunk(this->logger, PRIVATE, "Sk_pr secret", &(this->secrets.pr_key));
|
||||
|
||||
prf_plus->destroy(prf_plus);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of private_ike_sa_t.resend_last_reply.
|
||||
*/
|
||||
@@ -680,97 +512,209 @@ static prf_t *get_child_prf (private_ike_sa_t *this)
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of protected_ike_sa_t.get_key_pr.
|
||||
* Implementation of protected_ike_sa_t.get_prf_auth_i.
|
||||
*/
|
||||
static chunk_t get_key_pr (private_ike_sa_t *this)
|
||||
static prf_t *get_prf_auth_i (private_ike_sa_t *this)
|
||||
{
|
||||
return this->secrets.pr_key;
|
||||
return this->prf_auth_i;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of protected_ike_sa_t.get_prf_auth_r.
|
||||
*/
|
||||
static prf_t *get_prf_auth_r (private_ike_sa_t *this)
|
||||
{
|
||||
return this->prf_auth_r;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Implementation of protected_ike_sa_t.get_key_pi.
|
||||
* Implementation of protected_ike_sa_t.build_transforms.
|
||||
*/
|
||||
static chunk_t get_key_pi (private_ike_sa_t *this)
|
||||
static status_t build_transforms(private_ike_sa_t *this, proposal_t *proposal, diffie_hellman_t *dh, chunk_t nonce_i, chunk_t nonce_r)
|
||||
{
|
||||
return this->secrets.pi_key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of protected_ike_sa_t.set_prf.
|
||||
*/
|
||||
static status_t create_transforms_from_proposal (private_ike_sa_t *this,ike_proposal_t *proposal)
|
||||
{
|
||||
this->logger->log(this->logger, CONTROL|LEVEL2, "Going to create transform objects for proposal");
|
||||
|
||||
this->logger->log(this->logger, CONTROL|LEVEL2, "Encryption algorithm: %s with keylength %d",
|
||||
mapping_find(encryption_algorithm_m,proposal->encryption_algorithm),
|
||||
proposal->encryption_algorithm_key_length);
|
||||
this->logger->log(this->logger, CONTROL|LEVEL2, "Integrity algorithm: %s with keylength %d",
|
||||
mapping_find(integrity_algorithm_m,proposal->integrity_algorithm),
|
||||
proposal->integrity_algorithm_key_length);
|
||||
this->logger->log(this->logger, CONTROL|LEVEL2, "PRF: %s with keylength %d",
|
||||
mapping_find(pseudo_random_function_m,proposal->pseudo_random_function),
|
||||
proposal->pseudo_random_function_key_length);
|
||||
chunk_t nonces, nonces_spis, skeyseed, key, secret;
|
||||
u_int64_t spi_i, spi_r;
|
||||
prf_plus_t *prf_plus;
|
||||
algorithm_t *algo;
|
||||
size_t key_size;
|
||||
|
||||
/*
|
||||
* Build the PRF+ instance for deriving keys
|
||||
*/
|
||||
if (this->prf != NULL)
|
||||
{
|
||||
this->prf->destroy(this->prf);
|
||||
}
|
||||
this->prf = prf_create(proposal->pseudo_random_function);
|
||||
proposal->get_algorithm(proposal, IKE, PSEUDO_RANDOM_FUNCTION, &algo);
|
||||
if (algo == NULL)
|
||||
{
|
||||
this->logger->log(this->logger, ERROR|LEVEL2, "No PRF algoithm selected!?");
|
||||
return FAILED;
|
||||
}
|
||||
this->prf = prf_create(algo->algorithm);
|
||||
if (this->prf == NULL)
|
||||
{
|
||||
this->logger->log(this->logger, ERROR|LEVEL1, "PRF %s not supported!",
|
||||
mapping_find(pseudo_random_function_m,proposal->pseudo_random_function));
|
||||
return FAILED;
|
||||
}
|
||||
this->child_prf = prf_create(proposal->pseudo_random_function);
|
||||
if (this->child_prf == NULL)
|
||||
{
|
||||
this->logger->log(this->logger, ERROR|LEVEL1, "PRF %s not supported!",
|
||||
mapping_find(pseudo_random_function_m,proposal->pseudo_random_function));
|
||||
this->logger->log(this->logger, ERROR|LEVEL1,
|
||||
"PSEUDO_RANDOM_FUNCTION %s not supported!",
|
||||
mapping_find(pseudo_random_function_m, algo->algorithm));
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
if (this->crypter_initiator != NULL)
|
||||
{
|
||||
this->crypter_initiator->destroy(this->crypter_initiator);
|
||||
}
|
||||
this->crypter_initiator = crypter_create(proposal->encryption_algorithm,
|
||||
proposal->encryption_algorithm_key_length);
|
||||
if (this->crypter_initiator == NULL)
|
||||
{
|
||||
this->logger->log(this->logger, ERROR|LEVEL1, "Encryption algorithm %s not supported!",
|
||||
mapping_find(encryption_algorithm_m,proposal->encryption_algorithm));
|
||||
return FAILED;
|
||||
}
|
||||
/* concatenate nonces = nonce_i | nonce_r */
|
||||
nonces = allocator_alloc_as_chunk(nonce_i.len + nonce_r.len);
|
||||
memcpy(nonces.ptr, nonce_i.ptr, nonce_i.len);
|
||||
memcpy(nonces.ptr + nonce_i.len, nonce_r.ptr, nonce_r.len);
|
||||
|
||||
if (this->crypter_responder != NULL)
|
||||
{
|
||||
this->crypter_responder->destroy(this->crypter_responder);
|
||||
}
|
||||
this->crypter_responder = crypter_create(proposal->encryption_algorithm,
|
||||
proposal->encryption_algorithm_key_length);
|
||||
/* check must not be done again */
|
||||
/* concatenate prf_seed = nonce_i | nonce_r | spi_i | spi_r */
|
||||
nonces_spis = allocator_alloc_as_chunk(nonces.len + 16);
|
||||
memcpy(nonces_spis.ptr, nonces.ptr, nonces.len);
|
||||
spi_i = this->ike_sa_id->get_initiator_spi(this->ike_sa_id);
|
||||
spi_r = this->ike_sa_id->get_responder_spi(this->ike_sa_id);
|
||||
memcpy(nonces_spis.ptr + nonces.len, &spi_i, 8);
|
||||
memcpy(nonces_spis.ptr + nonces.len + 8, &spi_r, 8);
|
||||
|
||||
/* SKEYSEED = prf(Ni | Nr, g^ir) */
|
||||
dh->get_shared_secret(dh, &secret);
|
||||
this->logger->log_chunk(this->logger, PRIVATE, "Shared Diffie Hellman secret", &secret);
|
||||
this->prf->set_key(this->prf, nonces);
|
||||
this->prf->allocate_bytes(this->prf, secret, &skeyseed);
|
||||
this->logger->log_chunk(this->logger, PRIVATE | LEVEL1, "SKEYSEED", &skeyseed);
|
||||
allocator_free_chunk(&secret);
|
||||
|
||||
/* prf+ (SKEYSEED, Ni | Nr | SPIi | SPIr )
|
||||
* = SK_d | SK_ai | SK_ar | SK_ei | SK_er | SK_pi | SK_pr
|
||||
*
|
||||
* we use the prf directly for prf+
|
||||
*/
|
||||
this->prf->set_key(this->prf, skeyseed);
|
||||
prf_plus = prf_plus_create(this->prf, nonces_spis);
|
||||
|
||||
/* clean up unused stuff */
|
||||
allocator_free_chunk(&nonces);
|
||||
allocator_free_chunk(&nonces_spis);
|
||||
allocator_free_chunk(&skeyseed);
|
||||
|
||||
|
||||
/*
|
||||
* We now can derive all of our key. We build the transforms
|
||||
* directly.
|
||||
*/
|
||||
|
||||
|
||||
/* SK_d used for prf+ to derive keys for child SAs */
|
||||
this->child_prf = prf_create(algo->algorithm);
|
||||
key_size = this->child_prf->get_key_size(this->child_prf);
|
||||
prf_plus->allocate_bytes(prf_plus, key_size, &key);
|
||||
this->logger->log_chunk(this->logger, PRIVATE, "Sk_d secret", &key);
|
||||
this->child_prf->set_key(this->child_prf, key);
|
||||
allocator_free_chunk(&key);
|
||||
|
||||
|
||||
/* SK_ai/SK_ar used for integrity protection */
|
||||
proposal->get_algorithm(proposal, IKE, INTEGRITY_ALGORITHM, &algo);
|
||||
if (algo == NULL)
|
||||
{
|
||||
this->logger->log(this->logger, ERROR|LEVEL2, "No integrity algoithm selected?!");
|
||||
return FAILED;
|
||||
}
|
||||
if (this->signer_initiator != NULL)
|
||||
{
|
||||
this->signer_initiator->destroy(this->signer_initiator);
|
||||
}
|
||||
this->signer_initiator = signer_create(proposal->integrity_algorithm);
|
||||
if (this->signer_initiator == NULL)
|
||||
{
|
||||
this->logger->log(this->logger, ERROR|LEVEL1, "Integrity algorithm %s not supported!",
|
||||
mapping_find(integrity_algorithm_m,proposal->integrity_algorithm));
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
if (this->signer_responder != NULL)
|
||||
{
|
||||
this->signer_responder->destroy(this->signer_responder);
|
||||
}
|
||||
this->signer_responder = signer_create(proposal->integrity_algorithm);
|
||||
|
||||
this->signer_initiator = signer_create(algo->algorithm);
|
||||
this->signer_responder = signer_create(algo->algorithm);
|
||||
if (this->signer_initiator == NULL || this->signer_responder == NULL)
|
||||
{
|
||||
this->logger->log(this->logger, ERROR|LEVEL1,
|
||||
"INTEGRITY_ALGORITHM %s not supported!",
|
||||
mapping_find(integrity_algorithm_m,algo->algorithm));
|
||||
return FAILED;
|
||||
}
|
||||
key_size = this->signer_initiator->get_key_size(this->signer_initiator);
|
||||
|
||||
prf_plus->allocate_bytes(prf_plus, key_size, &key);
|
||||
this->logger->log_chunk(this->logger, PRIVATE, "Sk_ai secret", &key);
|
||||
this->signer_initiator->set_key(this->signer_initiator, key);
|
||||
allocator_free_chunk(&key);
|
||||
|
||||
prf_plus->allocate_bytes(prf_plus, key_size, &key);
|
||||
this->logger->log_chunk(this->logger, PRIVATE, "Sk_ar secret", &key);
|
||||
this->signer_responder->set_key(this->signer_responder, key);
|
||||
allocator_free_chunk(&key);
|
||||
|
||||
|
||||
/* SK_ei/SK_er used for encryption */
|
||||
proposal->get_algorithm(proposal, IKE, ENCRYPTION_ALGORITHM, &algo);
|
||||
if (algo == NULL)
|
||||
{
|
||||
this->logger->log(this->logger, ERROR|LEVEL2, "No encryption algoithm selected!?");
|
||||
return FAILED;
|
||||
}
|
||||
if (this->crypter_initiator != NULL)
|
||||
{
|
||||
this->crypter_initiator->destroy(this->crypter_initiator);
|
||||
}
|
||||
if (this->crypter_responder != NULL)
|
||||
{
|
||||
this->crypter_responder->destroy(this->crypter_responder);
|
||||
}
|
||||
|
||||
this->crypter_initiator = crypter_create(algo->algorithm, algo->key_size);
|
||||
this->crypter_responder = crypter_create(algo->algorithm, algo->key_size);
|
||||
if (this->crypter_initiator == NULL || this->crypter_responder == NULL)
|
||||
{
|
||||
this->logger->log(this->logger, ERROR|LEVEL1,
|
||||
"ENCRYPTION_ALGORITHM %s (key size %d) not supported!",
|
||||
mapping_find(encryption_algorithm_m, algo->algorithm),
|
||||
algo->key_size);
|
||||
return FAILED;
|
||||
}
|
||||
key_size = this->crypter_initiator->get_key_size(this->crypter_initiator);
|
||||
|
||||
prf_plus->allocate_bytes(prf_plus, key_size, &key);
|
||||
this->logger->log_chunk(this->logger, PRIVATE, "Sk_ei secret", &key);
|
||||
this->crypter_initiator->set_key(this->crypter_initiator, key);
|
||||
allocator_free_chunk(&key);
|
||||
|
||||
prf_plus->allocate_bytes(prf_plus, key_size, &key);
|
||||
this->logger->log_chunk(this->logger, PRIVATE, "Sk_er secret", &key);
|
||||
this->crypter_responder->set_key(this->crypter_responder, key);
|
||||
allocator_free_chunk(&key);
|
||||
|
||||
/* SK_pi/SK_pr used for authentication */
|
||||
proposal->get_algorithm(proposal, IKE, PSEUDO_RANDOM_FUNCTION, &algo);
|
||||
if (this->prf_auth_i != NULL)
|
||||
{
|
||||
this->prf_auth_i->destroy(this->prf_auth_i);
|
||||
}
|
||||
if (this->prf_auth_r != NULL)
|
||||
{
|
||||
this->prf_auth_r->destroy(this->prf_auth_r);
|
||||
}
|
||||
|
||||
this->prf_auth_i = prf_create(algo->algorithm);
|
||||
this->prf_auth_r = prf_create(algo->algorithm);
|
||||
|
||||
key_size = this->prf_auth_i->get_key_size(this->prf_auth_i);
|
||||
prf_plus->allocate_bytes(prf_plus, key_size, &key);
|
||||
this->logger->log_chunk(this->logger, PRIVATE, "Sk_pi secret", &key);
|
||||
this->prf_auth_i->set_key(this->prf_auth_i, key);
|
||||
allocator_free_chunk(&key);
|
||||
|
||||
prf_plus->allocate_bytes(prf_plus, key_size, &key);
|
||||
this->logger->log_chunk(this->logger, PRIVATE, "Sk_pr secret", &key);
|
||||
this->prf_auth_r->set_key(this->prf_auth_r, key);
|
||||
allocator_free_chunk(&key);
|
||||
|
||||
/* all done, prf_plus not needed anymore */
|
||||
prf_plus->destroy(prf_plus);
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
@@ -1081,10 +1025,6 @@ static void destroy (private_ike_sa_t *this)
|
||||
/* destroy child sa */
|
||||
}
|
||||
this->child_sas->destroy(this->child_sas);
|
||||
|
||||
this->logger->log(this->logger, CONTROL | LEVEL3, "Destroy secrets");
|
||||
allocator_free(this->secrets.pi_key.ptr);
|
||||
allocator_free(this->secrets.pr_key.ptr);
|
||||
|
||||
if (this->crypter_initiator != NULL)
|
||||
{
|
||||
@@ -1120,6 +1060,14 @@ static void destroy (private_ike_sa_t *this)
|
||||
this->logger->log(this->logger, CONTROL | LEVEL3, "Destroy child_prf object");
|
||||
this->child_prf->destroy(this->child_prf);
|
||||
}
|
||||
if (this->prf_auth_i != NULL)
|
||||
{
|
||||
this->prf_auth_i->destroy(this->prf_auth_i);
|
||||
}
|
||||
if (this->prf_auth_r != NULL)
|
||||
{
|
||||
this->prf_auth_r->destroy(this->prf_auth_r);
|
||||
}
|
||||
|
||||
/* destroy ike_sa_id */
|
||||
this->logger->log(this->logger, CONTROL | LEVEL3, "Destroy ike_sa_id object");
|
||||
@@ -1182,11 +1130,10 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id)
|
||||
|
||||
/* protected functions */
|
||||
this->protected.build_message = (void (*) (protected_ike_sa_t *, exchange_type_t , bool , message_t **)) build_message;
|
||||
this->protected.compute_secrets = (void (*) (protected_ike_sa_t *,chunk_t ,chunk_t , chunk_t )) compute_secrets;
|
||||
this->protected.get_prf = (prf_t *(*) (protected_ike_sa_t *)) get_prf;
|
||||
this->protected.get_child_prf = (prf_t *(*) (protected_ike_sa_t *)) get_child_prf;
|
||||
this->protected.get_key_pr = (chunk_t (*) (protected_ike_sa_t *)) get_key_pr;
|
||||
this->protected.get_key_pi = (chunk_t (*) (protected_ike_sa_t *)) get_key_pi;
|
||||
this->protected.get_child_prf = (prf_t *(*) (protected_ike_sa_t *)) get_child_prf;
|
||||
this->protected.get_prf_auth_i = (prf_t *(*) (protected_ike_sa_t *)) get_prf_auth_i;
|
||||
this->protected.get_prf_auth_r = (prf_t *(*) (protected_ike_sa_t *)) get_prf_auth_r;
|
||||
this->protected.get_logger = (logger_t *(*) (protected_ike_sa_t *)) get_logger;
|
||||
this->protected.set_init_config = (void (*) (protected_ike_sa_t *,init_config_t *)) set_init_config;
|
||||
this->protected.get_init_config = (init_config_t *(*) (protected_ike_sa_t *)) get_init_config;
|
||||
@@ -1200,7 +1147,7 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id)
|
||||
this->protected.send_request = (status_t (*) (protected_ike_sa_t *,message_t *)) send_request;
|
||||
this->protected.send_response = (status_t (*) (protected_ike_sa_t *,message_t *)) send_response;
|
||||
this->protected.send_notify = (void (*)(protected_ike_sa_t*,exchange_type_t,notify_message_type_t,chunk_t)) send_notify;
|
||||
this->protected.create_transforms_from_proposal = (status_t (*) (protected_ike_sa_t *,ike_proposal_t *)) create_transforms_from_proposal;
|
||||
this->protected.build_transforms = (status_t (*) (protected_ike_sa_t *,proposal_t*,diffie_hellman_t*,chunk_t,chunk_t)) build_transforms;
|
||||
this->protected.set_new_state = (void (*) (protected_ike_sa_t *,state_t *)) set_new_state;
|
||||
this->protected.get_crypter_initiator = (crypter_t *(*) (protected_ike_sa_t *)) get_crypter_initiator;
|
||||
this->protected.get_signer_initiator = (signer_t *(*) (protected_ike_sa_t *)) get_signer_initiator;
|
||||
@@ -1230,13 +1177,13 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id)
|
||||
this->message_id_out = 0;
|
||||
this->message_id_in = 0;
|
||||
this->last_replied_message_id = -1;
|
||||
this->secrets.pi_key = CHUNK_INITIALIZER;
|
||||
this->secrets.pr_key = CHUNK_INITIALIZER;
|
||||
this->crypter_initiator = NULL;
|
||||
this->crypter_responder = NULL;
|
||||
this->signer_initiator = NULL;
|
||||
this->signer_responder = NULL;
|
||||
this->prf = NULL;
|
||||
this->prf_auth_i = NULL;
|
||||
this->prf_auth_r = NULL;
|
||||
this->child_prf = NULL;
|
||||
this->init_config = NULL;
|
||||
this->sa_config = NULL;
|
||||
|
||||
+26
-42
@@ -163,22 +163,6 @@ struct protected_ike_sa_t {
|
||||
* @param message new message is stored at this location
|
||||
*/
|
||||
void (*build_message) (protected_ike_sa_t *this, exchange_type_t type, bool request, message_t **message);
|
||||
|
||||
/**
|
||||
* @brief Compute the shared secrets needed for encryption, signing, etc.
|
||||
*
|
||||
* Preconditions:
|
||||
* - Call of function protected_ike_sa_t.create_transforms_from_proposal
|
||||
*
|
||||
* @param this calling object
|
||||
* @param dh_shared_secret shared secret of diffie hellman exchange
|
||||
* @param initiator_nonce nonce of initiator
|
||||
* @param responder_nonce nonce of responder
|
||||
*/
|
||||
void (*compute_secrets) (protected_ike_sa_t *this,
|
||||
chunk_t dh_shared_secret,
|
||||
chunk_t initiator_nonce,
|
||||
chunk_t responder_nonce);
|
||||
|
||||
/**
|
||||
* @brief Get the internal stored logger_t object for given ike_sa_t object.
|
||||
@@ -259,16 +243,20 @@ struct protected_ike_sa_t {
|
||||
void (*set_other_host) (protected_ike_sa_t *this,host_t *other_host);
|
||||
|
||||
/**
|
||||
* @brief Create all needed transform objects for this IKE_SA using
|
||||
* the informations stored in a ike_proposal_t object.
|
||||
* @brief Derive all keys and create the transforms for IKE communication.
|
||||
*
|
||||
* Keys are derived using the diffie hellman secret, nonces and internal
|
||||
* stored SPIs.
|
||||
* Allready existing objects get destroyed.
|
||||
*
|
||||
* @param this calling object
|
||||
* @param proposal proposal used to get informations for transform
|
||||
* objects (algorithms, key lengths, etc.)
|
||||
* @param proposal proposal which contains algorithms to use
|
||||
* @param dh diffie hellman object with shared secret
|
||||
* @param nonce_i initiators nonce
|
||||
* @param nonce_r responders nonce
|
||||
*/
|
||||
status_t (*create_transforms_from_proposal) (protected_ike_sa_t *this,ike_proposal_t * proposal);
|
||||
status_t (*build_transforms) (protected_ike_sa_t *this, proposal_t* proposal,
|
||||
diffie_hellman_t *dh, chunk_t nonce_i, chunk_t nonce_r);
|
||||
|
||||
/**
|
||||
* @brief Send the next request message.
|
||||
@@ -368,7 +356,7 @@ struct protected_ike_sa_t {
|
||||
signer_t *(*get_signer_responder) (protected_ike_sa_t *this);
|
||||
|
||||
/**
|
||||
* @brief Get the internal stored prf_t object.
|
||||
* @brief Get the multi purpose prf.
|
||||
*
|
||||
* @param this calling object
|
||||
* @return pointer to prf_t object
|
||||
@@ -383,6 +371,22 @@ struct protected_ike_sa_t {
|
||||
*/
|
||||
prf_t *(*get_child_prf) (protected_ike_sa_t *this);
|
||||
|
||||
/**
|
||||
* @brief Get the prf used for authentication of initiator.
|
||||
*
|
||||
* @param this calling object
|
||||
* @return pointer to prf_t object
|
||||
*/
|
||||
prf_t *(*get_prf_auth_i) (protected_ike_sa_t *this);
|
||||
|
||||
/**
|
||||
* @brief Get the prf used for authentication of responder.
|
||||
*
|
||||
* @param this calling object
|
||||
* @return pointer to prf_t object
|
||||
*/
|
||||
prf_t *(*get_prf_auth_r) (protected_ike_sa_t *this);
|
||||
|
||||
/**
|
||||
* @brief Get the last responded message.
|
||||
*
|
||||
@@ -403,26 +407,6 @@ struct protected_ike_sa_t {
|
||||
*/
|
||||
message_t *(*get_last_requested_message) (protected_ike_sa_t *this);
|
||||
|
||||
/**
|
||||
* @brief Get the Shared key SK_pr.
|
||||
*
|
||||
* Returned value is not cloned!
|
||||
*
|
||||
* @param this calling object
|
||||
* @return SK_pr key
|
||||
*/
|
||||
chunk_t (*get_key_pr) (protected_ike_sa_t *this);
|
||||
|
||||
/**
|
||||
* @brief Get the Shared key SK_pi.
|
||||
*
|
||||
* Returned value is not cloned!
|
||||
*
|
||||
* @param this calling object
|
||||
* @return SK_pi key
|
||||
*/
|
||||
chunk_t (*get_key_pi) (protected_ike_sa_t *this);
|
||||
|
||||
/**
|
||||
* @brief Resets message counters and does destroy stored received and sent messages.
|
||||
*
|
||||
|
||||
@@ -326,14 +326,14 @@ static status_t process_idr_payload(private_ike_auth_requested_t *this, id_paylo
|
||||
*/
|
||||
static status_t process_sa_payload(private_ike_auth_requested_t *this, sa_payload_t *sa_payload)
|
||||
{
|
||||
child_proposal_t *proposal, *proposal_tmp;
|
||||
proposal_t *proposal, *proposal_tmp;
|
||||
linked_list_t *proposal_list;
|
||||
child_sa_t *child_sa;
|
||||
chunk_t seed;
|
||||
prf_plus_t *prf_plus;
|
||||
|
||||
/* get his selected proposal */
|
||||
proposal_list = sa_payload->get_child_proposals(sa_payload);
|
||||
proposal_list = sa_payload->get_proposals(sa_payload);
|
||||
/* check count of proposals */
|
||||
if (proposal_list->get_count(proposal_list) == 0)
|
||||
{
|
||||
|
||||
@@ -69,19 +69,16 @@ struct private_ike_sa_init_requested_t {
|
||||
*/
|
||||
chunk_t received_nonce;
|
||||
|
||||
/**
|
||||
* Selected proposal
|
||||
*/
|
||||
proposal_t *proposal;
|
||||
|
||||
/**
|
||||
* Packet data of ike_sa_init request
|
||||
*/
|
||||
chunk_t ike_sa_init_request_data;
|
||||
|
||||
/**
|
||||
* DH group priority used to get dh_group_number from configuration manager.
|
||||
*
|
||||
* Is passed to the next state object of type INITATOR_INIT if the selected group number
|
||||
* is not the same as in the peers selected proposal.
|
||||
*/
|
||||
u_int16_t dh_group_priority;
|
||||
|
||||
/**
|
||||
* Assigned logger
|
||||
*
|
||||
@@ -329,7 +326,15 @@ static status_t process_message(private_ike_sa_init_requested_t *this, message_t
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/* derive all the keys used in the IKE_SA */
|
||||
status = this->ike_sa->build_transforms(this->ike_sa, this->proposal, this->diffie_hellman, this->sent_nonce, this->received_nonce);
|
||||
if (status != SUCCESS)
|
||||
{
|
||||
this->logger->log(this->logger, AUDIT, "Transform objects could not be created from selected proposal. Deleting IKE_SA");
|
||||
return DELETE_ME;
|
||||
}
|
||||
|
||||
/* build empty message */
|
||||
this->ike_sa->build_message(this->ike_sa, IKE_AUTH, TRUE, &request);
|
||||
|
||||
@@ -402,45 +407,39 @@ status_t process_nonce_payload (private_ike_sa_init_requested_t *this, nonce_pay
|
||||
*/
|
||||
status_t process_sa_payload (private_ike_sa_init_requested_t *this, sa_payload_t *sa_payload)
|
||||
{
|
||||
ike_proposal_t selected_proposal;
|
||||
ike_proposal_t *ike_proposals;
|
||||
proposal_t *proposal;
|
||||
linked_list_t *proposal_list;
|
||||
init_config_t *init_config;
|
||||
size_t proposal_count;
|
||||
status_t status;
|
||||
|
||||
init_config = this->ike_sa->get_init_config(this->ike_sa);
|
||||
|
||||
/* get the list of selected proposals */
|
||||
status = sa_payload->get_ike_proposals (sa_payload, &ike_proposals,&proposal_count);
|
||||
if (status != SUCCESS)
|
||||
/* get the list of selected proposals, the peer has to select only one proposal */
|
||||
proposal_list = sa_payload->get_proposals (sa_payload);
|
||||
if (proposal_list->get_count(proposal_list) != 1)
|
||||
{
|
||||
this->logger->log(this->logger, AUDIT, "IKE_SA_INIT response did not contain any proposals. Deleting IKE_SA");
|
||||
return DELETE_ME;
|
||||
}
|
||||
/* the peer has to select only one proposal */
|
||||
if (proposal_count != 1)
|
||||
{
|
||||
this->logger->log(this->logger, AUDIT, "IKE_SA_INIT response contained more than one proposal. Deleting IKE_SA");
|
||||
allocator_free(ike_proposals);
|
||||
return DELETE_ME;
|
||||
this->logger->log(this->logger, AUDIT, "IKE_SA_INIT response did not contain a single proposal. Deleting IKE_SA");
|
||||
while (proposal_list->remove_last(proposal_list, (void**)&proposal) == SUCCESS)
|
||||
{
|
||||
proposal->destroy(proposal);
|
||||
}
|
||||
proposal_list->destroy(proposal_list);
|
||||
return DELETE_ME;
|
||||
}
|
||||
|
||||
/* now let the configuration-manager check the selected proposals*/
|
||||
this->logger->log(this->logger, CONTROL | LEVEL2, "Check selected proposal");
|
||||
status = init_config->select_proposal (init_config,ike_proposals,1,&selected_proposal);
|
||||
allocator_free(ike_proposals);
|
||||
if (status != SUCCESS)
|
||||
/* we have to re-check if the others selection is valid */
|
||||
this->proposal = init_config->select_proposal(init_config, proposal_list);
|
||||
while (proposal_list->remove_last(proposal_list, (void**)&proposal) == SUCCESS)
|
||||
{
|
||||
proposal->destroy(proposal);
|
||||
}
|
||||
proposal_list->destroy(proposal_list);
|
||||
|
||||
if (this->proposal == NULL)
|
||||
{
|
||||
this->logger->log(this->logger, AUDIT, "IKE_SA_INIT response contained selected proposal we did not offer. Deleting IKE_SA");
|
||||
return DELETE_ME;
|
||||
}
|
||||
|
||||
status = this->ike_sa->create_transforms_from_proposal(this->ike_sa,&selected_proposal);
|
||||
if (status != SUCCESS)
|
||||
{
|
||||
this->logger->log(this->logger, AUDIT, "Transform objects could not be created from selected proposal. Deleting IKE_SA");
|
||||
return DELETE_ME;
|
||||
}
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
@@ -448,24 +447,9 @@ status_t process_sa_payload (private_ike_sa_init_requested_t *this, sa_payload_t
|
||||
* Implementation of private_ike_sa_init_requested_t.process_ke_payload.
|
||||
*/
|
||||
status_t process_ke_payload (private_ike_sa_init_requested_t *this, ke_payload_t *ke_payload)
|
||||
{
|
||||
chunk_t shared_secret;
|
||||
status_t status;
|
||||
|
||||
{
|
||||
this->diffie_hellman->set_other_public_value(this->diffie_hellman, ke_payload->get_key_exchange_data(ke_payload));
|
||||
|
||||
/* store shared secret
|
||||
* status of dh object does not have to get checked cause other key is set
|
||||
*/
|
||||
this->logger->log(this->logger, CONTROL | LEVEL2, "Retrieve shared secret and store it");
|
||||
status = this->diffie_hellman->get_shared_secret(this->diffie_hellman, &shared_secret);
|
||||
this->logger->log_chunk(this->logger, PRIVATE, "Shared secret", &shared_secret);
|
||||
|
||||
this->logger->log(this->logger, CONTROL | LEVEL2, "Going to derive all secrets from shared secret");
|
||||
this->ike_sa->compute_secrets(this->ike_sa,shared_secret,this->sent_nonce, this->received_nonce);
|
||||
|
||||
allocator_free_chunk(&(shared_secret));
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
@@ -528,7 +512,7 @@ static status_t build_sa_payload (private_ike_sa_init_requested_t *this, message
|
||||
/* get proposals form config, add to payload */
|
||||
sa_config = this->ike_sa->get_sa_config(this->ike_sa);
|
||||
proposal_list = sa_config->get_proposals(sa_config);
|
||||
sa_payload = sa_payload_create_from_child_proposal_list(proposal_list);
|
||||
sa_payload = sa_payload_create_from_proposal_list(proposal_list);
|
||||
|
||||
/* TODO child sa stuff */
|
||||
|
||||
@@ -625,9 +609,25 @@ static status_t process_notify_payload(private_ike_sa_init_requested_t *this, no
|
||||
case INVALID_KE_PAYLOAD:
|
||||
{
|
||||
initiator_init_t *initiator_init_state;
|
||||
u_int16_t new_dh_group_priority;
|
||||
chunk_t notify_data;
|
||||
diffie_hellman_group_t dh_group;
|
||||
init_config_t *init_config;
|
||||
|
||||
notify_data = notify_payload->get_notification_data(notify_payload);
|
||||
dh_group = ntohs(*((u_int16_t*)notify_data.ptr));
|
||||
|
||||
this->logger->log(this->logger, ERROR|LEVEL1, "Peer wouldn't accept DH group, it requested %s!",
|
||||
mapping_find(diffie_hellman_group_m, dh_group));
|
||||
/* check if we can accept this dh group */
|
||||
init_config = this->ike_sa->get_init_config(this->ike_sa);
|
||||
if (!init_config->check_dh_group(init_config, dh_group))
|
||||
{
|
||||
this->logger->log(this->logger, AUDIT,
|
||||
"Peer does only accept DH group %s, which we do not accept! Aborting",
|
||||
mapping_find(diffie_hellman_group_m, dh_group));
|
||||
return DELETE_ME;
|
||||
}
|
||||
|
||||
this->logger->log(this->logger, ERROR|LEVEL1, "Selected DH group is not the one in the proposal selected by the responder!");
|
||||
/* Going to change state back to initiator_init_t */
|
||||
this->logger->log(this->logger, CONTROL|LEVEL2, "Create next state object");
|
||||
initiator_init_state = initiator_init_create(this->ike_sa);
|
||||
@@ -644,15 +644,13 @@ static status_t process_notify_payload(private_ike_sa_init_requested_t *this, no
|
||||
|
||||
this->logger->log(this->logger, CONTROL|LEVEL2, "Destroy old sate object");
|
||||
this->logger->log(this->logger, CONTROL|LEVEL2, "Going to retry initialization of connection");
|
||||
new_dh_group_priority = this->dh_group_priority + 1;
|
||||
|
||||
this->public.state_interface.destroy(&(this->public.state_interface));
|
||||
if (initiator_init_state->retry_initiate_connection (initiator_init_state,new_dh_group_priority) != SUCCESS)
|
||||
if (initiator_init_state->retry_initiate_connection (initiator_init_state, dh_group) != SUCCESS)
|
||||
{
|
||||
return DELETE_ME;
|
||||
}
|
||||
return FAILED;
|
||||
|
||||
}
|
||||
default:
|
||||
{
|
||||
@@ -676,7 +674,6 @@ static status_t process_notify_payload(private_ike_sa_init_requested_t *this, no
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Implementation of state_t.get_state.
|
||||
*/
|
||||
@@ -690,14 +687,13 @@ static ike_sa_state_t get_state(private_ike_sa_init_requested_t *this)
|
||||
*/
|
||||
static void destroy_after_state_change (private_ike_sa_init_requested_t *this)
|
||||
{
|
||||
this->logger->log(this->logger, CONTROL | LEVEL3, "Going to destroy state of type ike_sa_init_requested_t after state change.");
|
||||
|
||||
this->logger->log(this->logger, CONTROL | LEVEL3, "Destroy diffie hellman object");
|
||||
this->diffie_hellman->destroy(this->diffie_hellman);
|
||||
this->logger->log(this->logger, CONTROL | LEVEL3, "Destroy ike_sa_init_request_data");
|
||||
allocator_free_chunk(&(this->ike_sa_init_request_data));
|
||||
this->logger->log(this->logger, CONTROL | LEVEL3, "Destroy object itself");
|
||||
allocator_free(this);
|
||||
if (this->proposal)
|
||||
{
|
||||
this->proposal->destroy(this->proposal);
|
||||
}
|
||||
allocator_free(this);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -705,24 +701,21 @@ static void destroy_after_state_change (private_ike_sa_init_requested_t *this)
|
||||
*/
|
||||
static void destroy(private_ike_sa_init_requested_t *this)
|
||||
{
|
||||
this->logger->log(this->logger, CONTROL | LEVEL3, "Going to destroy state of type ike_sa_init_requested_t");
|
||||
|
||||
this->logger->log(this->logger, CONTROL | LEVEL3, "Destroy diffie hellman object");
|
||||
this->diffie_hellman->destroy(this->diffie_hellman);
|
||||
this->logger->log(this->logger, CONTROL | LEVEL3, "Destroy sent nonce");
|
||||
allocator_free(this->sent_nonce.ptr);
|
||||
this->logger->log(this->logger, CONTROL | LEVEL3, "Destroy received nonce");
|
||||
allocator_free(this->received_nonce.ptr);
|
||||
this->logger->log(this->logger, CONTROL | LEVEL3, "Destroy ike_sa_init_request_data");
|
||||
allocator_free_chunk(&(this->ike_sa_init_request_data));
|
||||
this->logger->log(this->logger, CONTROL | LEVEL3, "Destroy object itself");
|
||||
if (this->proposal)
|
||||
{
|
||||
this->proposal->destroy(this->proposal);
|
||||
}
|
||||
allocator_free(this);
|
||||
}
|
||||
|
||||
/*
|
||||
* Described in header.
|
||||
*/
|
||||
ike_sa_init_requested_t *ike_sa_init_requested_create(protected_ike_sa_t *ike_sa, u_int16_t dh_group_priority, diffie_hellman_t *diffie_hellman, chunk_t sent_nonce,chunk_t ike_sa_init_request_data)
|
||||
ike_sa_init_requested_t *ike_sa_init_requested_create(protected_ike_sa_t *ike_sa, diffie_hellman_t *diffie_hellman, chunk_t sent_nonce,chunk_t ike_sa_init_request_data)
|
||||
{
|
||||
private_ike_sa_init_requested_t *this = allocator_alloc_thing(private_ike_sa_init_requested_t);
|
||||
|
||||
@@ -748,9 +741,9 @@ ike_sa_init_requested_t *ike_sa_init_requested_create(protected_ike_sa_t *ike_sa
|
||||
this->received_nonce = CHUNK_INITIALIZER;
|
||||
this->logger = this->ike_sa->get_logger(this->ike_sa);
|
||||
this->diffie_hellman = diffie_hellman;
|
||||
this->proposal = NULL;
|
||||
this->sent_nonce = sent_nonce;
|
||||
this->ike_sa_init_request_data = ike_sa_init_request_data;
|
||||
this->dh_group_priority = dh_group_priority;
|
||||
|
||||
return &(this->public);
|
||||
}
|
||||
|
||||
@@ -53,7 +53,6 @@ struct ike_sa_init_requested_t {
|
||||
* Constructor of class ike_sa_init_requested_t.
|
||||
*
|
||||
* @param ike_sa assigned ike_sa
|
||||
* @param dh_group_priority the last used priority number to get the DH group for request
|
||||
* @param diffie_hellman diffie_hellman object use to retrieve shared secret
|
||||
* @param sent_nonce Sent nonce value
|
||||
* @param ike_sa_init_request_data the binary representation of the IKE_SA_INIT request message
|
||||
@@ -62,7 +61,6 @@ struct ike_sa_init_requested_t {
|
||||
* @ingroup states
|
||||
*/
|
||||
ike_sa_init_requested_t *ike_sa_init_requested_create(protected_ike_sa_t *ike_sa,
|
||||
u_int16_t dh_group_priority,
|
||||
diffie_hellman_t *diffie_hellman,
|
||||
chunk_t sent_nonce,
|
||||
chunk_t ike_sa_init_request_data);
|
||||
|
||||
@@ -387,7 +387,7 @@ static status_t build_idr_payload(private_ike_sa_init_responded_t *this, id_payl
|
||||
*/
|
||||
static status_t build_sa_payload(private_ike_sa_init_responded_t *this, sa_payload_t *request, message_t *response)
|
||||
{
|
||||
child_proposal_t *proposal, *proposal_tmp;
|
||||
proposal_t *proposal, *proposal_tmp;
|
||||
linked_list_t *proposal_list;
|
||||
sa_payload_t *sa_response;
|
||||
child_sa_t *child_sa;
|
||||
@@ -397,7 +397,7 @@ static status_t build_sa_payload(private_ike_sa_init_responded_t *this, sa_paylo
|
||||
/* TODO: child sa stuff */
|
||||
|
||||
/* get proposals from request */
|
||||
proposal_list = request->get_child_proposals(request);
|
||||
proposal_list = request->get_proposals(request);
|
||||
if (proposal_list->get_count(proposal_list) == 0)
|
||||
{
|
||||
/* if the other side did not offer any proposals, we do not create child sa's */
|
||||
@@ -426,7 +426,7 @@ static status_t build_sa_payload(private_ike_sa_init_responded_t *this, sa_paylo
|
||||
}
|
||||
|
||||
/* create payload with selected propsal */
|
||||
sa_response = sa_payload_create_from_child_proposal(proposal);
|
||||
sa_response = sa_payload_create_from_proposal(proposal);
|
||||
response->add_payload(response, (payload_t*)sa_response);
|
||||
|
||||
/* install child SAs for AH and esp */
|
||||
|
||||
@@ -57,17 +57,6 @@ struct private_initiator_init_t {
|
||||
*/
|
||||
diffie_hellman_t *diffie_hellman;
|
||||
|
||||
/**
|
||||
* DH group number.
|
||||
*/
|
||||
u_int16_t dh_group_number;
|
||||
|
||||
/**
|
||||
* DH group priority used to get dh_group_number from configuration manager.
|
||||
* This priority is passed to the next state of type IKE_SA_INIT_REQUESTED.
|
||||
*/
|
||||
u_int16_t dh_group_priority;
|
||||
|
||||
/**
|
||||
* Sent nonce.
|
||||
* This nonce is passed to the next state of type IKE_SA_INIT_REQUESTED.
|
||||
@@ -124,49 +113,41 @@ static status_t initiate_connection (private_initiator_init_t *this, char *name)
|
||||
init_config_t *init_config;
|
||||
sa_config_t *sa_config;
|
||||
status_t status;
|
||||
|
||||
diffie_hellman_group_t dh_group;
|
||||
|
||||
this->logger->log(this->logger, CONTROL, "Initializing connection %s",name);
|
||||
|
||||
/* get configs */
|
||||
status = charon->configuration_manager->get_init_config_for_name(charon->configuration_manager,name,&init_config);
|
||||
if (status != SUCCESS)
|
||||
{
|
||||
this->logger->log(this->logger, ERROR | LEVEL1, "Could not retrieve INIT configuration informations for %s",name);
|
||||
return DELETE_ME;
|
||||
}
|
||||
|
||||
this->ike_sa->set_init_config(this->ike_sa,init_config);
|
||||
|
||||
status = charon->configuration_manager->get_sa_config_for_name(charon->configuration_manager,name,&sa_config);
|
||||
|
||||
if (status != SUCCESS)
|
||||
{
|
||||
{
|
||||
this->logger->log(this->logger, ERROR | LEVEL1, "Could not retrieve SA configuration informations for %s",name);
|
||||
return DELETE_ME;
|
||||
}
|
||||
|
||||
this->ike_sa->set_sa_config(this->ike_sa,sa_config);
|
||||
|
||||
/* host informations are read from configuration */
|
||||
this->ike_sa->set_other_host(this->ike_sa,init_config->get_other_host_clone(init_config));
|
||||
this->ike_sa->set_my_host(this->ike_sa,init_config->get_my_host_clone(init_config));
|
||||
|
||||
this->dh_group_number = init_config->get_dh_group_number(init_config,this->dh_group_priority);
|
||||
if (this->dh_group_number == MODP_UNDEFINED)
|
||||
{
|
||||
this->logger->log(this->logger, AUDIT, "Could not find a matching diffie hellman group after %d. try. Aborting.",
|
||||
this->dh_group_priority);
|
||||
return DELETE_ME;
|
||||
}
|
||||
/* we must guess now a DH group. For that we choose our most preferred group */
|
||||
dh_group = init_config->get_dh_group(init_config);
|
||||
|
||||
/* next step is done in retry_initiate_connection */
|
||||
return this->public.retry_initiate_connection(&(this->public),this->dh_group_priority);
|
||||
return this->public.retry_initiate_connection(&(this->public), dh_group);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of initiator_init_t.retry_initiate_connection.
|
||||
*/
|
||||
status_t retry_initiate_connection (private_initiator_init_t *this, int dh_group_priority)
|
||||
status_t retry_initiate_connection (private_initiator_init_t *this, diffie_hellman_group_t dh_group)
|
||||
{
|
||||
ike_sa_init_requested_t *next_state;
|
||||
chunk_t ike_sa_init_request_data;
|
||||
@@ -174,24 +155,18 @@ status_t retry_initiate_connection (private_initiator_init_t *this, int dh_group
|
||||
ike_sa_id_t *ike_sa_id;
|
||||
message_t *message;
|
||||
status_t status;
|
||||
|
||||
|
||||
this->dh_group_priority = dh_group_priority;
|
||||
|
||||
init_config = this->ike_sa->get_init_config(this->ike_sa);
|
||||
|
||||
ike_sa_id = this->ike_sa->public.get_id(&(this->ike_sa->public));
|
||||
ike_sa_id->set_responder_spi(ike_sa_id,0);
|
||||
|
||||
this->dh_group_number = init_config->get_dh_group_number(init_config,dh_group_priority);
|
||||
if (this->dh_group_number == MODP_UNDEFINED)
|
||||
if (dh_group == MODP_UNDEFINED)
|
||||
{
|
||||
this->logger->log(this->logger, AUDIT, "Could not find a matching diffie hellman group after %d. try. Aborting.",
|
||||
this->dh_group_priority);
|
||||
this->logger->log(this->logger, AUDIT, "No DH group acceptable for initialization, Aborting");
|
||||
message->destroy(message);
|
||||
return DELETE_ME;
|
||||
}
|
||||
|
||||
this->diffie_hellman = diffie_hellman_create(this->dh_group_number);
|
||||
init_config = this->ike_sa->get_init_config(this->ike_sa);
|
||||
this->diffie_hellman = diffie_hellman_create(dh_group);
|
||||
ike_sa_id = this->ike_sa->public.get_id(&(this->ike_sa->public));
|
||||
ike_sa_id->set_responder_spi(ike_sa_id,0);
|
||||
|
||||
/* going to build message */
|
||||
this->logger->log(this->logger, CONTROL|LEVEL2, "Going to build message");
|
||||
@@ -222,7 +197,7 @@ status_t retry_initiate_connection (private_initiator_init_t *this, int dh_group
|
||||
|
||||
/* state can now be changed */
|
||||
this->logger->log(this->logger, CONTROL|LEVEL2, "Create next state object");
|
||||
next_state = ike_sa_init_requested_create(this->ike_sa, this->dh_group_priority, this->diffie_hellman, this->sent_nonce,ike_sa_init_request_data);
|
||||
next_state = ike_sa_init_requested_create(this->ike_sa, this->diffie_hellman, this->sent_nonce,ike_sa_init_request_data);
|
||||
this->ike_sa->set_new_state(this->ike_sa,(state_t *) next_state);
|
||||
|
||||
this->logger->log(this->logger, CONTROL|LEVEL2, "Destroy old sate object");
|
||||
@@ -236,19 +211,16 @@ status_t retry_initiate_connection (private_initiator_init_t *this, int dh_group
|
||||
static void build_sa_payload(private_initiator_init_t *this, message_t *request)
|
||||
{
|
||||
sa_payload_t* sa_payload;
|
||||
size_t proposal_count;
|
||||
ike_proposal_t *proposals;
|
||||
linked_list_t *proposal_list;
|
||||
init_config_t *init_config;
|
||||
|
||||
this->logger->log(this->logger, CONTROL|LEVEL1, "Building SA payload");
|
||||
|
||||
init_config = this->ike_sa->get_init_config(this->ike_sa);
|
||||
|
||||
proposal_count = init_config->get_proposals(init_config,&proposals);
|
||||
proposal_list = init_config->get_proposals(init_config);
|
||||
|
||||
sa_payload = sa_payload_create_from_ike_proposals(proposals,proposal_count);
|
||||
|
||||
allocator_free(proposals);
|
||||
sa_payload = sa_payload_create_from_proposal_list(proposal_list);
|
||||
|
||||
this->logger->log(this->logger, CONTROL|LEVEL2, "Add SA payload to message");
|
||||
request->add_payload(request, (payload_t *) sa_payload);
|
||||
@@ -261,13 +233,15 @@ static void build_ke_payload(private_initiator_init_t *this, message_t *request)
|
||||
{
|
||||
ke_payload_t *ke_payload;
|
||||
chunk_t key_data;
|
||||
diffie_hellman_group_t dh_group;
|
||||
|
||||
this->logger->log(this->logger, CONTROL|LEVEL1, "Building KE payload");
|
||||
|
||||
this->diffie_hellman->get_my_public_value(this->diffie_hellman,&key_data);
|
||||
dh_group = this->diffie_hellman->get_dh_group(this->diffie_hellman);
|
||||
|
||||
ke_payload = ke_payload_create();
|
||||
ke_payload->set_dh_group_number(ke_payload, this->dh_group_number);
|
||||
ke_payload->set_dh_group_number(ke_payload, dh_group);
|
||||
ke_payload->set_key_exchange_data(ke_payload, key_data);
|
||||
|
||||
allocator_free_chunk(&key_data);
|
||||
@@ -372,7 +346,6 @@ initiator_init_t *initiator_init_create(protected_ike_sa_t *ike_sa)
|
||||
|
||||
/* private data */
|
||||
this->ike_sa = ike_sa;
|
||||
this->dh_group_priority = 1;
|
||||
this->logger = this->ike_sa->get_logger(this->ike_sa);
|
||||
this->sent_nonce = CHUNK_INITIALIZER;
|
||||
this->diffie_hellman = NULL;
|
||||
|
||||
@@ -79,6 +79,11 @@ struct private_responder_init_t {
|
||||
*/
|
||||
chunk_t received_nonce;
|
||||
|
||||
/**
|
||||
* Selected proposal
|
||||
*/
|
||||
proposal_t *proposal;
|
||||
|
||||
/**
|
||||
* Logger used to log data .
|
||||
*
|
||||
@@ -153,7 +158,6 @@ static status_t process_message(private_responder_init_t *this, message_t *messa
|
||||
nonce_payload_t *nonce_request = NULL;
|
||||
host_t *source, *destination;
|
||||
init_config_t *init_config;
|
||||
chunk_t shared_secret;
|
||||
iterator_t *payloads;
|
||||
message_t *response;
|
||||
status_t status;
|
||||
@@ -275,17 +279,15 @@ static status_t process_message(private_responder_init_t *this, message_t *messa
|
||||
{
|
||||
response->destroy(response);
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
/* store shared secret */
|
||||
this->logger->log(this->logger, CONTROL | LEVEL2, "Retrieve shared secret and store it");
|
||||
status = this->diffie_hellman->get_shared_secret(this->diffie_hellman, &shared_secret);
|
||||
this->logger->log_chunk(this->logger, PRIVATE, "Shared Diffie Hellman secret", &shared_secret);
|
||||
|
||||
this->ike_sa->compute_secrets(this->ike_sa,shared_secret,this->received_nonce, this->sent_nonce);
|
||||
|
||||
/* not used anymore */
|
||||
allocator_free_chunk(&shared_secret);
|
||||
/* derive all the keys used in the IKE_SA */
|
||||
status = this->ike_sa->build_transforms(this->ike_sa, this->proposal, this->diffie_hellman, this->received_nonce, this->sent_nonce);
|
||||
if (status != SUCCESS)
|
||||
{
|
||||
this->logger->log(this->logger, AUDIT, "Transform objects could not be created from selected proposal. Deleting IKE_SA");
|
||||
return DELETE_ME;
|
||||
}
|
||||
|
||||
/* message can now be sent (must not be destroyed) */
|
||||
status = this->ike_sa->send_response(this->ike_sa, response);
|
||||
@@ -318,47 +320,40 @@ static status_t process_message(private_responder_init_t *this, message_t *messa
|
||||
*/
|
||||
static status_t build_sa_payload(private_responder_init_t *this,sa_payload_t *sa_request, message_t *response)
|
||||
{
|
||||
ike_proposal_t selected_proposal;
|
||||
ike_proposal_t *ike_proposals;
|
||||
proposal_t *proposal;
|
||||
linked_list_t *proposal_list;
|
||||
init_config_t *init_config;
|
||||
sa_payload_t* sa_payload;
|
||||
size_t proposal_count;
|
||||
status_t status;
|
||||
algorithm_t *algo;
|
||||
|
||||
init_config = this->ike_sa->get_init_config(this->ike_sa);
|
||||
|
||||
this->logger->log(this->logger, CONTROL | LEVEL2, "Process received SA payload");
|
||||
|
||||
/* get the list of suggested proposals */
|
||||
status = sa_request->get_ike_proposals (sa_request, &ike_proposals,&proposal_count);
|
||||
if (status != SUCCESS)
|
||||
{
|
||||
this->logger->log(this->logger, AUDIT, "IKE_SA_INIT request did not contain any proposals. Deleting IKE_SA");
|
||||
this->ike_sa->send_notify(this->ike_sa, IKE_SA_INIT, NO_PROPOSAL_CHOSEN, CHUNK_INITIALIZER);
|
||||
return DELETE_ME;
|
||||
}
|
||||
proposal_list = sa_request->get_proposals (sa_request);
|
||||
|
||||
status = init_config->select_proposal(init_config, ike_proposals,proposal_count,&(selected_proposal));
|
||||
allocator_free(ike_proposals);
|
||||
if (status != SUCCESS)
|
||||
/* select proposal */
|
||||
this->proposal = init_config->select_proposal(init_config, proposal_list);
|
||||
while(proposal_list->remove_last(proposal_list, (void**)&proposal) == SUCCESS)
|
||||
{
|
||||
proposal->destroy(proposal);
|
||||
}
|
||||
proposal_list->destroy(proposal_list);
|
||||
if (this->proposal == NULL)
|
||||
{
|
||||
this->logger->log(this->logger, AUDIT, "IKE_SA_INIT request did not contain any acceptable proposals. Deleting IKE_SA");
|
||||
this->ike_sa->send_notify(this->ike_sa, IKE_SA_INIT, NO_PROPOSAL_CHOSEN, CHUNK_INITIALIZER);
|
||||
return DELETE_ME;
|
||||
}
|
||||
|
||||
this->dh_group_number = selected_proposal.diffie_hellman_group;
|
||||
|
||||
status = this->ike_sa->create_transforms_from_proposal(this->ike_sa,&(selected_proposal));
|
||||
if (status != SUCCESS)
|
||||
{
|
||||
this->logger->log(this->logger, AUDIT, "Transform objects could not be created from selected proposal. Deleting IKE_SA");
|
||||
return DELETE_ME;
|
||||
}
|
||||
/* get selected DH group to force policy, this is very restrictive!? */
|
||||
this->proposal->get_algorithm(this->proposal, IKE, DIFFIE_HELLMAN_GROUP, &algo);
|
||||
this->dh_group_number = algo->algorithm;
|
||||
|
||||
this->logger->log(this->logger, CONTROL | LEVEL2, "SA Payload processed");
|
||||
|
||||
this->logger->log(this->logger, CONTROL|LEVEL2, "Building SA payload");
|
||||
sa_payload = sa_payload_create_from_ike_proposals(&(selected_proposal),1);
|
||||
sa_payload = sa_payload_create_from_proposal(this->proposal);
|
||||
this->logger->log(this->logger, CONTROL|LEVEL2, "add SA payload to message");
|
||||
response->add_payload(response,(payload_t *) sa_payload);
|
||||
|
||||
@@ -383,6 +378,7 @@ static status_t build_ke_payload(private_responder_init_t *this,ke_payload_t *ke
|
||||
this->logger->log(this->logger, AUDIT, "No diffie hellman group to select. Deleting IKE_SA");
|
||||
return DELETE_ME;
|
||||
}
|
||||
|
||||
if (this->dh_group_number != group)
|
||||
{
|
||||
u_int16_t accepted_group;
|
||||
@@ -510,6 +506,10 @@ static void destroy(private_responder_init_t *this)
|
||||
this->logger->log(this->logger, CONTROL | LEVEL2, "Destroy diffie_hellman_t hellman object");
|
||||
this->diffie_hellman->destroy(this->diffie_hellman);
|
||||
}
|
||||
if (this->proposal)
|
||||
{
|
||||
this->proposal->destroy(this->proposal);
|
||||
}
|
||||
this->logger->log(this->logger, CONTROL | LEVEL2, "Destroy object");
|
||||
allocator_free(this);
|
||||
}
|
||||
@@ -527,6 +527,10 @@ static void destroy_after_state_change (private_responder_init_t *this)
|
||||
this->logger->log(this->logger, CONTROL | LEVEL2, "Destroy diffie_hellman_t object");
|
||||
this->diffie_hellman->destroy(this->diffie_hellman);
|
||||
}
|
||||
if (this->proposal)
|
||||
{
|
||||
this->proposal->destroy(this->proposal);
|
||||
}
|
||||
|
||||
this->logger->log(this->logger, CONTROL | LEVEL2, "Destroy object");
|
||||
allocator_free(this);
|
||||
@@ -558,6 +562,7 @@ responder_init_t *responder_init_create(protected_ike_sa_t *ike_sa)
|
||||
this->received_nonce = CHUNK_INITIALIZER;
|
||||
this->dh_group_number = MODP_UNDEFINED;
|
||||
this->diffie_hellman = NULL;
|
||||
this->proposal = NULL;
|
||||
|
||||
return &(this->public);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user