diff options
Diffstat (limited to 'Source/charon/sa')
-rw-r--r-- | Source/charon/sa/authenticator.c | 10 | ||||
-rw-r--r-- | Source/charon/sa/child_sa.c | 2 | ||||
-rw-r--r-- | Source/charon/sa/child_sa.h | 2 | ||||
-rw-r--r-- | Source/charon/sa/ike_sa.c | 433 | ||||
-rw-r--r-- | Source/charon/sa/ike_sa.h | 68 | ||||
-rw-r--r-- | Source/charon/sa/states/ike_auth_requested.c | 4 | ||||
-rw-r--r-- | Source/charon/sa/states/ike_sa_init_requested.c | 137 | ||||
-rw-r--r-- | Source/charon/sa/states/ike_sa_init_requested.h | 2 | ||||
-rw-r--r-- | Source/charon/sa/states/ike_sa_init_responded.c | 6 | ||||
-rw-r--r-- | Source/charon/sa/states/initiator_init.c | 69 | ||||
-rw-r--r-- | Source/charon/sa/states/responder_init.c | 73 |
11 files changed, 353 insertions, 453 deletions
diff --git a/Source/charon/sa/authenticator.c b/Source/charon/sa/authenticator.c index 7d40c78c2..5aaa2d983 100644 --- a/Source/charon/sa/authenticator.c +++ b/Source/charon/sa/authenticator.c @@ -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; diff --git a/Source/charon/sa/child_sa.c b/Source/charon/sa/child_sa.c index c18b760f2..2c4624310 100644 --- a/Source/charon/sa/child_sa.c +++ b/Source/charon/sa/child_sa.c @@ -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; diff --git a/Source/charon/sa/child_sa.h b/Source/charon/sa/child_sa.h index 8a7462594..bde032b74 100644 --- a/Source/charon/sa/child_sa.h +++ b/Source/charon/sa/child_sa.h @@ -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_*/ diff --git a/Source/charon/sa/ike_sa.c b/Source/charon/sa/ike_sa.c index 2f403abf6..ac617faef 100644 --- a/Source/charon/sa/ike_sa.c +++ b/Source/charon/sa/ike_sa.c @@ -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; - - /** - * Key for generating auth payload (responder) - */ - chunk_t pr_key; + prf_t *prf_auth_i; - } 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); }; /** @@ -441,103 +370,6 @@ static ike_sa_id_t* get_id(private_ike_sa_t *this) } /** - * 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. */ static status_t resend_last_reply(private_ike_sa_t *this) @@ -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_key_pi. + * Implementation of protected_ike_sa_t.get_prf_auth_r. */ -static chunk_t get_key_pi (private_ike_sa_t *this) +static prf_t *get_prf_auth_r (private_ike_sa_t *this) { - return this->secrets.pi_key; + return this->prf_auth_r; } + /** - * Implementation of protected_ike_sa_t.set_prf. + * Implementation of protected_ike_sa_t.build_transforms. */ -static status_t create_transforms_from_proposal (private_ike_sa_t *this,ike_proposal_t *proposal) +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) { - 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); - if (this->prf == NULL) + proposal->get_algorithm(proposal, IKE, PSEUDO_RANDOM_FUNCTION, &algo); + if (algo == 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|LEVEL2, "No PRF algoithm selected!?"); return FAILED; } - this->child_prf = prf_create(proposal->pseudo_random_function); - if (this->child_prf == NULL) + 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)); + 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) + /* 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); + + /* 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->crypter_initiator->destroy(this->crypter_initiator); + this->logger->log(this->logger, ERROR|LEVEL2, "No integrity algoithm selected?!"); + return FAILED; } - this->crypter_initiator = crypter_create(proposal->encryption_algorithm, - proposal->encryption_algorithm_key_length); - if (this->crypter_initiator == NULL) + if (this->signer_initiator != NULL) + { + this->signer_initiator->destroy(this->signer_initiator); + } + if (this->signer_responder != NULL) { - this->logger->log(this->logger, ERROR|LEVEL1, "Encryption algorithm %s not supported!", - mapping_find(encryption_algorithm_m,proposal->encryption_algorithm)); + this->signer_responder->destroy(this->signer_responder); + } + + 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_responder = crypter_create(proposal->encryption_algorithm, - proposal->encryption_algorithm_key_length); - /* check must not be done again */ - if (this->signer_initiator != NULL) + 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->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)); + 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); - if (this->signer_responder != NULL) + 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->signer_responder->destroy(this->signer_responder); + this->prf_auth_i->destroy(this->prf_auth_i); } - this->signer_responder = signer_create(proposal->integrity_algorithm); - + 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; diff --git a/Source/charon/sa/ike_sa.h b/Source/charon/sa/ike_sa.h index 09101f7f5..f5591a00b 100644 --- a/Source/charon/sa/ike_sa.h +++ b/Source/charon/sa/ike_sa.h @@ -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 @@ -384,6 +372,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. * * @param this calling object @@ -404,26 +408,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. * * @param this calling object diff --git a/Source/charon/sa/states/ike_auth_requested.c b/Source/charon/sa/states/ike_auth_requested.c index 60369ba28..e6559319c 100644 --- a/Source/charon/sa/states/ike_auth_requested.c +++ b/Source/charon/sa/states/ike_auth_requested.c @@ -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) { diff --git a/Source/charon/sa/states/ike_sa_init_requested.c b/Source/charon/sa/states/ike_sa_init_requested.c index 7636ecbbe..327eb2d7c 100644 --- a/Source/charon/sa/states/ike_sa_init_requested.c +++ b/Source/charon/sa/states/ike_sa_init_requested.c @@ -70,17 +70,14 @@ struct private_ike_sa_init_requested_t { chunk_t received_nonce; /** - * Packet data of ike_sa_init request + * Selected proposal */ - chunk_t ike_sa_init_request_data; + proposal_t *proposal; /** - * 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. + * Packet data of ike_sa_init request */ - u_int16_t dh_group_priority; + chunk_t ike_sa_init_request_data; /** * 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; + 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; } - /* the peer has to select only one proposal */ - if (proposal_count != 1) + + /* 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) { - 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; + proposal->destroy(proposal); } + proposal_list->destroy(proposal_list); - /* 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) + 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); } diff --git a/Source/charon/sa/states/ike_sa_init_requested.h b/Source/charon/sa/states/ike_sa_init_requested.h index 7d4df6ba8..1fe0a6d1d 100644 --- a/Source/charon/sa/states/ike_sa_init_requested.h +++ b/Source/charon/sa/states/ike_sa_init_requested.h @@ -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); diff --git a/Source/charon/sa/states/ike_sa_init_responded.c b/Source/charon/sa/states/ike_sa_init_responded.c index 2c21992e6..536041d0d 100644 --- a/Source/charon/sa/states/ike_sa_init_responded.c +++ b/Source/charon/sa/states/ike_sa_init_responded.c @@ -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 */ diff --git a/Source/charon/sa/states/initiator_init.c b/Source/charon/sa/states/initiator_init.c index 6ab698f89..f27dcb559 100644 --- a/Source/charon/sa/states/initiator_init.c +++ b/Source/charon/sa/states/initiator_init.c @@ -58,17 +58,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; diff --git a/Source/charon/sa/states/responder_init.c b/Source/charon/sa/states/responder_init.c index 2ea5b034d..c85f12efc 100644 --- a/Source/charon/sa/states/responder_init.c +++ b/Source/charon/sa/states/responder_init.c @@ -80,6 +80,11 @@ struct private_responder_init_t { chunk_t received_nonce; /** + * Selected proposal + */ + proposal_t *proposal; + + /** * Logger used to log data . * * Is logger of ike_sa! @@ -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) + proposal_list = sa_request->get_proposals (sa_request); + + /* select proposal */ + this->proposal = init_config->select_proposal(init_config, proposal_list); + while(proposal_list->remove_last(proposal_list, (void**)&proposal) == 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->destroy(proposal); } - - status = init_config->select_proposal(init_config, ike_proposals,proposal_count,&(selected_proposal)); - allocator_free(ike_proposals); - if (status != SUCCESS) + 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); } |