- allocator_free_chunk changed
[strongswan.git] / Source / charon / sa / ike_sa.c
1 /**
2 * @file ike_sa.c
3 *
4 * @brief Class ike_sa_t. An object of this type is managed by an
5 * ike_sa_manager_t object and represents an IKE_SA
6 *
7 */
8
9 /*
10 * Copyright (C) 2005 Jan Hutter, Martin Willi
11 * Hochschule fuer Technik Rapperswil
12 *
13 * This program is free software; you can redistribute it and/or modify it
14 * under the terms of the GNU General Public License as published by the
15 * Free Software Foundation; either version 2 of the License, or (at your
16 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
17 *
18 * This program is distributed in the hope that it will be useful, but
19 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
20 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 * for more details.
22 */
23
24 #include "ike_sa.h"
25
26 #include <types.h>
27 #include <globals.h>
28 #include <definitions.h>
29 #include <utils/allocator.h>
30 #include <utils/linked_list.h>
31 #include <utils/logger_manager.h>
32 #include <utils/randomizer.h>
33 #include <transforms/diffie_hellman.h>
34 #include <transforms/prf_plus.h>
35 #include <encoding/payloads/sa_payload.h>
36 #include <encoding/payloads/nonce_payload.h>
37 #include <encoding/payloads/ke_payload.h>
38 #include <encoding/payloads/transform_substructure.h>
39 #include <encoding/payloads/transform_attribute.h>
40 #include <sa/states/initiator_init.h>
41 #include <sa/states/responder_init.h>
42 #include <queues/jobs/delete_ike_sa_job.h>
43
44
45
46
47 /**
48 * @brief implements function process_message of protected_ike_sa_t
49 */
50 static status_t process_message (protected_ike_sa_t *this, message_t *message)
51 {
52 u_int32_t message_id;
53 exchange_type_t exchange_type;
54 bool is_request;
55 status_t status;
56 state_t *new_state;
57
58 /* we must process each request or response from remote host */
59
60 /* find out type of message (request or response) */
61 is_request = message->get_request(message);
62 exchange_type = message->get_exchange_type(message);
63
64 this->logger->log(this->logger, CONTROL|MORE, "Process %s message of exchange type %s",(is_request) ? "REQUEST" : "RESPONSE",mapping_find(exchange_type_m,exchange_type));
65
66 message_id = message->get_message_id(message);
67
68 /*
69 * It has to be checked, if the message has to be resent cause of lost packets!
70 */
71 if (is_request && ( message_id == (this->message_id_in - 1)))
72 {
73 /* message can be resent ! */
74 this->logger->log(this->logger, CONTROL|MORE, "Resent message detected. Send stored reply");
75 return (this->resend_last_reply(this));
76 }
77
78 /* Now, the message id is checked for request AND reply */
79 if (is_request)
80 {
81 /* In a request, the message has to be this->message_id_in (other case is already handled) */
82 if (message_id != this->message_id_in)
83 {
84 this->logger->log(this->logger, ERROR | MORE, "Message request with message id %d received, but %d expected",message_id,this->message_id_in);
85 return FAILED;
86 }
87 }
88 else
89 {
90 /* In a reply, the message has to be this->message_id_out -1 cause it is the reply to the last sent message*/
91 if (message_id != (this->message_id_out - 1))
92 {
93 this->logger->log(this->logger, ERROR | MORE, "Message reply with message id %d received, but %d expected",message_id,this->message_id_in);
94 return FAILED;
95 }
96 }
97
98 /* now the message is processed by the current state object */
99 status = this->current_state->process_message(this->current_state,message,&new_state);
100
101 if (status == SUCCESS)
102 {
103 this->current_state = new_state;
104 }
105 return status;
106 }
107
108 /**
109 * @brief Implements function build_message of protected_ike_sa_t.
110 */
111 static status_t build_message(protected_ike_sa_t *this, exchange_type_t type, bool request, message_t **message)
112 {
113 status_t status;
114 message_t *new_message;
115 host_t *source, *destination;
116
117 this ->logger->log(this->logger, CONTROL|MORE, "build empty message");
118 new_message = message_create();
119 if (new_message == NULL)
120 {
121 this->logger->log(this->logger, ERROR, "Fatal error: could not create empty message object");
122 return OUT_OF_RES;
123 }
124
125 status = this->me.host->clone(this->me.host, &source);
126 if (status != SUCCESS)
127 {
128 this->logger->log(this->logger, ERROR, "Fatal error: could not clone my host information");
129 new_message->destroy(new_message);
130 return status;
131 }
132 status = this->other.host->clone(this->other.host, &destination);
133 if (status != SUCCESS)
134 {
135 this->logger->log(this->logger, ERROR, "Fatal error: could not clone other host information");
136 source->destroy(source);
137 new_message->destroy(new_message);
138 return status;
139 }
140
141 new_message->set_source(new_message, source);
142 new_message->set_destination(new_message, destination);
143
144 new_message->set_exchange_type(new_message, type);
145 new_message->set_request(new_message, request);
146
147 new_message->set_message_id(new_message, (request) ? this->message_id_out : this->message_id_in);
148
149 status = new_message->set_ike_sa_id(new_message, this->ike_sa_id);
150 if (status != SUCCESS)
151 {
152 this->logger->log(this->logger, ERROR, "Fatal error: could not set ike_sa_id of message");
153 new_message->destroy(new_message);
154 return status;
155 }
156
157 *message = new_message;
158
159 return SUCCESS;
160 }
161
162 /**
163 * @brief implements function process_configuration of protected_ike_sa_t
164 */
165 static status_t initialize_connection(protected_ike_sa_t *this, char *name)
166 {
167 /* work is done in state object of type INITIATOR_INIT */
168 initiator_init_t *current_state;
169 status_t status;
170 state_t *new_state;
171
172 if (this->current_state->get_state(this->current_state) != INITIATOR_INIT)
173 {
174 return FAILED;
175 }
176
177 current_state = (initiator_init_t *) this->current_state;
178
179 status = current_state->initiate_connection(current_state,name,&new_state);
180
181 if (status == SUCCESS)
182 {
183 this->current_state = new_state;
184 }
185 else
186 {
187 this->create_delete_job(this);
188 }
189 return status;
190 }
191
192 /**
193 * @brief implements function protected_ike_sa_t.get_id
194 */
195 static ike_sa_id_t* get_id(protected_ike_sa_t *this)
196 {
197 return this->ike_sa_id;
198 }
199
200 static status_t compute_secrets (protected_ike_sa_t *this,chunk_t dh_shared_secret,chunk_t initiator_nonce, chunk_t responder_nonce)
201 {
202 chunk_t concatenated_nonces;
203 chunk_t skeyseed;
204 chunk_t prf_plus_seed;
205 status_t status;
206 u_int64_t initiator_spi;
207 u_int64_t responder_spi;
208 prf_plus_t *prf_plus;
209 chunk_t secrets_raw;
210
211 /*
212 * TODO check length for specific prf's
213 */
214 concatenated_nonces.len = (initiator_nonce.len + responder_nonce.len);
215 concatenated_nonces.ptr = allocator_alloc(concatenated_nonces.len);
216 if (concatenated_nonces.ptr == NULL)
217 {
218 this->logger->log(this->logger, ERROR, "Fatal errror: Could not allocate memory for concatenated nonces");
219 return FAILED;
220 }
221 /* first is initiator */
222 memcpy(concatenated_nonces.ptr,initiator_nonce.ptr,initiator_nonce.len);
223 /* second is responder */
224 memcpy(concatenated_nonces.ptr + initiator_nonce.len,responder_nonce.ptr,responder_nonce.len);
225
226 this->logger->log_chunk(this->logger, RAW, "Nonce data", &concatenated_nonces);
227
228
229 /* status of set_key is not checked */
230 status = this->prf->set_key(this->prf,concatenated_nonces);
231
232 status = this->prf->allocate_bytes(this->prf,dh_shared_secret,&skeyseed);
233 if (status != SUCCESS)
234 {
235 allocator_free_chunk(&concatenated_nonces);
236 this->logger->log(this->logger, ERROR, "Fatal errror: Could not allocate bytes for skeyseed");
237 return status;
238 }
239 allocator_free_chunk(&concatenated_nonces);
240
241 prf_plus_seed.len = (initiator_nonce.len + responder_nonce.len + 16);
242 prf_plus_seed.ptr = allocator_alloc(prf_plus_seed.len);
243 if (prf_plus_seed.ptr == NULL)
244 {
245 this->logger->log(this->logger, ERROR, "Fatal errror: Could not allocate memory for prf+ seed");
246 allocator_free_chunk(&skeyseed);
247 return FAILED;
248 }
249
250 /* first is initiator */
251 memcpy(prf_plus_seed.ptr,initiator_nonce.ptr,initiator_nonce.len);
252 /* second is responder */
253 memcpy(prf_plus_seed.ptr + initiator_nonce.len,responder_nonce.ptr,responder_nonce.len);
254 /* third is initiator spi */
255 initiator_spi = this->ike_sa_id->get_initiator_spi(this->ike_sa_id);
256 memcpy(prf_plus_seed.ptr + initiator_nonce.len + responder_nonce.len,&initiator_spi,8);
257 /* fourth is responder spi */
258 responder_spi = this->ike_sa_id->get_responder_spi(this->ike_sa_id);
259 memcpy(prf_plus_seed.ptr + initiator_nonce.len + responder_nonce.len + 8,&responder_spi,8);
260
261 this->logger->log_chunk(this->logger, PRIVATE, "Keyseed", &skeyseed);
262 this->logger->log_chunk(this->logger, PRIVATE, "PRF+ Seed", &prf_plus_seed);
263
264 this->logger->log(this->logger, CONTROL | MOST, "Set new key of prf object");
265 status = this->prf->set_key(this->prf,skeyseed);
266 allocator_free_chunk(&skeyseed);
267 if (status != SUCCESS)
268 {
269 this->logger->log(this->logger, ERROR, "Fatal errror: Could not allocate memory for prf+ seed");
270 allocator_free_chunk(&prf_plus_seed);
271 return FAILED;
272 }
273
274 this->logger->log(this->logger, CONTROL | MOST, "Create new prf+ object");
275 prf_plus = prf_plus_create(this->prf, prf_plus_seed);
276 allocator_free_chunk(&prf_plus_seed);
277 if (prf_plus == NULL)
278 {
279 this->logger->log(this->logger, ERROR, "Fatal errror: prf+ object could not be created");
280 return FAILED;
281 }
282
283 prf_plus->allocate_bytes(prf_plus,100,&secrets_raw);
284
285 this->logger->log_chunk(this->logger, PRIVATE, "Secrets", &secrets_raw);
286
287 allocator_free_chunk(&secrets_raw);
288
289 prf_plus->destroy(prf_plus);
290
291 return SUCCESS;
292 }
293
294 /**
295 * @brief implements function resend_last_reply of protected_ike_sa_t
296 */
297 status_t resend_last_reply (protected_ike_sa_t *this)
298 {
299 packet_t *packet;
300 status_t status;
301
302 status = this->last_responded_message->generate(this->last_responded_message, &packet);
303 if (status != SUCCESS)
304 {
305 this->logger->log(this->logger, ERROR, "Could not generate message to resent");
306 return status;
307 }
308
309 status = global_send_queue->add(global_send_queue, packet);
310 if (status != SUCCESS)
311 {
312 this->logger->log(this->logger, ERROR, "Could not add packet to send queue");
313 packet->destroy(packet);
314 return status;
315 }
316 return SUCCESS;
317 }
318
319 status_t create_delete_job (protected_ike_sa_t *this)
320 {
321 job_t *delete_job;
322 status_t status;
323
324 this->logger->log(this->logger, CONTROL | MORE, "Going to create job to delete this IKE_SA");
325
326 delete_job = (job_t *) delete_ike_sa_job_create(this->ike_sa_id);
327 if (delete_job == NULL)
328 {
329 this->logger->log(this->logger, ERROR, "Job to delete IKE SA could not be created");
330 return FAILED;
331 }
332
333 status = global_job_queue->add(global_job_queue,delete_job);
334 if (status != SUCCESS)
335 {
336 this->logger->log(this->logger, ERROR, "%s Job to delete IKE SA could not be added to job queue",mapping_find(status_m,status));
337 delete_job->destroy_all(delete_job);
338 return status;
339 }
340 return SUCCESS;
341 }
342
343 /**
344 * @brief implements function destroy of protected_ike_sa_t
345 */
346 static status_t destroy (protected_ike_sa_t *this)
347 {
348
349 this->logger->log(this->logger, CONTROL | MORE, "Going to destroy IKE_SA");
350
351 /* destroy child sa's */
352 this->logger->log(this->logger, CONTROL | MOST, "Destroy all child_sa's");
353 while (this->child_sas->get_count(this->child_sas) > 0)
354 {
355 void *child_sa;
356 if (this->child_sas->remove_first(this->child_sas,&child_sa) != SUCCESS)
357 {
358 break;
359 }
360 /* destroy child sa */
361 }
362 this->child_sas->destroy(this->child_sas);
363
364 this->logger->log(this->logger, CONTROL | MOST, "Destroy secrets");
365 if (this->secrets.d_key.ptr != NULL)
366 {
367 allocator_free(this->secrets.d_key.ptr);
368 }
369 if (this->secrets.ai_key.ptr != NULL)
370 {
371 allocator_free(this->secrets.ai_key.ptr);
372 }
373 if (this->secrets.ar_key.ptr != NULL)
374 {
375 allocator_free(this->secrets.ar_key.ptr);
376 }
377 if (this->secrets.ei_key.ptr != NULL)
378 {
379 allocator_free(this->secrets.ei_key.ptr);
380 }
381 if (this->secrets.er_key.ptr != NULL)
382 {
383 allocator_free(this->secrets.er_key.ptr);
384 }
385 if (this->secrets.pi_key.ptr != NULL)
386 {
387 allocator_free(this->secrets.pi_key.ptr);
388 }
389 if (this->secrets.pr_key.ptr != NULL)
390 {
391 allocator_free(this->secrets.pr_key.ptr);
392 }
393
394 if ( this->crypter_initiator != NULL)
395 {
396 this->logger->log(this->logger, CONTROL | MOST, "Destroy initiator crypter");
397 this->crypter_initiator->destroy(this->crypter_initiator);
398 }
399
400 if ( this->crypter_responder != NULL)
401 {
402 this->logger->log(this->logger, CONTROL | MOST, "Destroy responder crypter");
403 this->crypter_responder->destroy(this->crypter_responder);
404 }
405
406 if ( this->signer_initiator != NULL)
407 {
408 this->logger->log(this->logger, CONTROL | MOST, "Destroy initiator signer");
409 this->signer_initiator->destroy(this->signer_initiator);
410 }
411
412 if (this->signer_responder != NULL)
413 {
414 this->logger->log(this->logger, CONTROL | MOST, "Destroy responder signer");
415 this->signer_responder->destroy(this->signer_responder);
416 }
417
418 if (this->prf != NULL)
419 {
420 this->logger->log(this->logger, CONTROL | MOST, "Destroy prf");
421 this->prf->destroy(this->prf);
422 }
423
424 /* destroy ike_sa_id */
425 this->logger->log(this->logger, CONTROL | MOST, "Destroy assigned ike_sa_id");
426 this->ike_sa_id->destroy(this->ike_sa_id);
427
428 /* destroy stored requested message */
429 if (this->last_requested_message != NULL)
430 {
431 this->logger->log(this->logger, CONTROL | MOST, "Destroy last requested message");
432 this->last_requested_message->destroy(this->last_requested_message);
433 }
434
435 /* destroy stored responded messages */
436 if (this->last_responded_message != NULL)
437 {
438 this->logger->log(this->logger, CONTROL | MOST, "Destroy last responded message");
439 this->last_responded_message->destroy(this->last_responded_message);
440 }
441
442 this->logger->log(this->logger, CONTROL | MOST, "Destroy randomizer");
443 this->randomizer->destroy(this->randomizer);
444
445 if (this->me.host != NULL)
446 {
447 this->logger->log(this->logger, CONTROL | MOST, "Destroy host informations of me");
448 this->me.host->destroy(this->me.host);
449 }
450
451 if (this->other.host != NULL)
452 {
453 this->logger->log(this->logger, CONTROL | MOST, "Destroy host informations of other");
454 this->other.host->destroy(this->other.host);
455 }
456
457 this->logger->log(this->logger, CONTROL | MOST, "Destroy current state object");
458 this->current_state->destroy(this->current_state);
459
460 this->logger->log(this->logger, CONTROL | MOST, "Destroy logger of IKE_SA");
461
462 global_logger_manager->destroy_logger(global_logger_manager, this->logger);
463
464 allocator_free(this);
465 return SUCCESS;
466 }
467
468 /*
469 * Described in Header
470 */
471 ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id)
472 {
473 protected_ike_sa_t *this = allocator_alloc_thing(protected_ike_sa_t);
474 if (this == NULL)
475 {
476 return NULL;
477 }
478
479 /* Public functions */
480 this->public.process_message = (status_t(*)(ike_sa_t*, message_t*)) process_message;
481 this->public.initialize_connection = (status_t(*)(ike_sa_t*, char*)) initialize_connection;
482 this->public.get_id = (ike_sa_id_t*(*)(ike_sa_t*)) get_id;
483 this->public.destroy = (status_t(*)(ike_sa_t*))destroy;
484
485 /* private functions */
486 this->build_message = build_message;
487 this->resend_last_reply = resend_last_reply;
488 this->create_delete_job = create_delete_job;
489 this->compute_secrets = compute_secrets;
490
491 /* initialize private fields */
492 this->logger = global_logger_manager->create_logger(global_logger_manager, IKE_SA, NULL);
493 if (this->logger == NULL)
494 {
495 allocator_free(this);
496 }
497
498 if (ike_sa_id->clone(ike_sa_id,&(this->ike_sa_id)) != SUCCESS)
499 {
500 this->logger->log(this->logger, ERROR, "Fatal error: Could not clone ike_sa_id");
501 global_logger_manager->destroy_logger(global_logger_manager,this->logger);
502 allocator_free(this);
503 return NULL;
504 }
505 this->child_sas = linked_list_create();
506 if (this->child_sas == NULL)
507 {
508 this->logger->log(this->logger, ERROR, "Fatal error: Could not create list for child_sa's");
509 this->ike_sa_id->destroy(this->ike_sa_id);
510 global_logger_manager->destroy_logger(global_logger_manager,this->logger);
511 allocator_free(this);
512 return NULL;
513 }
514 this->randomizer = randomizer_create();
515 if (this->randomizer == NULL)
516 {
517 this->logger->log(this->logger, ERROR, "Fatal error: Could not create list for child_sa's");
518 this->child_sas->destroy(this->child_sas);
519 this->ike_sa_id->destroy(this->ike_sa_id);
520 global_logger_manager->destroy_logger(global_logger_manager,this->logger);
521 allocator_free(this);
522 }
523
524 this->me.host = NULL;
525 this->other.host = NULL;
526 this->last_requested_message = NULL;
527 this->last_responded_message = NULL;
528 this->message_id_out = 0;
529 this->message_id_in = 0;
530 this->secrets.d_key.ptr = NULL;
531 this->secrets.d_key.len = 0;
532 this->secrets.ai_key.ptr = NULL;
533 this->secrets.ai_key.len = 0;
534 this->secrets.ar_key.ptr = NULL;
535 this->secrets.ar_key.len = 0;
536 this->secrets.ei_key.ptr = NULL;
537 this->secrets.ei_key.len = 0;
538 this->secrets.er_key.ptr = NULL;
539 this->secrets.er_key.len = 0;
540 this->secrets.pi_key.ptr = NULL;
541 this->secrets.pi_key.len = 0;
542 this->secrets.pr_key.ptr = NULL;
543 this->secrets.pr_key.len = 0;
544 this->crypter_initiator = NULL;
545 this->crypter_responder = NULL;
546 this->signer_initiator = NULL;
547 this->signer_responder = NULL;
548 this->prf = NULL;
549
550
551
552
553 /* at creation time, IKE_SA is in a initiator state */
554 if (ike_sa_id->is_initiator(ike_sa_id))
555 {
556 this->current_state = (state_t *) initiator_init_create(this);
557 }
558 else
559 {
560 this->current_state = (state_t *) responder_init_create(this);
561 }
562
563 if (this->current_state == NULL)
564 {
565 this->logger->log(this->logger, ERROR, "Fatal error: Could not create state object");
566 this->child_sas->destroy(this->child_sas);
567 this->ike_sa_id->destroy(this->ike_sa_id);
568 global_logger_manager->destroy_logger(global_logger_manager,this->logger);
569 this->randomizer->destroy(this->randomizer);
570 allocator_free(this);
571 }
572
573
574 return &(this->public);
575 }