2005-11-08 13:33:28 +00:00
/**
* @ file ike_sa . c
2005-11-09 09:11:06 +00:00
*
2005-11-29 08:08:03 +00:00
* @ brief Implementation of ike_sa_t .
2005-11-09 09:11:06 +00:00
*
2005-11-08 13:33:28 +00:00
*/
/*
* Copyright ( C ) 2005 Jan Hutter , Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software ; you can redistribute it and / or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation ; either version 2 of the License , or ( at your
* option ) any later version . See < http : //www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful , but
* WITHOUT ANY WARRANTY ; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE . See the GNU General Public License
* for more details .
*/
2005-11-11 13:52:11 +00:00
# include "ike_sa.h"
2005-11-23 09:24:35 +00:00
# include <types.h>
2005-11-29 10:25:07 +00:00
# include <daemon.h>
2005-11-23 09:24:35 +00:00
# include <definitions.h>
# include <utils/allocator.h>
# include <utils/linked_list.h>
# include <utils/logger_manager.h>
# include <utils/randomizer.h>
# include <transforms/diffie_hellman.h>
# include <transforms/prf_plus.h>
2005-11-28 15:20:51 +00:00
# include <transforms/crypters/crypter.h>
2005-11-23 09:57:18 +00:00
# include <encoding/payloads/sa_payload.h>
# include <encoding/payloads/nonce_payload.h>
# include <encoding/payloads/ke_payload.h>
# include <encoding/payloads/transform_substructure.h>
# include <encoding/payloads/transform_attribute.h>
2005-11-23 10:11:50 +00:00
# include <sa/states/initiator_init.h>
# include <sa/states/responder_init.h>
2005-11-24 16:22:04 +00:00
# include <queues/jobs/delete_ike_sa_job.h>
2005-11-08 13:33:28 +00:00
2005-11-18 10:31:56 +00:00
2005-11-08 13:33:28 +00:00
2005-11-25 13:42:02 +00:00
typedef struct private_ike_sa_t private_ike_sa_t ;
/**
* Private data of an ike_sa_t object .
*/
struct private_ike_sa_t {
/**
* Protected part of a ike_sa_t object .
*/
protected_ike_sa_t protected ;
/**
* Creates a job to delete the given IKE_SA .
*
* @ param this calling object
*/
status_t ( * create_delete_job ) ( private_ike_sa_t * this ) ;
/**
* 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
*/
ike_sa_id_t * ike_sa_id ;
/**
* Linked List containing the child sa ' s of the current IKE_SA
*/
linked_list_t * child_sas ;
2005-12-01 17:16:10 +00:00
/**
* TODO
*/
init_config_t * init_config ;
/**
* TODO
*/
sa_config_t * sa_config ;
2005-11-25 13:42:02 +00:00
/**
* Current state of the IKE_SA
*/
state_t * current_state ;
/**
* this SA ' s source for random data
*/
randomizer_t * randomizer ;
/**
* contains the last responded message
*
*/
message_t * last_responded_message ;
/**
* contains the last requested message
*
*/
message_t * last_requested_message ;
/**
* Informations of this host
*/
struct {
host_t * host ;
} me ;
/**
* Informations of the other host
*/
struct {
host_t * host ;
} other ;
/**
* Crypter object for initiator
*/
crypter_t * crypter_initiator ;
/**
* Crypter object for responder
*/
crypter_t * crypter_responder ;
/**
* Signer object for initiator
*/
signer_t * signer_initiator ;
/**
* Signer object for responder
*/
signer_t * signer_responder ;
/**
* prf function
*/
prf_t * prf ;
/**
* Shared secrets
*/
struct {
/**
* Key used for deriving other keys
*/
chunk_t d_key ;
/**
* Key for authenticate ( initiator )
*/
chunk_t ai_key ;
/**
* Key for authenticate ( responder )
*/
chunk_t ar_key ;
/**
* Key for encryption ( initiator )
*/
chunk_t ei_key ;
/**
* Key for encryption ( responder )
*/
chunk_t er_key ;
/**
* Key for generating auth payload ( initiator )
*/
chunk_t pi_key ;
/**
* Key for generating auth payload ( responder )
*/
chunk_t pr_key ;
} secrets ;
/**
* next message id to receive
*/
u_int32_t message_id_in ;
/**
* next message id to send
*/
u_int32_t message_id_out ;
/**
* a logger for this IKE_SA
*/
logger_t * logger ;
} ;
2005-11-08 13:33:28 +00:00
/**
2005-11-28 20:29:47 +00:00
* Implements protected_ike_sa_t . process_message .
2005-11-08 13:33:28 +00:00
*/
2005-11-25 13:42:02 +00:00
static status_t process_message ( private_ike_sa_t * this , message_t * message )
2005-11-28 20:29:47 +00:00
{
2005-11-18 14:56:34 +00:00
u_int32_t message_id ;
2005-11-21 10:59:45 +00:00
exchange_type_t exchange_type ;
2005-11-21 16:41:24 +00:00
bool is_request ;
/* we must process each request or response from remote host */
2005-11-21 10:59:45 +00:00
/* find out type of message (request or response) */
2005-11-18 15:10:19 +00:00
is_request = message - > get_request ( message ) ;
2005-11-21 10:59:45 +00:00
exchange_type = message - > get_exchange_type ( message ) ;
2005-11-27 14:04:16 +00:00
this - > logger - > log ( this - > logger , CONTROL , " Process %s message of exchange type %s " , ( is_request ) ? " REQUEST " : " RESPONSE " , mapping_find ( exchange_type_m , exchange_type ) ) ;
2005-11-21 10:59:45 +00:00
message_id = message - > get_message_id ( message ) ;
2005-11-18 15:10:19 +00:00
2005-11-21 10:59:45 +00:00
/*
* It has to be checked , if the message has to be resent cause of lost packets !
*/
2005-11-28 20:29:47 +00:00
if ( is_request & & ( message_id = = ( this - > message_id_in - 1 ) ) )
2005-11-21 10:59:45 +00:00
{
/* message can be resent ! */
this - > logger - > log ( this - > logger , CONTROL | MORE , " Resent message detected. Send stored reply " ) ;
return ( this - > resend_last_reply ( this ) ) ;
}
2005-11-18 14:56:34 +00:00
2005-11-21 10:59:45 +00:00
/* Now, the message id is checked for request AND reply */
if ( is_request )
{
/* In a request, the message has to be this->message_id_in (other case is already handled) */
if ( message_id ! = this - > message_id_in )
{
this - > logger - > log ( this - > logger , ERROR | MORE , " Message request with message id %d received, but %d expected " , message_id , this - > message_id_in ) ;
return FAILED ;
}
}
else
{
/* In a reply, the message has to be this->message_id_out -1 cause it is the reply to the last sent message*/
if ( message_id ! = ( this - > message_id_out - 1 ) )
{
this - > logger - > log ( this - > logger , ERROR | MORE , " Message reply with message id %d received, but %d expected " , message_id , this - > message_id_in ) ;
return FAILED ;
}
}
2005-11-18 14:56:34 +00:00
2005-11-21 16:41:24 +00:00
/* now the message is processed by the current state object */
2005-11-25 13:42:02 +00:00
/* the current state does change the current change to the next one*/
2005-11-28 20:29:47 +00:00
return this - > current_state - > process_message ( this - > current_state , message ) ;
2005-11-18 10:31:56 +00:00
}
2005-11-21 10:59:45 +00:00
/**
2005-11-28 20:29:47 +00:00
* Implements protected_ike_sa_t . build_message .
2005-11-21 10:59:45 +00:00
*/
2005-11-28 20:29:47 +00:00
static void build_message ( private_ike_sa_t * this , exchange_type_t type , bool request , message_t * * message )
2005-11-18 12:01:53 +00:00
{
2005-11-18 13:59:21 +00:00
message_t * new_message ;
2005-11-18 12:01:53 +00:00
host_t * source , * destination ;
2005-11-21 10:59:45 +00:00
2005-11-27 14:04:16 +00:00
this - > logger - > log ( this - > logger , CONTROL | MORE , " build empty message " ) ;
2005-11-18 13:59:21 +00:00
new_message = message_create ( ) ;
2005-11-21 10:59:45 +00:00
2005-11-28 20:29:47 +00:00
source = this - > me . host - > clone ( this - > me . host ) ;
destination = this - > other . host - > clone ( this - > other . host ) ;
2005-11-18 13:59:21 +00:00
new_message - > set_source ( new_message , source ) ;
new_message - > set_destination ( new_message , destination ) ;
new_message - > set_exchange_type ( new_message , type ) ;
new_message - > set_request ( new_message , request ) ;
2005-11-21 10:59:45 +00:00
new_message - > set_message_id ( new_message , ( request ) ? this - > message_id_out : this - > message_id_in ) ;
2005-11-28 16:55:46 +00:00
new_message - > set_ike_sa_id ( new_message , this - > ike_sa_id ) ;
2005-11-18 13:59:21 +00:00
* message = new_message ;
2005-11-18 12:01:53 +00:00
}
2005-11-21 10:59:45 +00:00
/**
2005-11-28 20:29:47 +00:00
* Implements protected_ike_sa_t . process_configuration .
2005-11-21 10:59:45 +00:00
*/
2005-11-25 13:42:02 +00:00
static status_t initialize_connection ( private_ike_sa_t * this , char * name )
2005-11-18 13:59:21 +00:00
{
2005-11-21 16:41:24 +00:00
/* work is done in state object of type INITIATOR_INIT */
initiator_init_t * current_state ;
2005-11-18 14:56:34 +00:00
status_t status ;
2005-11-21 13:45:26 +00:00
2005-11-21 16:41:24 +00:00
if ( this - > current_state - > get_state ( this - > current_state ) ! = INITIATOR_INIT )
2005-11-18 14:56:34 +00:00
{
return FAILED ;
}
2005-11-21 16:41:24 +00:00
current_state = ( initiator_init_t * ) this - > current_state ;
2005-11-18 14:56:34 +00:00
2005-11-25 13:42:02 +00:00
status = current_state - > initiate_connection ( current_state , name ) ;
2005-12-01 17:16:10 +00:00
2005-11-21 16:41:24 +00:00
return status ;
2005-11-08 13:33:28 +00:00
}
2005-11-08 16:24:18 +00:00
/**
2005-11-28 20:29:47 +00:00
* Implements protected_ike_sa_t . get_id .
2005-11-08 16:24:18 +00:00
*/
2005-11-25 13:42:02 +00:00
static ike_sa_id_t * get_id ( private_ike_sa_t * this )
2005-11-08 16:24:18 +00:00
{
return this - > ike_sa_id ;
}
2005-11-28 15:20:51 +00:00
/**
2005-11-28 20:29:47 +00:00
* Implements protected_ike_sa_t . compute_secrets .
2005-11-28 15:20:51 +00:00
*/
2005-11-28 20:29:47 +00:00
static void compute_secrets ( private_ike_sa_t * this , chunk_t dh_shared_secret , chunk_t initiator_nonce , chunk_t responder_nonce )
2005-11-22 15:38:41 +00:00
{
chunk_t concatenated_nonces ;
chunk_t skeyseed ;
chunk_t prf_plus_seed ;
u_int64_t initiator_spi ;
u_int64_t responder_spi ;
prf_plus_t * prf_plus ;
2005-11-28 15:20:51 +00:00
2005-11-22 15:38:41 +00:00
/*
* TODO check length for specific prf ' s
*/
concatenated_nonces . len = ( initiator_nonce . len + responder_nonce . len ) ;
concatenated_nonces . ptr = allocator_alloc ( concatenated_nonces . len ) ;
2005-11-28 20:29:47 +00:00
2005-11-22 15:38:41 +00:00
/* 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 ) ;
2005-11-23 07:17:54 +00:00
this - > logger - > log_chunk ( this - > logger , RAW , " Nonce data " , & concatenated_nonces ) ;
2005-11-22 15:38:41 +00:00
/* status of set_key is not checked */
2005-11-28 20:29:47 +00:00
this - > prf - > set_key ( this - > prf , concatenated_nonces ) ;
this - > prf - > allocate_bytes ( this - > prf , dh_shared_secret , & skeyseed ) ;
2005-11-22 15:38:41 +00:00
2005-11-25 08:11:49 +00:00
allocator_free_chunk ( & concatenated_nonces ) ;
2005-11-22 15:38:41 +00:00
prf_plus_seed . len = ( initiator_nonce . len + responder_nonce . len + 16 ) ;
prf_plus_seed . ptr = allocator_alloc ( prf_plus_seed . len ) ;
2005-11-28 15:20:51 +00:00
2005-11-22 15:38:41 +00:00
/* 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 ) ;
2005-11-28 15:20:51 +00:00
this - > logger - > log_chunk ( this - > logger , PRIVATE | MORE , " Keyseed " , & skeyseed ) ;
this - > logger - > log_chunk ( this - > logger , PRIVATE | MORE , " PRF+ Seed " , & prf_plus_seed ) ;
2005-11-22 15:38:41 +00:00
this - > logger - > log ( this - > logger , CONTROL | MOST , " Set new key of prf object " ) ;
2005-11-28 20:29:47 +00:00
this - > prf - > set_key ( this - > prf , skeyseed ) ;
2005-11-25 08:11:49 +00:00
allocator_free_chunk ( & skeyseed ) ;
2005-11-28 20:29:47 +00:00
2005-11-22 15:38:41 +00:00
this - > logger - > log ( this - > logger , CONTROL | MOST , " Create new prf+ object " ) ;
prf_plus = prf_plus_create ( this - > prf , prf_plus_seed ) ;
2005-11-25 08:11:49 +00:00
allocator_free_chunk ( & prf_plus_seed ) ;
2005-11-22 15:38:41 +00:00
2005-11-28 20:29:47 +00:00
prf_plus - > allocate_bytes ( prf_plus , this - > prf - > get_block_size ( this - > prf ) , & ( this - > secrets . d_key ) ) ;
2005-11-28 15:20:51 +00:00
this - > logger - > log_chunk ( this - > logger , PRIVATE , " Sk_d secret " , & ( this - > secrets . d_key ) ) ;
2005-11-29 17:19:59 +00:00
prf_plus - > allocate_bytes ( prf_plus , this - > signer_initiator - > get_key_size ( this - > signer_initiator ) , & ( this - > secrets . ai_key ) ) ;
this - > logger - > log_chunk ( this - > logger , PRIVATE , " Sk_ai secret " , & ( this - > secrets . ai_key ) ) ;
this - > signer_initiator - > set_key ( this - > signer_initiator , this - > secrets . ai_key ) ;
prf_plus - > allocate_bytes ( prf_plus , this - > signer_responder - > get_key_size ( this - > signer_responder ) , & ( this - > secrets . ar_key ) ) ;
this - > logger - > log_chunk ( this - > logger , PRIVATE , " Sk_ar secret " , & ( this - > secrets . ar_key ) ) ;
this - > signer_responder - > set_key ( this - > signer_responder , this - > secrets . ar_key ) ;
2005-11-28 20:29:47 +00:00
prf_plus - > allocate_bytes ( prf_plus , this - > crypter_initiator - > get_block_size ( this - > crypter_initiator ) , & ( this - > secrets . ei_key ) ) ;
2005-11-28 15:20:51 +00:00
this - > logger - > log_chunk ( this - > logger , PRIVATE , " Sk_ei secret " , & ( this - > secrets . ei_key ) ) ;
2005-11-28 20:29:47 +00:00
this - > crypter_initiator - > set_key ( this - > crypter_initiator , this - > secrets . ei_key ) ;
2005-11-28 15:20:51 +00:00
2005-11-28 20:29:47 +00:00
prf_plus - > allocate_bytes ( prf_plus , this - > crypter_responder - > get_block_size ( this - > crypter_responder ) , & ( this - > secrets . er_key ) ) ;
2005-11-28 15:20:51 +00:00
this - > logger - > log_chunk ( this - > logger , PRIVATE , " Sk_er secret " , & ( this - > secrets . er_key ) ) ;
2005-11-28 20:29:47 +00:00
this - > crypter_responder - > set_key ( this - > crypter_responder , this - > secrets . er_key ) ;
2005-11-28 15:20:51 +00:00
2005-11-28 20:29:47 +00:00
prf_plus - > allocate_bytes ( prf_plus , this - > crypter_responder - > get_block_size ( this - > crypter_responder ) , & ( this - > secrets . pi_key ) ) ;
2005-11-28 15:20:51 +00:00
this - > logger - > log_chunk ( this - > logger , PRIVATE , " Sk_pi secret " , & ( this - > secrets . pi_key ) ) ;
2005-11-22 15:38:41 +00:00
2005-11-28 20:29:47 +00:00
prf_plus - > allocate_bytes ( prf_plus , this - > crypter_responder - > get_block_size ( this - > crypter_responder ) , & ( this - > secrets . pr_key ) ) ;
2005-11-28 15:20:51 +00:00
this - > logger - > log_chunk ( this - > logger , PRIVATE , " Sk_pr secret " , & ( this - > secrets . pr_key ) ) ;
2005-11-22 15:38:41 +00:00
prf_plus - > destroy ( prf_plus ) ;
}
2005-11-08 13:33:28 +00:00
/**
2005-11-28 20:29:47 +00:00
* Implements protected_ike_sa_t . resend_last_reply .
2005-11-08 13:33:28 +00:00
*/
2005-11-28 20:29:47 +00:00
static status_t resend_last_reply ( private_ike_sa_t * this )
2005-11-21 10:59:45 +00:00
{
packet_t * packet ;
status_t status ;
2005-11-28 15:43:05 +00:00
status = this - > last_responded_message - > generate ( this - > last_responded_message , NULL , NULL , & packet ) ;
2005-11-21 10:59:45 +00:00
if ( status ! = SUCCESS )
{
this - > logger - > log ( this - > logger , ERROR , " Could not generate message to resent " ) ;
return status ;
}
2005-11-29 10:25:07 +00:00
charon - > send_queue - > add ( charon - > send_queue , packet ) ;
2005-11-21 10:59:45 +00:00
return SUCCESS ;
}
2005-11-28 20:29:47 +00:00
/**
* Implements protected_ike_sa_t . resend_last_reply .
*/
static status_t create_delete_job ( private_ike_sa_t * this )
2005-11-21 10:59:45 +00:00
{
job_t * delete_job ;
this - > logger - > log ( this - > logger , CONTROL | MORE , " Going to create job to delete this IKE_SA " ) ;
delete_job = ( job_t * ) delete_ike_sa_job_create ( this - > ike_sa_id ) ;
2005-11-29 10:25:07 +00:00
charon - > job_queue - > add ( charon - > job_queue , delete_job ) ;
2005-11-28 20:29:47 +00:00
2005-11-21 10:59:45 +00:00
return SUCCESS ;
}
2005-11-25 13:42:02 +00:00
/**
* Implementation of protected_ike_sa_t . set_new_state .
*/
static void set_new_state ( private_ike_sa_t * this , state_t * state )
{
2005-11-28 15:20:51 +00:00
this - > logger - > log ( this - > logger , ERROR , " Change current state %s to %s " , mapping_find ( ike_sa_state_m , this - > current_state - > get_state ( this - > current_state ) ) , mapping_find ( ike_sa_state_m , state - > get_state ( state ) ) ) ;
2005-11-25 13:42:02 +00:00
this - > current_state = state ;
}
/**
* Implementation of protected_ike_sa_t . get_logger .
*/
static logger_t * get_logger ( private_ike_sa_t * this )
{
return this - > logger ;
}
/**
* Implementation of protected_ike_sa_t . get_my_host .
*/
static host_t * get_my_host ( private_ike_sa_t * this )
{
return this - > me . host ;
}
/**
* Implementation of protected_ike_sa_t . get_other_host .
*/
static host_t * get_other_host ( private_ike_sa_t * this )
{
return this - > other . host ;
}
2005-12-01 17:16:10 +00:00
/**
* Implementation of protected_ike_sa_t . get_init_config .
*/
static init_config_t * get_init_config ( private_ike_sa_t * this )
{
return this - > init_config ;
}
/**
* Implementation of protected_ike_sa_t . set_init_config .
*/
static void set_init_config ( private_ike_sa_t * this , init_config_t * init_config )
{
this - > init_config = init_config ;
}
/**
* Implementation of protected_ike_sa_t . get_sa_config .
*/
static sa_config_t * get_sa_config ( private_ike_sa_t * this )
{
return this - > sa_config ;
}
/**
* Implementation of protected_ike_sa_t . set_sa_config .
*/
static void set_sa_config ( private_ike_sa_t * this , sa_config_t * sa_config )
{
this - > sa_config = sa_config ;
}
2005-11-25 13:42:02 +00:00
/**
* Implementation of protected_ike_sa_t . set_my_host .
*/
static void set_my_host ( private_ike_sa_t * this , host_t * my_host )
{
this - > me . host = my_host ;
}
/**
* Implementation of protected_ike_sa_t . set_other_host .
*/
static void set_other_host ( private_ike_sa_t * this , host_t * other_host )
{
this - > other . host = other_host ;
}
/**
* Implementation of protected_ike_sa_t . set_prf .
*/
2005-12-01 17:16:10 +00:00
static status_t create_transforms_from_proposal ( private_ike_sa_t * this , ike_proposal_t * proposal )
2005-11-25 13:42:02 +00:00
{
2005-11-28 20:29:47 +00:00
this - > logger - > log ( this - > logger , CONTROL | MORE , " Going to create transform objects for proposal " ) ;
2005-11-28 15:20:51 +00:00
2005-12-01 17:16:10 +00:00
this - > logger - > log ( this - > logger , CONTROL | MORE , " 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 | MORE , " 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 | MORE , " prf: %s with keylength %d " , mapping_find ( pseudo_random_function_m , proposal - > pseudo_random_function ) , proposal - > pseudo_random_function_key_length ) ;
2005-11-28 15:20:51 +00:00
2005-11-25 13:42:02 +00:00
if ( this - > prf ! = NULL )
{
this - > prf - > destroy ( this - > prf ) ;
}
2005-12-01 17:16:10 +00:00
this - > prf = prf_create ( proposal - > pseudo_random_function ) ;
2005-11-28 15:20:51 +00:00
if ( this - > prf = = NULL )
{
2005-11-28 20:29:47 +00:00
this - > logger - > log ( this - > logger , ERROR | MORE , " prf not supported! " ) ;
2005-11-28 15:20:51 +00:00
return FAILED ;
}
if ( this - > crypter_initiator ! = NULL )
{
this - > crypter_initiator - > destroy ( this - > crypter_initiator ) ;
}
2005-12-01 17:16:10 +00:00
this - > crypter_initiator = crypter_create ( proposal - > encryption_algorithm , proposal - > encryption_algorithm_key_length ) ;
2005-11-28 15:20:51 +00:00
if ( this - > crypter_initiator = = NULL )
{
2005-11-28 20:29:47 +00:00
this - > logger - > log ( this - > logger , ERROR | MORE , " encryption algorithm not supported! " ) ;
2005-11-28 15:20:51 +00:00
return FAILED ;
}
if ( this - > crypter_responder ! = NULL )
{
this - > crypter_responder - > destroy ( this - > crypter_responder ) ;
}
2005-12-01 17:16:10 +00:00
this - > crypter_responder = crypter_create ( proposal - > encryption_algorithm , proposal - > encryption_algorithm_key_length ) ;
2005-11-28 15:20:51 +00:00
if ( this - > crypter_responder = = NULL )
{
2005-11-28 20:29:47 +00:00
this - > logger - > log ( this - > logger , ERROR | MORE , " encryption algorithm not supported! " ) ;
2005-11-28 15:20:51 +00:00
return FAILED ;
}
if ( this - > signer_initiator ! = NULL )
{
this - > signer_initiator - > destroy ( this - > signer_initiator ) ;
}
2005-12-01 17:16:10 +00:00
this - > signer_initiator = signer_create ( proposal - > integrity_algorithm ) ;
2005-11-28 15:20:51 +00:00
if ( this - > signer_initiator = = NULL )
{
2005-11-28 20:29:47 +00:00
this - > logger - > log ( this - > logger , ERROR | MORE , " integrity algorithm not supported! " ) ;
2005-11-28 15:20:51 +00:00
return FAILED ;
}
if ( this - > signer_responder ! = NULL )
{
this - > signer_responder - > destroy ( this - > signer_responder ) ;
}
2005-12-01 17:16:10 +00:00
this - > signer_responder = signer_create ( proposal - > integrity_algorithm ) ;
2005-11-28 15:20:51 +00:00
if ( this - > signer_responder = = NULL )
{
2005-11-28 20:29:47 +00:00
this - > logger - > log ( this - > logger , ERROR | MORE , " integrity algorithm not supported! " ) ;
2005-11-28 15:20:51 +00:00
return FAILED ;
}
return SUCCESS ;
2005-11-25 13:42:02 +00:00
}
/**
* Implementation of protected_ike_sa_t . get_randomizer .
*/
static randomizer_t * get_randomizer ( private_ike_sa_t * this )
{
return this - > randomizer ;
}
2005-11-29 17:19:59 +00:00
/**
* Implementation of protected_ike_sa_t . get_crypter_initiator .
*/
static crypter_t * get_crypter_initiator ( private_ike_sa_t * this )
{
return this - > crypter_initiator ;
}
/**
* Implementation of protected_ike_sa_t . get_signer_initiator .
*/
static signer_t * get_signer_initiator ( private_ike_sa_t * this )
{
return this - > signer_initiator ;
}
2005-12-02 12:38:55 +00:00
/**
* Implementation of protected_ike_sa_t . get_crypter_responder .
*/
static crypter_t * get_crypter_responder ( private_ike_sa_t * this )
{
return this - > crypter_responder ;
}
/**
* Implementation of protected_ike_sa_t . get_signer_responder .
*/
static signer_t * get_signer_responder ( private_ike_sa_t * this )
{
return this - > signer_responder ;
}
2005-11-25 13:42:02 +00:00
/**
* Implementation of protected_ike_sa_t . set_last_requested_message .
*/
static status_t set_last_requested_message ( private_ike_sa_t * this , message_t * message )
{
2005-11-28 20:29:47 +00:00
if ( this - > last_requested_message ! = NULL )
2005-11-25 13:42:02 +00:00
{
/* destroy message */
this - > last_requested_message - > destroy ( this - > last_requested_message ) ;
}
if ( message - > get_message_id ( message ) ! = this - > message_id_out )
{
2005-11-28 20:29:47 +00:00
this - > logger - > log ( this - > logger , CONTROL | MOST , " last requested message could not be set cause id was not as expected " ) ;
2005-11-25 13:42:02 +00:00
return FAILED ;
}
2005-11-28 20:29:47 +00:00
this - > logger - > log ( this - > logger , CONTROL | MOST , " replace last requested message with new one " ) ;
this - > last_requested_message = message ;
2005-11-25 13:42:02 +00:00
/* message counter can now be increased */
2005-11-28 20:29:47 +00:00
this - > logger - > log ( this - > logger , CONTROL | MOST , " Increate message counter for outgoing messages " ) ;
2005-11-25 13:42:02 +00:00
this - > message_id_out + + ;
return SUCCESS ;
}
/**
* Implementation of protected_ike_sa_t . set_last_responded_message .
*/
static status_t set_last_responded_message ( private_ike_sa_t * this , message_t * message )
{
2005-11-28 20:29:47 +00:00
if ( this - > last_responded_message ! = NULL )
2005-11-25 13:42:02 +00:00
{
/* destroy message */
this - > last_responded_message - > destroy ( this - > last_responded_message ) ;
}
if ( message - > get_message_id ( message ) ! = this - > message_id_in )
{
2005-11-28 20:29:47 +00:00
this - > logger - > log ( this - > logger , CONTROL | MOST , " last responded message could not be set cause id was not as expected " ) ;
2005-11-25 13:42:02 +00:00
return FAILED ;
}
2005-11-28 20:29:47 +00:00
this - > logger - > log ( this - > logger , CONTROL | MOST , " replace last responded message with new one " ) ;
this - > last_responded_message = message ;
2005-11-25 13:42:02 +00:00
/* message counter can now be increased */
2005-11-28 20:29:47 +00:00
this - > logger - > log ( this - > logger , CONTROL | MOST , " Increate message counter for incoming messages " ) ;
2005-11-25 13:42:02 +00:00
this - > message_id_in + + ;
return SUCCESS ;
}
2005-12-02 11:38:56 +00:00
/**
* Implementation of protected_ike_sa_t . destroy .
*/
static void reset_message_buffers ( private_ike_sa_t * this )
{
this - > logger - > log ( this - > logger , CONTROL | MOST , " Reset message counters and destroy stored messages " ) ;
/* destroy stored requested message */
if ( this - > last_requested_message ! = NULL )
{
this - > last_requested_message - > destroy ( this - > last_requested_message ) ;
this - > last_requested_message = NULL ;
}
/* destroy stored responded messages */
if ( this - > last_responded_message ! = NULL )
{
this - > last_responded_message - > destroy ( this - > last_responded_message ) ;
this - > last_responded_message = NULL ;
}
this - > message_id_out = 0 ;
this - > message_id_in = 0 ;
}
2005-11-25 13:42:02 +00:00
2005-11-16 16:05:46 +00:00
/**
2005-12-02 11:38:56 +00:00
* Implementation of protected_ike_sa_t . destroy .
2005-11-16 16:05:46 +00:00
*/
2005-11-28 20:29:47 +00:00
static void destroy ( private_ike_sa_t * this )
2005-11-16 16:05:46 +00:00
{
2005-11-21 09:21:34 +00:00
this - > logger - > log ( this - > logger , CONTROL | MORE , " Going to destroy IKE_SA " ) ;
2005-11-21 16:41:24 +00:00
2005-11-18 14:56:34 +00:00
/* destroy child sa's */
2005-11-21 09:21:34 +00:00
this - > logger - > log ( this - > logger , CONTROL | MOST , " Destroy all child_sa's " ) ;
2005-11-18 14:56:34 +00:00
while ( this - > child_sas - > get_count ( this - > child_sas ) > 0 )
2005-11-16 16:05:46 +00:00
{
2005-11-18 14:56:34 +00:00
void * child_sa ;
2005-11-28 20:29:47 +00:00
if ( this - > child_sas - > remove_first ( this - > child_sas , & child_sa ) ! = SUCCESS )
2005-11-18 14:56:34 +00:00
{
break ;
}
/* destroy child sa */
2005-11-16 16:05:46 +00:00
}
2005-11-08 13:33:28 +00:00
this - > child_sas - > destroy ( this - > child_sas ) ;
2005-11-22 15:38:41 +00:00
this - > logger - > log ( this - > logger , CONTROL | MOST , " Destroy secrets " ) ;
2005-11-28 20:29:47 +00:00
allocator_free ( this - > secrets . d_key . ptr ) ;
allocator_free ( this - > secrets . ai_key . ptr ) ;
allocator_free ( this - > secrets . ar_key . ptr ) ;
allocator_free ( this - > secrets . ei_key . ptr ) ;
allocator_free ( this - > secrets . er_key . ptr ) ;
allocator_free ( this - > secrets . pi_key . ptr ) ;
allocator_free ( this - > secrets . pr_key . ptr ) ;
if ( this - > crypter_initiator ! = NULL )
2005-11-22 15:38:41 +00:00
{
this - > crypter_initiator - > destroy ( this - > crypter_initiator ) ;
}
2005-11-28 20:29:47 +00:00
if ( this - > crypter_responder ! = NULL )
2005-11-22 15:38:41 +00:00
{
this - > crypter_responder - > destroy ( this - > crypter_responder ) ;
}
2005-11-28 20:29:47 +00:00
if ( this - > signer_initiator ! = NULL )
2005-11-22 15:38:41 +00:00
{
this - > signer_initiator - > destroy ( this - > signer_initiator ) ;
}
if ( this - > signer_responder ! = NULL )
{
this - > signer_responder - > destroy ( this - > signer_responder ) ;
}
if ( this - > prf ! = NULL )
{
this - > prf - > destroy ( this - > prf ) ;
}
2005-11-16 16:05:46 +00:00
2005-11-18 14:56:34 +00:00
/* destroy ike_sa_id */
2005-11-16 16:05:46 +00:00
this - > ike_sa_id - > destroy ( this - > ike_sa_id ) ;
2005-11-18 14:56:34 +00:00
2005-11-21 09:21:34 +00:00
/* destroy stored requested message */
if ( this - > last_requested_message ! = NULL )
2005-11-18 14:56:34 +00:00
{
2005-11-21 09:21:34 +00:00
this - > last_requested_message - > destroy ( this - > last_requested_message ) ;
2005-11-18 14:56:34 +00:00
}
2005-12-01 17:16:10 +00:00
/* destroy stored host_t objects */
2005-11-21 17:50:56 +00:00
if ( this - > me . host ! = NULL )
{
this - > me . host - > destroy ( this - > me . host ) ;
}
2005-12-01 17:16:10 +00:00
/* destroy stored host_t objects */
2005-11-21 17:50:56 +00:00
if ( this - > other . host ! = NULL )
{
this - > other . host - > destroy ( this - > other . host ) ;
}
2005-12-01 17:16:10 +00:00
/* destroy stored responded messages */
if ( this - > last_responded_message ! = NULL )
{
this - > last_responded_message - > destroy ( this - > last_responded_message ) ;
}
this - > randomizer - > destroy ( this - > randomizer ) ;
2005-11-21 17:50:56 +00:00
this - > logger - > log ( this - > logger , CONTROL | MOST , " Destroy current state object " ) ;
this - > current_state - > destroy ( this - > current_state ) ;
this - > logger - > log ( this - > logger , CONTROL | MOST , " Destroy logger of IKE_SA " ) ;
2005-11-29 10:25:07 +00:00
charon - > logger_manager - > destroy_logger ( charon - > logger_manager , this - > logger ) ;
2005-11-21 17:50:56 +00:00
allocator_free ( this ) ;
2005-11-08 13:33:28 +00:00
}
/*
* Described in Header
*/
ike_sa_t * ike_sa_create ( ike_sa_id_t * ike_sa_id )
{
2005-11-25 13:42:02 +00:00
private_ike_sa_t * this = allocator_alloc_thing ( private_ike_sa_t ) ;
2005-11-09 09:11:06 +00:00
2005-11-08 13:33:28 +00:00
/* Public functions */
2005-11-25 13:42:02 +00:00
this - > protected . public . process_message = ( status_t ( * ) ( ike_sa_t * , message_t * ) ) process_message ;
this - > protected . public . initialize_connection = ( status_t ( * ) ( ike_sa_t * , char * ) ) initialize_connection ;
this - > protected . public . get_id = ( ike_sa_id_t * ( * ) ( ike_sa_t * ) ) get_id ;
2005-11-28 20:29:47 +00:00
this - > protected . public . destroy = ( void ( * ) ( ike_sa_t * ) ) destroy ;
2005-11-25 13:42:02 +00:00
/* protected functions */
2005-11-28 20:29:47 +00:00
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 ;
2005-11-25 13:42:02 +00:00
this - > protected . get_logger = ( logger_t * ( * ) ( protected_ike_sa_t * ) ) get_logger ;
2005-12-01 17:16:10 +00:00
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 ;
this - > protected . set_sa_config = ( void ( * ) ( protected_ike_sa_t * , sa_config_t * ) ) set_sa_config ;
this - > protected . get_sa_config = ( sa_config_t * ( * ) ( protected_ike_sa_t * ) ) get_sa_config ;
2005-11-25 13:42:02 +00:00
this - > protected . get_my_host = ( host_t * ( * ) ( protected_ike_sa_t * ) ) get_my_host ;
this - > protected . get_other_host = ( host_t * ( * ) ( protected_ike_sa_t * ) ) get_other_host ;
this - > protected . set_my_host = ( void ( * ) ( protected_ike_sa_t * , host_t * ) ) set_my_host ;
this - > protected . set_other_host = ( void ( * ) ( protected_ike_sa_t * , host_t * ) ) set_other_host ;
this - > protected . get_randomizer = ( randomizer_t * ( * ) ( protected_ike_sa_t * ) ) get_randomizer ;
this - > protected . set_last_requested_message = ( status_t ( * ) ( protected_ike_sa_t * , message_t * ) ) set_last_requested_message ;
this - > protected . set_last_responded_message = ( status_t ( * ) ( protected_ike_sa_t * , message_t * ) ) set_last_responded_message ;
2005-12-01 17:16:10 +00:00
this - > protected . create_transforms_from_proposal = ( status_t ( * ) ( protected_ike_sa_t * , ike_proposal_t * ) ) create_transforms_from_proposal ;
2005-11-25 13:42:02 +00:00
this - > protected . set_new_state = ( void ( * ) ( protected_ike_sa_t * , state_t * ) ) set_new_state ;
2005-11-29 17:19:59 +00:00
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 ;
2005-12-02 12:38:55 +00:00
this - > protected . get_crypter_responder = ( crypter_t * ( * ) ( protected_ike_sa_t * ) ) get_crypter_responder ;
this - > protected . get_signer_responder = ( signer_t * ( * ) ( protected_ike_sa_t * ) ) get_signer_responder ;
2005-12-02 11:38:56 +00:00
this - > protected . reset_message_buffers = ( void ( * ) ( protected_ike_sa_t * ) ) reset_message_buffers ;
2005-11-25 13:42:02 +00:00
2005-11-18 14:56:34 +00:00
/* private functions */
2005-11-21 10:59:45 +00:00
this - > resend_last_reply = resend_last_reply ;
this - > create_delete_job = create_delete_job ;
2005-11-25 13:42:02 +00:00
2005-11-16 16:05:46 +00:00
2005-11-29 17:19:59 +00:00
2005-11-08 13:33:28 +00:00
/* initialize private fields */
2005-11-29 10:25:07 +00:00
this - > logger = charon - > logger_manager - > create_logger ( charon - > logger_manager , IKE_SA , NULL ) ;
2005-11-21 09:21:34 +00:00
2005-11-28 20:29:47 +00:00
this - > ike_sa_id = ike_sa_id - > clone ( ike_sa_id ) ;
2005-11-08 13:33:28 +00:00
this - > child_sas = linked_list_create ( ) ;
2005-11-16 16:05:46 +00:00
this - > randomizer = randomizer_create ( ) ;
2005-11-16 17:16:35 +00:00
this - > me . host = NULL ;
this - > other . host = NULL ;
2005-11-21 09:21:34 +00:00
this - > last_requested_message = NULL ;
this - > last_responded_message = NULL ;
2005-11-18 12:01:53 +00:00
this - > message_id_out = 0 ;
this - > message_id_in = 0 ;
2005-11-28 20:29:47 +00:00
this - > secrets . d_key = CHUNK_INITIALIZER ;
this - > secrets . ai_key = CHUNK_INITIALIZER ;
this - > secrets . ar_key = CHUNK_INITIALIZER ;
this - > secrets . ei_key = CHUNK_INITIALIZER ;
this - > secrets . er_key = CHUNK_INITIALIZER ;
this - > secrets . pi_key = CHUNK_INITIALIZER ;
this - > secrets . pr_key = CHUNK_INITIALIZER ;
2005-11-22 15:38:41 +00:00
this - > crypter_initiator = NULL ;
this - > crypter_responder = NULL ;
this - > signer_initiator = NULL ;
this - > signer_responder = NULL ;
this - > prf = NULL ;
2005-12-01 17:16:10 +00:00
this - > init_config = NULL ;
this - > sa_config = NULL ;
2005-11-22 15:38:41 +00:00
2005-11-21 16:41:24 +00:00
/* at creation time, IKE_SA is in a initiator state */
if ( ike_sa_id - > is_initiator ( ike_sa_id ) )
{
2005-11-25 13:42:02 +00:00
this - > current_state = ( state_t * ) initiator_init_create ( & ( this - > protected ) ) ;
2005-11-21 16:41:24 +00:00
}
else
{
2005-11-25 13:42:02 +00:00
this - > current_state = ( state_t * ) responder_init_create ( & ( this - > protected ) ) ;
2005-11-21 16:41:24 +00:00
}
2005-11-25 13:42:02 +00:00
return & ( this - > protected . public ) ;
2005-11-08 13:33:28 +00:00
}