2 * @file encryption_payload.c
4 * @brief Implementation of encryption_payload_t.
9 * Copyright (C) 2005 Jan Hutter, Martin Willi
10 * Hochschule fuer Technik Rapperswil
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by the
14 * Free Software Foundation; either version 2 of the License, or (at your
15 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
19 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
26 #include "encryption_payload.h"
28 #include <encoding/payloads/encodings.h>
29 #include <utils/allocator.h>
30 #include <utils/linked_list.h>
31 #include <encoding/generator.h>
32 #include <encoding/parser.h>
33 #include <utils/iterator.h>
34 #include <utils/randomizer.h>
35 #include <transforms/signers/signer.h>
40 typedef struct private_encryption_payload_t private_encryption_payload_t
;
43 * Private data of an encryption_payload_t' Object.
46 struct private_encryption_payload_t
{
48 * Public encryption_payload_t interface.
50 encryption_payload_t
public;
53 * There is no next payload for an encryption payload,
54 * since encryption payload MUST be the last one.
55 * next_payload means here the first payload of the
56 * contained, encrypted payload.
58 u_int8_t next_payload
;
66 * Length of this payload
68 u_int16_t payload_length
;
71 * Initialization vector.
81 * Chunk containing the iv, data, padding,
82 * and (an eventually not calculated) signature.
87 * Chunk containing the data in decrypted (unpadded) form.
92 * Signer set by set_signer.
97 * Contained payloads of this encrpytion_payload.
99 linked_list_t
*payloads
;
102 * @brief Computes the length of this payload.
104 * @param this calling private_encryption_payload_t object
106 void (*compute_length
) (private_encryption_payload_t
*this);
109 * @brief Generate payloads (unencrypted) in chunk decrypted.
111 * @param this calling private_encryption_payload_t object
113 void (*generate
) (private_encryption_payload_t
*this);
114 status_t (*parse
) (private_encryption_payload_t
*this);
118 * Encoding rules to parse or generate a IKEv2-Encryption Payload.
120 * The defined offsets are the positions in a object of type
121 * private_encryption_payload_t.
124 encoding_rule_t encryption_payload_encodings
[] = {
125 /* 1 Byte next payload type, stored in the field next_payload */
126 { U_INT_8
, offsetof(private_encryption_payload_t
, next_payload
) },
127 /* the critical bit */
128 { FLAG
, offsetof(private_encryption_payload_t
, critical
) },
129 /* 7 Bit reserved bits, nowhere stored */
137 /* Length of the whole encryption payload*/
138 { PAYLOAD_LENGTH
, offsetof(private_encryption_payload_t
, payload_length
) },
139 /* encrypted data, stored in a chunk. contains iv, data, padding */
140 { ENCRYPTED_DATA
, offsetof(private_encryption_payload_t
, encrypted
) },
145 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
146 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
147 ! Next Payload !C! RESERVED ! Payload Length !
148 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
149 ! Initialization Vector !
150 ! (length is block size for encryption algorithm) !
151 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
152 ! Encrypted IKE Payloads !
153 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
154 ! ! Padding (0-255 octets) !
155 +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+
157 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
158 ~ Integrity Checksum Data ~
159 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
163 * Implementation of payload_t.verify.
165 static status_t
verify(private_encryption_payload_t
*this)
167 // int proposal_number = 1;
169 // iterator_t *iterator;
170 // bool first = TRUE;
172 // if (this->critical)
174 // /* critical bit set! */
178 // /* check proposal numbering */
179 // status = this->proposals->create_iterator(this->proposals,&iterator,TRUE);
180 // if (status != SUCCESS)
185 // while(iterator->has_next(iterator))
187 // proposal_substructure_t *current_proposal;
188 // status = iterator->current(iterator,(void **)¤t_proposal);
192 // if (current_proposal->get_proposal_number(current_proposal) > proposal_number)
196 // /* first number must be 1 */
201 // if (current_proposal->get_proposal_number(current_proposal) != (proposal_number + 1))
203 // /* must be only one more then previous proposal */
208 // else if (current_proposal->get_proposal_number(current_proposal) < proposal_number)
210 // iterator->destroy(iterator);
211 // /* must not be smaller then proceeding one */
218 // iterator->destroy(iterator);
223 * Implementation of payload_t.destroy.
225 static void destroy(private_encryption_payload_t
*this)
227 /* all proposals are getting destroyed */
228 while (this->payloads
->get_count(this->payloads
) > 0)
230 payload_t
*current_payload
;
231 this->payloads
->remove_last(this->payloads
,(void **)¤t_payload
);
232 current_payload
->destroy(current_payload
);
234 this->payloads
->destroy(this->payloads
);
236 allocator_free(this->iv
.ptr
);
237 allocator_free(this->encrypted
.ptr
);
238 allocator_free(this->decrypted
.ptr
);
239 allocator_free(this->checksum
.ptr
);
240 allocator_free(this);
244 * Implementation of payload_t.get_encoding_rules.
246 static void get_encoding_rules(private_encryption_payload_t
*this, encoding_rule_t
**rules
, size_t *rule_count
)
248 *rules
= encryption_payload_encodings
;
249 *rule_count
= sizeof(encryption_payload_encodings
) / sizeof(encoding_rule_t
);
253 * Implementation of payload_t.get_type.
255 static payload_type_t
get_type(private_encryption_payload_t
*this)
261 * Implementation of payload_t.get_next_type.
263 static payload_type_t
get_next_type(private_encryption_payload_t
*this)
265 /* returns first contained payload here */
266 return (this->next_payload
);
270 * Implementation of payload_t.set_next_type.
272 static void set_next_type(private_encryption_payload_t
*this, payload_type_t type
)
274 /* set next type is not allowed, since this payload MUST be the last one
275 * and so nothing is done in here*/
279 * Implementation of payload_t.get_length.
281 static size_t get_length(private_encryption_payload_t
*this)
283 this->compute_length(this);
284 return this->payload_length
;
288 * Implementation of payload_t.create_payload_iterator.
290 static iterator_t
*create_payload_iterator (private_encryption_payload_t
*this, bool forward
)
292 return (this->payloads
->create_iterator(this->payloads
, forward
));
296 * Implementation of payload_t.add_payload.
298 static void add_payload(private_encryption_payload_t
*this, payload_t
*payload
)
300 payload_t
*last_payload
;
301 if (this->payloads
->get_count(this->payloads
) > 0)
303 this->payloads
->get_last(this->payloads
,(void **) &last_payload
);
306 if (this->payloads
->get_count(this->payloads
) == 1)
308 this->next_payload
= payload
->get_type(payload
);
312 last_payload
->set_next_type(last_payload
, payload
->get_type(payload
));
314 payload
->set_next_type(payload
, NO_PAYLOAD
);
315 this->compute_length(this);
319 * Implementation of encryption_payload_t.encrypt.
321 static status_t
encrypt(private_encryption_payload_t
*this, crypter_t
*crypter
)
323 chunk_t iv
, padding
, concatenated
;
324 randomizer_t
*randomizer
;
327 if (this->signer
== NULL
)
329 return INVALID_STATE
;
332 /* for random data in iv and padding */
333 randomizer
= randomizer_create();
335 /* build payload chunk */
336 this->generate(this);
339 padding
.len
= (this->decrypted
.len
+ 1) % crypter
->get_block_size(crypter
);
340 status
= randomizer
->allocate_pseudo_random_bytes(randomizer
, padding
.len
, &padding
);
341 if (status
!= SUCCESS
)
343 randomizer
->destroy(randomizer
);
347 /* concatenate payload data, padding, padding len */
348 concatenated
.len
= this->decrypted
.len
+ padding
.len
+ 1;
349 concatenated
.ptr
= allocator_alloc(concatenated
.len
);
351 memcpy(concatenated
.ptr
, this->decrypted
.ptr
, this->decrypted
.len
);
352 memcpy(concatenated
.ptr
+ this->decrypted
.len
, padding
.ptr
, padding
.len
);
353 *(concatenated
.ptr
+ concatenated
.len
- 1) = padding
.len
;
357 iv
.len
= crypter
->get_block_size(crypter
);
358 randomizer
->allocate_pseudo_random_bytes(randomizer
, iv
.len
, &iv
);
359 randomizer
->destroy(randomizer
);
361 /* encrypt concatenated chunk */
362 allocator_free(this->encrypted
.ptr
);
363 status
= crypter
->encrypt(crypter
, iv
, concatenated
, &(this->encrypted
));
364 allocator_free(padding
.ptr
);
365 allocator_free(concatenated
.ptr
);
366 allocator_free(iv
.ptr
);
367 if (status
!= SUCCESS
)
372 /* append an empty signature */
373 this->encrypted
.len
+= this->signer
->get_block_size(this->signer
);
374 allocator_realloc(this->encrypted
.ptr
, this->encrypted
.len
);
379 * Implementation of encryption_payload_t.encrypt.
381 static status_t
decrypt(private_encryption_payload_t
*this, crypter_t
*crypter
)
383 chunk_t iv
, concatenated
;
384 u_int8_t padding_length
;
387 if (this->signer
== NULL
)
389 return INVALID_STATE
;
393 iv
.len
= crypter
->get_block_size(crypter
);
394 iv
.ptr
= this->encrypted
.ptr
;
396 /* point concatenated to data + padding + padding_length*/
397 concatenated
.ptr
= this->encrypted
.ptr
+ iv
.len
;
398 concatenated
.len
= this->encrypted
.len
- iv
.len
- this->signer
->get_block_size(this->signer
);
400 /* check the size of input:
401 * concatenated must be at least on block_size of crypter
403 if (concatenated
.len
< iv
.len
)
408 /* free previus data, if any */
409 allocator_free(this->decrypted
.ptr
);
411 status
= crypter
->decrypt(crypter
, iv
, concatenated
, &(this->decrypted
));
412 if (status
!= SUCCESS
)
417 /* get padding length, sits just bevore signature */
418 padding_length
= *(this->decrypted
.ptr
+ this->decrypted
.len
- 1);
419 this->decrypted
.len
-= padding_length
;
421 /* check size again */
422 if (padding_length
> concatenated
.len
|| this->decrypted
.len
< 0)
424 /* decryption failed :-/ */
429 this->decrypted
.ptr
= allocator_realloc(this->decrypted
.ptr
, this->decrypted
.len
);
430 if (this->decrypted
.ptr
== NULL
)
439 * Implementation of encryption_payload_t.set_signer.
441 static void set_signer(private_encryption_payload_t
*this, signer_t
* signer
)
443 this->signer
= signer
;
447 * Implementation of encryption_payload_t.build_signature.
449 static status_t
build_signature(private_encryption_payload_t
*this, chunk_t data
)
451 chunk_t data_without_sig
= data
;
454 if (this->signer
== NULL
)
456 return INVALID_STATE
;
459 sig
.len
= this->signer
->get_block_size(this->signer
);
460 data_without_sig
.len
-= sig
.len
;
461 sig
.ptr
= data
.ptr
+ data_without_sig
.len
;
462 this->signer
->get_signature(this->signer
, data_without_sig
, sig
.ptr
);
467 * Implementation of encryption_payload_t.verify_signature.
469 static status_t
verify_signature(private_encryption_payload_t
*this, chunk_t data
)
471 chunk_t sig
, data_without_sig
;
474 if (this->signer
== NULL
)
476 return INVALID_STATE
;
478 /* find signature in data chunk */
479 sig
.len
= this->signer
->get_block_size(this->signer
);
480 if (data
.len
<= sig
.len
)
484 sig
.ptr
= data
.ptr
+ data
.len
- sig
.len
;
487 data_without_sig
.len
= data
.len
- sig
.len
;
488 data_without_sig
.ptr
= data
.ptr
;
489 this->signer
->verify_signature(this->signer
, data_without_sig
, sig
, &valid
);
500 * Implementation of private_encryption_payload_t.generate.
502 static void generate(private_encryption_payload_t
*this)
504 payload_t
*current_payload
, *next_payload
;
505 generator_t
*generator
;
506 iterator_t
*iterator
;
508 /* create iterator */
509 iterator
= this->payloads
->create_iterator(this->payloads
, TRUE
);
511 /* get first payload */
512 if (iterator
->has_next(iterator
))
514 iterator
->current(iterator
, (void**)¤t_payload
);
515 this->next_payload
= current_payload
->get_type(current_payload
);
520 allocator_free(this->decrypted
.ptr
);
521 this->decrypted
= CHUNK_INITIALIZER
;
522 iterator
->destroy(iterator
);
526 generator
= generator_create();
528 /* build all payload, except last */
529 while(iterator
->has_next(iterator
))
531 iterator
->current(iterator
, (void**)&next_payload
);
532 current_payload
->set_next_type(current_payload
, next_payload
->get_type(next_payload
));
534 generator
->generate_payload(generator
, current_payload
);
535 current_payload
= next_payload
;
537 iterator
->destroy(iterator
);
539 /* build last payload */
540 current_payload
->set_next_type(current_payload
, NO_PAYLOAD
);
541 generator
->generate_payload(generator
, current_payload
);
543 /* free already generated data */
544 allocator_free(this->decrypted
.ptr
);
546 generator
->write_to_chunk(generator
, &(this->decrypted
));
547 generator
->destroy(generator
);
551 * Implementation of private_encryption_payload_t.parse.
553 static status_t
parse(private_encryption_payload_t
*this)
557 payload_type_t current_payload_type
;
559 /* check if there is decrypted data */
560 if (this->decrypted
.ptr
== NULL
)
562 return INVALID_STATE
;
565 /* build a parser on the decrypted data */
566 parser
= parser_create(this->decrypted
);
568 current_payload_type
= this->next_payload
;
569 /* parse all payloads */
570 while (current_payload_type
!= NO_PAYLOAD
)
572 payload_t
*current_payload
;
574 status
= parser
->parse_payload(parser
, current_payload_type
, (payload_t
**)¤t_payload
);
575 if (status
!= SUCCESS
)
580 status
= current_payload
->verify(current_payload
);
581 if (status
!= SUCCESS
)
586 /* get next payload type */
587 current_payload_type
= current_payload
->get_next_type(current_payload
);
589 this->payloads
->insert_last(this->payloads
,current_payload
);
595 * Implementation of private_encryption_payload_t.compute_length.
597 static void compute_length(private_encryption_payload_t
*this)
599 iterator_t
*iterator
;
600 size_t length
= ENCRYPTION_PAYLOAD_HEADER_LENGTH
;
601 iterator
= this->payloads
->create_iterator(this->payloads
, TRUE
);
603 while (iterator
->has_next(iterator
))
605 payload_t
*current_payload
;
606 iterator
->current(iterator
, (void **) ¤t_payload
);
607 length
+= current_payload
->get_length(current_payload
);
609 iterator
->destroy(iterator
);
611 this->payload_length
= length
;
616 * Described in header
618 encryption_payload_t
*encryption_payload_create()
620 private_encryption_payload_t
*this = allocator_alloc_thing(private_encryption_payload_t
);
622 /* payload_t interface functions */
623 this->public.payload_interface
.verify
= (status_t (*) (payload_t
*))verify
;
624 this->public.payload_interface
.get_encoding_rules
= (void (*) (payload_t
*, encoding_rule_t
**, size_t *) ) get_encoding_rules
;
625 this->public.payload_interface
.get_length
= (size_t (*) (payload_t
*)) get_length
;
626 this->public.payload_interface
.get_next_type
= (payload_type_t (*) (payload_t
*)) get_next_type
;
627 this->public.payload_interface
.set_next_type
= (void (*) (payload_t
*,payload_type_t
)) set_next_type
;
628 this->public.payload_interface
.get_type
= (payload_type_t (*) (payload_t
*)) get_type
;
629 this->public.payload_interface
.destroy
= (void (*) (payload_t
*))destroy
;
631 /* public functions */
632 this->public.create_payload_iterator
= (iterator_t
* (*) (encryption_payload_t
*,bool)) create_payload_iterator
;
633 this->public.add_payload
= (void (*) (encryption_payload_t
*,payload_t
*)) add_payload
;
634 this->public.encrypt
= (status_t (*) (encryption_payload_t
*, crypter_t
*)) encrypt
;
635 this->public.decrypt
= (status_t (*) (encryption_payload_t
*, crypter_t
*)) decrypt
;
636 this->public.set_signer
= (void (*) (encryption_payload_t
*,signer_t
*)) set_signer
;
637 this->public.build_signature
= (status_t (*) (encryption_payload_t
*, chunk_t
)) build_signature
;
638 this->public.verify_signature
= (status_t (*) (encryption_payload_t
*, chunk_t
)) verify_signature
;
639 this->public.destroy
= (void (*) (encryption_payload_t
*)) destroy
;
641 /* private functions */
642 this->compute_length
= compute_length
;
643 this->generate
= generate
;
646 /* set default values of the fields */
647 this->critical
= TRUE
;
648 this->next_payload
= NO_PAYLOAD
;
649 this->payload_length
= ENCRYPTION_PAYLOAD_HEADER_LENGTH
;
650 this->iv
= CHUNK_INITIALIZER
;
651 this->encrypted
= CHUNK_INITIALIZER
;
652 this->decrypted
= CHUNK_INITIALIZER
;
653 this->checksum
= CHUNK_INITIALIZER
;
655 this->payloads
= linked_list_create();
657 return (&(this->public));