2 * Copyright (C) 2005-2010 Martin Willi
3 * Copyright (C) 2010 revosec AG
4 * Copyright (C) 2011 Tobias Brunner
5 * Copyright (C) 2005 Jan Hutter
6 * Hochschule fuer Technik Rapperswil
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22 #include "encryption_payload.h"
25 #include <encoding/payloads/encodings.h>
26 #include <collections/linked_list.h>
27 #include <encoding/generator.h>
28 #include <encoding/parser.h>
30 typedef struct private_encryption_payload_t private_encryption_payload_t
;
33 * Private data of an encryption_payload_t' Object.
36 struct private_encryption_payload_t
{
39 * Public encryption_payload_t interface.
41 encryption_payload_t
public;
44 * There is no next payload for an encryption payload,
45 * since encryption payload MUST be the last one.
46 * next_payload means here the first payload of the
47 * contained, encrypted payload.
49 u_int8_t next_payload
;
52 * Flags, including reserved bits
57 * Length of this payload
59 u_int16_t payload_length
;
62 * Chunk containing the IV, plain, padding and ICV.
67 * AEAD transform to use
74 linked_list_t
*payloads
;
77 * Type of payload, ENCRYPTED or ENCRYPTED_V1
83 * Encoding rules to parse or generate a IKEv2-Encryption Payload.
85 * The defined offsets are the positions in a object of type
86 * private_encryption_payload_t.
88 static encoding_rule_t encodings_v2
[] = {
89 /* 1 Byte next payload type, stored in the field next_payload */
90 { U_INT_8
, offsetof(private_encryption_payload_t
, next_payload
) },
91 /* Critical and 7 reserved bits, all stored for reconstruction */
92 { U_INT_8
, offsetof(private_encryption_payload_t
, flags
) },
93 /* Length of the whole encryption payload*/
94 { PAYLOAD_LENGTH
, offsetof(private_encryption_payload_t
, payload_length
) },
95 /* encrypted data, stored in a chunk. contains iv, data, padding */
96 { CHUNK_DATA
, offsetof(private_encryption_payload_t
, encrypted
) },
101 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
102 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
103 ! Next Payload !C! RESERVED ! Payload Length !
104 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
105 ! Initialization Vector !
106 ! (length is block size for encryption algorithm) !
107 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
108 ! Encrypted IKE Payloads !
109 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
110 ! ! Padding (0-255 octets) !
111 +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+
113 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
114 ~ Integrity Checksum Data ~
115 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
119 * Encoding rules to parse or generate a complete encrypted IKEv1 message.
121 * The defined offsets are the positions in a object of type
122 * private_encryption_payload_t.
124 static encoding_rule_t encodings_v1
[] = {
125 /* encrypted data, stored in a chunk */
126 { ENCRYPTED_DATA
, offsetof(private_encryption_payload_t
, encrypted
) },
131 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
132 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
133 ! Encrypted IKE Payloads !
134 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
135 ! ! Padding (0-255 octets) !
136 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
139 METHOD(payload_t
, verify
, status_t
,
140 private_encryption_payload_t
*this)
145 METHOD(payload_t
, get_encoding_rules
, int,
146 private_encryption_payload_t
*this, encoding_rule_t
**rules
)
148 if (this->type
== ENCRYPTED
)
150 *rules
= encodings_v2
;
151 return countof(encodings_v2
);
153 *rules
= encodings_v1
;
154 return countof(encodings_v1
);
157 METHOD(payload_t
, get_header_length
, int,
158 private_encryption_payload_t
*this)
160 if (this->type
== ENCRYPTED
)
167 METHOD(payload_t
, get_type
, payload_type_t
,
168 private_encryption_payload_t
*this)
173 METHOD(payload_t
, get_next_type
, payload_type_t
,
174 private_encryption_payload_t
*this)
176 return this->next_payload
;
179 METHOD(payload_t
, set_next_type
, void,
180 private_encryption_payload_t
*this, payload_type_t type
)
182 /* the next payload is set during add, still allow this for IKEv1 */
183 this->next_payload
= type
;
187 * Compute the length of the whole payload
189 static void compute_length(private_encryption_payload_t
*this)
191 enumerator_t
*enumerator
;
193 size_t bs
, length
= 0;
195 if (this->encrypted
.len
)
197 length
= this->encrypted
.len
;
201 enumerator
= this->payloads
->create_enumerator(this->payloads
);
202 while (enumerator
->enumerate(enumerator
, &payload
))
204 length
+= payload
->get_length(payload
);
206 enumerator
->destroy(enumerator
);
211 bs
= this->aead
->get_block_size(this->aead
);
212 length
+= bs
- (length
% bs
);
214 length
+= this->aead
->get_iv_size(this->aead
);
216 length
+= this->aead
->get_icv_size(this->aead
);
219 length
+= get_header_length(this);
220 this->payload_length
= length
;
223 METHOD2(payload_t
, encryption_payload_t
, get_length
, size_t,
224 private_encryption_payload_t
*this)
226 compute_length(this);
227 return this->payload_length
;
230 METHOD(encryption_payload_t
, add_payload
, void,
231 private_encryption_payload_t
*this, payload_t
*payload
)
233 payload_t
*last_payload
;
235 if (this->payloads
->get_count(this->payloads
) > 0)
237 this->payloads
->get_last(this->payloads
, (void **)&last_payload
);
238 last_payload
->set_next_type(last_payload
, payload
->get_type(payload
));
242 this->next_payload
= payload
->get_type(payload
);
244 payload
->set_next_type(payload
, NO_PAYLOAD
);
245 this->payloads
->insert_last(this->payloads
, payload
);
246 compute_length(this);
249 METHOD(encryption_payload_t
, remove_payload
, payload_t
*,
250 private_encryption_payload_t
*this)
254 if (this->payloads
->remove_first(this->payloads
,
255 (void**)&payload
) == SUCCESS
)
263 * Generate payload before encryption
265 static chunk_t
generate(private_encryption_payload_t
*this,
266 generator_t
*generator
)
268 payload_t
*current
, *next
;
269 enumerator_t
*enumerator
;
271 chunk_t chunk
= chunk_empty
;
273 enumerator
= this->payloads
->create_enumerator(this->payloads
);
274 if (enumerator
->enumerate(enumerator
, ¤t
))
276 this->next_payload
= current
->get_type(current
);
278 while (enumerator
->enumerate(enumerator
, &next
))
280 current
->set_next_type(current
, next
->get_type(next
));
281 generator
->generate_payload(generator
, current
);
284 current
->set_next_type(current
, NO_PAYLOAD
);
285 generator
->generate_payload(generator
, current
);
287 chunk
= generator
->get_chunk(generator
, &lenpos
);
288 DBG2(DBG_ENC
, "generated content in encryption payload");
290 enumerator
->destroy(enumerator
);
295 * Append the encryption payload header to the associated data
297 static chunk_t
append_header(private_encryption_payload_t
*this, chunk_t assoc
)
300 u_int8_t next_payload
;
303 } __attribute__((packed
)) header
= {
304 .next_payload
= this->next_payload
,
305 .flags
= this->flags
,
306 .length
= htons(get_length(this)),
308 return chunk_cat("cc", assoc
, chunk_from_thing(header
));
311 METHOD(encryption_payload_t
, encrypt
, status_t
,
312 private_encryption_payload_t
*this, chunk_t assoc
)
314 chunk_t iv
, plain
, padding
, icv
, crypt
;
315 generator_t
*generator
;
320 if (this->aead
== NULL
)
322 DBG1(DBG_ENC
, "encrypting encryption payload failed, transform missing");
323 return INVALID_STATE
;
326 rng
= lib
->crypto
->create_rng(lib
->crypto
, RNG_WEAK
);
329 DBG1(DBG_ENC
, "encrypting encryption payload failed, no RNG found");
330 return NOT_SUPPORTED
;
333 iv_gen
= this->aead
->get_iv_gen(this->aead
);
336 DBG1(DBG_ENC
, "encrypting encryption payload failed, no IV generator");
337 return NOT_SUPPORTED
;
340 assoc
= append_header(this, assoc
);
342 generator
= generator_create();
343 plain
= generate(this, generator
);
344 bs
= this->aead
->get_block_size(this->aead
);
345 /* we need at least one byte padding to store the padding length */
346 padding
.len
= bs
- (plain
.len
% bs
);
347 iv
.len
= this->aead
->get_iv_size(this->aead
);
348 icv
.len
= this->aead
->get_icv_size(this->aead
);
350 /* prepare data to authenticate-encrypt:
351 * | IV | plain | padding | ICV |
352 * \____crypt______/ ^
355 * assoc -> + ------->/
357 free(this->encrypted
.ptr
);
358 this->encrypted
= chunk_alloc(iv
.len
+ plain
.len
+ padding
.len
+ icv
.len
);
359 iv
.ptr
= this->encrypted
.ptr
;
360 memcpy(iv
.ptr
+ iv
.len
, plain
.ptr
, plain
.len
);
361 plain
.ptr
= iv
.ptr
+ iv
.len
;
362 padding
.ptr
= plain
.ptr
+ plain
.len
;
363 icv
.ptr
= padding
.ptr
+ padding
.len
;
364 crypt
= chunk_create(plain
.ptr
, plain
.len
+ padding
.len
);
365 generator
->destroy(generator
);
367 if (!iv_gen
->get_iv(iv_gen
, iv
.len
, iv
.ptr
) ||
368 !rng
->get_bytes(rng
, padding
.len
- 1, padding
.ptr
))
370 DBG1(DBG_ENC
, "encrypting encryption payload failed, no IV or padding");
375 padding
.ptr
[padding
.len
- 1] = padding
.len
- 1;
378 DBG3(DBG_ENC
, "encryption payload encryption:");
379 DBG3(DBG_ENC
, "IV %B", &iv
);
380 DBG3(DBG_ENC
, "plain %B", &plain
);
381 DBG3(DBG_ENC
, "padding %B", &padding
);
382 DBG3(DBG_ENC
, "assoc %B", &assoc
);
384 if (!this->aead
->encrypt(this->aead
, crypt
, assoc
, iv
, NULL
))
390 DBG3(DBG_ENC
, "encrypted %B", &crypt
);
391 DBG3(DBG_ENC
, "ICV %B", &icv
);
398 METHOD(encryption_payload_t
, encrypt_v1
, status_t
,
399 private_encryption_payload_t
*this, chunk_t iv
)
401 generator_t
*generator
;
402 chunk_t plain
, padding
;
405 if (this->aead
== NULL
)
407 DBG1(DBG_ENC
, "encryption failed, transform missing");
408 return INVALID_STATE
;
411 generator
= generator_create();
412 plain
= generate(this, generator
);
413 bs
= this->aead
->get_block_size(this->aead
);
414 padding
.len
= bs
- (plain
.len
% bs
);
416 /* prepare data to encrypt:
417 * | plain | padding | */
418 free(this->encrypted
.ptr
);
419 this->encrypted
= chunk_alloc(plain
.len
+ padding
.len
);
420 memcpy(this->encrypted
.ptr
, plain
.ptr
, plain
.len
);
421 plain
.ptr
= this->encrypted
.ptr
;
422 padding
.ptr
= plain
.ptr
+ plain
.len
;
423 memset(padding
.ptr
, 0, padding
.len
);
424 generator
->destroy(generator
);
426 DBG3(DBG_ENC
, "encrypting payloads:");
427 DBG3(DBG_ENC
, "plain %B", &plain
);
428 DBG3(DBG_ENC
, "padding %B", &padding
);
430 if (!this->aead
->encrypt(this->aead
, this->encrypted
, chunk_empty
, iv
, NULL
))
435 DBG3(DBG_ENC
, "encrypted %B", &this->encrypted
);
441 * Parse the payloads after decryption.
443 static status_t
parse(private_encryption_payload_t
*this, chunk_t plain
)
448 parser
= parser_create(plain
);
449 type
= this->next_payload
;
450 while (type
!= NO_PAYLOAD
)
454 if (plain
.len
< 4 || untoh16(plain
.ptr
+ 2) > plain
.len
)
456 DBG1(DBG_ENC
, "invalid %N payload length, decryption failed?",
457 payload_type_names
, type
);
458 parser
->destroy(parser
);
461 if (parser
->parse_payload(parser
, type
, &payload
) != SUCCESS
)
463 parser
->destroy(parser
);
466 if (payload
->verify(payload
) != SUCCESS
)
468 DBG1(DBG_ENC
, "%N verification failed",
469 payload_type_names
, payload
->get_type(payload
));
470 payload
->destroy(payload
);
471 parser
->destroy(parser
);
474 type
= payload
->get_next_type(payload
);
475 this->payloads
->insert_last(this->payloads
, payload
);
477 parser
->destroy(parser
);
478 DBG2(DBG_ENC
, "parsed content of encryption payload");
482 METHOD(encryption_payload_t
, decrypt
, status_t
,
483 private_encryption_payload_t
*this, chunk_t assoc
)
485 chunk_t iv
, plain
, padding
, icv
, crypt
;
488 if (this->aead
== NULL
)
490 DBG1(DBG_ENC
, "decrypting encryption payload failed, transform missing");
491 return INVALID_STATE
;
494 /* prepare data to authenticate-decrypt:
495 * | IV | plain | padding | ICV |
496 * \____crypt______/ ^
499 * assoc -> + ------->/
502 bs
= this->aead
->get_block_size(this->aead
);
503 iv
.len
= this->aead
->get_iv_size(this->aead
);
504 iv
.ptr
= this->encrypted
.ptr
;
505 icv
.len
= this->aead
->get_icv_size(this->aead
);
506 icv
.ptr
= this->encrypted
.ptr
+ this->encrypted
.len
- icv
.len
;
507 crypt
.ptr
= iv
.ptr
+ iv
.len
;
508 crypt
.len
= this->encrypted
.len
- iv
.len
;
510 if (iv
.len
+ icv
.len
> this->encrypted
.len
||
511 (crypt
.len
- icv
.len
) % bs
)
513 DBG1(DBG_ENC
, "decrypting encryption payload failed, invalid length");
517 assoc
= append_header(this, assoc
);
519 DBG3(DBG_ENC
, "encryption payload decryption:");
520 DBG3(DBG_ENC
, "IV %B", &iv
);
521 DBG3(DBG_ENC
, "encrypted %B", &crypt
);
522 DBG3(DBG_ENC
, "ICV %B", &icv
);
523 DBG3(DBG_ENC
, "assoc %B", &assoc
);
525 if (!this->aead
->decrypt(this->aead
, crypt
, assoc
, iv
, NULL
))
527 DBG1(DBG_ENC
, "verifying encryption payload integrity failed");
533 plain
= chunk_create(crypt
.ptr
, crypt
.len
- icv
.len
);
534 padding
.len
= plain
.ptr
[plain
.len
- 1] + 1;
535 if (padding
.len
> plain
.len
)
537 DBG1(DBG_ENC
, "decrypting encryption payload failed, "
538 "padding invalid %B", &crypt
);
541 plain
.len
-= padding
.len
;
542 padding
.ptr
= plain
.ptr
+ plain
.len
;
544 DBG3(DBG_ENC
, "plain %B", &plain
);
545 DBG3(DBG_ENC
, "padding %B", &padding
);
547 return parse(this, plain
);
550 METHOD(encryption_payload_t
, decrypt_v1
, status_t
,
551 private_encryption_payload_t
*this, chunk_t iv
)
553 if (this->aead
== NULL
)
555 DBG1(DBG_ENC
, "decryption failed, transform missing");
556 return INVALID_STATE
;
559 /* data must be a multiple of block size */
560 if (iv
.len
!= this->aead
->get_block_size(this->aead
) ||
561 this->encrypted
.len
< iv
.len
|| this->encrypted
.len
% iv
.len
)
563 DBG1(DBG_ENC
, "decryption failed, invalid length");
567 DBG3(DBG_ENC
, "decrypting payloads:");
568 DBG3(DBG_ENC
, "encrypted %B", &this->encrypted
);
570 if (!this->aead
->decrypt(this->aead
, this->encrypted
, chunk_empty
, iv
, NULL
))
575 DBG3(DBG_ENC
, "plain %B", &this->encrypted
);
577 return parse(this, this->encrypted
);
580 METHOD(encryption_payload_t
, set_transform
, void,
581 private_encryption_payload_t
*this, aead_t
* aead
)
586 METHOD2(payload_t
, encryption_payload_t
, destroy
, void,
587 private_encryption_payload_t
*this)
589 this->payloads
->destroy_offset(this->payloads
, offsetof(payload_t
, destroy
));
590 free(this->encrypted
.ptr
);
595 * Described in header
597 encryption_payload_t
*encryption_payload_create(payload_type_t type
)
599 private_encryption_payload_t
*this;
603 .payload_interface
= {
605 .get_encoding_rules
= _get_encoding_rules
,
606 .get_header_length
= _get_header_length
,
607 .get_length
= _get_length
,
608 .get_next_type
= _get_next_type
,
609 .set_next_type
= _set_next_type
,
610 .get_type
= _get_type
,
613 .get_length
= _get_length
,
614 .add_payload
= _add_payload
,
615 .remove_payload
= _remove_payload
,
616 .set_transform
= _set_transform
,
621 .next_payload
= NO_PAYLOAD
,
622 .payloads
= linked_list_create(),
625 this->payload_length
= get_header_length(this);
627 if (type
== ENCRYPTED_V1
)
629 this->public.encrypt
= _encrypt_v1
;
630 this->public.decrypt
= _decrypt_v1
;
633 return &this->public;