]> git.ipfire.org Git - thirdparty/strongswan.git/blame - src/libcharon/encoding/payloads/encrypted_payload.c
encrypted-payload: Change how the length for reassembled messages is calculated
[thirdparty/strongswan.git] / src / libcharon / encoding / payloads / encrypted_payload.c
CommitLineData
0c7cfb18 1/*
62721936 2 * Copyright (C) 2011-2018 Tobias Brunner
b5190712
MW
3 * Copyright (C) 2005-2010 Martin Willi
4 * Copyright (C) 2010 revosec AG
c71d53ba 5 * Copyright (C) 2005 Jan Hutter
1b671669 6 * HSR Hochschule fuer Technik Rapperswil
0c7cfb18
MW
7 *
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>.
12 *
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
16 * for more details.
17 */
5113680f 18
0c7cfb18 19#include <stddef.h>
5113680f 20#include <string.h>
0c7cfb18 21
147fe503 22#include "encrypted_payload.h"
4c345b15 23#include "encrypted_fragment_payload.h"
0c7cfb18 24
ccf783d2 25#include <daemon.h>
0c7cfb18 26#include <encoding/payloads/encodings.h>
12642a68 27#include <collections/linked_list.h>
0c7cfb18 28#include <encoding/parser.h>
0c7cfb18 29
147fe503 30typedef struct private_encrypted_payload_t private_encrypted_payload_t;
4c345b15 31typedef struct private_encrypted_fragment_payload_t private_encrypted_fragment_payload_t;
0c7cfb18 32
147fe503 33struct private_encrypted_payload_t {
7daf5226 34
0c7cfb18 35 /**
147fe503 36 * Public encrypted_payload_t interface.
0c7cfb18 37 */
147fe503 38 encrypted_payload_t public;
7daf5226 39
0c7cfb18 40 /**
147fe503
TB
41 * There is no next payload for an encrypted payload,
42 * since encrypted payload MUST be the last one.
7daf5226 43 * next_payload means here the first payload of the
0c7cfb18
MW
44 * contained, encrypted payload.
45 */
b12c53ce 46 uint8_t next_payload;
0c7cfb18
MW
47
48 /**
b5190712 49 * Flags, including reserved bits
0c7cfb18 50 */
b12c53ce 51 uint8_t flags;
7daf5226 52
0c7cfb18
MW
53 /**
54 * Length of this payload
55 */
b12c53ce 56 uint16_t payload_length;
7daf5226 57
0c7cfb18 58 /**
b5190712 59 * Chunk containing the IV, plain, padding and ICV.
0c7cfb18
MW
60 */
61 chunk_t encrypted;
7daf5226 62
0c7cfb18 63 /**
b5190712 64 * AEAD transform to use
0f803b47 65 */
b5190712 66 aead_t *aead;
7daf5226 67
0c7cfb18 68 /**
b5190712 69 * Contained payloads
0c7cfb18
MW
70 */
71 linked_list_t *payloads;
6f5f8ee4
TB
72
73 /**
3ecfc83c 74 * Type of payload, PLV2_ENCRYPTED or PLV1_ENCRYPTED
6f5f8ee4
TB
75 */
76 payload_type_t type;
0c7cfb18
MW
77};
78
4c345b15
TB
79struct private_encrypted_fragment_payload_t {
80
81 /**
82 * Public interface.
83 */
84 encrypted_fragment_payload_t public;
85
86 /**
87 * The first fragment contains the type of the first payload contained in
88 * the original encrypted payload, for all other fragments it MUST be set
89 * to zero.
90 */
b12c53ce 91 uint8_t next_payload;
4c345b15
TB
92
93 /**
94 * Flags, including reserved bits
95 */
b12c53ce 96 uint8_t flags;
4c345b15
TB
97
98 /**
99 * Length of this payload
100 */
b12c53ce 101 uint16_t payload_length;
4c345b15
TB
102
103 /**
104 * Chunk containing the IV, plain, padding and ICV.
105 */
106 chunk_t encrypted;
107
108 /**
109 * Fragment number
110 */
b12c53ce 111 uint16_t fragment_number;
4c345b15
TB
112
113 /**
114 * Total fragments
115 */
b12c53ce 116 uint16_t total_fragments;
4c345b15
TB
117
118 /**
119 * AEAD transform to use
120 */
121 aead_t *aead;
122
123 /**
124 * Chunk containing the plain packet data.
125 */
126 chunk_t plain;
127};
128
0c7cfb18 129/**
147fe503 130 * Encoding rules to parse or generate a IKEv2-Encrypted Payload.
7daf5226
MW
131 *
132 * The defined offsets are the positions in a object of type
147fe503 133 * private_encrypted_payload_t.
0c7cfb18 134 */
6f5f8ee4 135static encoding_rule_t encodings_v2[] = {
0c7cfb18 136 /* 1 Byte next payload type, stored in the field next_payload */
147fe503 137 { U_INT_8, offsetof(private_encrypted_payload_t, next_payload) },
b5190712 138 /* Critical and 7 reserved bits, all stored for reconstruction */
147fe503
TB
139 { U_INT_8, offsetof(private_encrypted_payload_t, flags) },
140 /* Length of the whole encrypted payload*/
141 { PAYLOAD_LENGTH, offsetof(private_encrypted_payload_t, payload_length) },
0c7cfb18 142 /* encrypted data, stored in a chunk. contains iv, data, padding */
147fe503 143 { CHUNK_DATA, offsetof(private_encrypted_payload_t, encrypted) },
0c7cfb18
MW
144};
145
146/*
147 1 2 3
148 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
149 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
150 ! Next Payload !C! RESERVED ! Payload Length !
151 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
152 ! Initialization Vector !
153 ! (length is block size for encryption algorithm) !
154 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
155 ! Encrypted IKE Payloads !
156 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
157 ! ! Padding (0-255 octets) !
158 +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+
159 ! ! Pad Length !
160 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
161 ~ Integrity Checksum Data ~
162 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
163*/
164
6f5f8ee4
TB
165/**
166 * Encoding rules to parse or generate a complete encrypted IKEv1 message.
167 *
168 * The defined offsets are the positions in a object of type
147fe503 169 * private_encrypted_payload_t.
6f5f8ee4
TB
170 */
171static encoding_rule_t encodings_v1[] = {
172 /* encrypted data, stored in a chunk */
147fe503 173 { ENCRYPTED_DATA, offsetof(private_encrypted_payload_t, encrypted) },
6f5f8ee4
TB
174};
175
176/*
177 1 2 3
178 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
179 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
6f5f8ee4
TB
180 ! Encrypted IKE Payloads !
181 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
182 ! ! Padding (0-255 octets) !
183 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
184*/
185
4c345b15
TB
186/**
187 * Encoding rules to parse or generate an IKEv2-Encrypted Fragment Payload.
188 *
189 * The defined offsets are the positions in a object of type
190 * private_encrypted_payload_t.
191 */
192static encoding_rule_t encodings_fragment[] = {
193 /* 1 Byte next payload type, stored in the field next_payload */
194 { U_INT_8, offsetof(private_encrypted_fragment_payload_t, next_payload) },
195 /* Critical and 7 reserved bits, all stored for reconstruction */
196 { U_INT_8, offsetof(private_encrypted_fragment_payload_t, flags) },
197 /* Length of the whole encryption payload*/
198 { PAYLOAD_LENGTH, offsetof(private_encrypted_fragment_payload_t, payload_length) },
199 /* Fragment number */
200 { U_INT_16, offsetof(private_encrypted_fragment_payload_t, fragment_number) },
201 /* Total number of fragments */
202 { U_INT_16, offsetof(private_encrypted_fragment_payload_t, total_fragments) },
203 /* encrypted data, stored in a chunk. contains iv, data, padding */
204 { CHUNK_DATA, offsetof(private_encrypted_fragment_payload_t, encrypted) },
205};
206
207/*
208 1 2 3
209 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
210 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
211 ! Next Payload !C! RESERVED ! Payload Length !
212 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
213 ! Fragment Number | Total Fragments !
214 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
215 ! Initialization Vector !
216 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
217 ! Encrypted IKE Payloads !
218 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
219 ! ! Padding (0-255 octets) !
220 +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+
221 ! ! Pad Length !
222 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
223 ~ Integrity Checksum Data ~
224 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
225*/
226
0cca7427 227METHOD(payload_t, verify, status_t,
147fe503 228 private_encrypted_payload_t *this)
0c7cfb18 229{
ee29afd4 230 return SUCCESS;
0c7cfb18
MW
231}
232
e9b55b83 233METHOD(payload_t, get_encoding_rules, int,
147fe503 234 private_encrypted_payload_t *this, encoding_rule_t **rules)
0c7cfb18 235{
3ecfc83c 236 if (this->type == PLV2_ENCRYPTED)
6f5f8ee4
TB
237 {
238 *rules = encodings_v2;
239 return countof(encodings_v2);
240 }
241 *rules = encodings_v1;
242 return countof(encodings_v1);
0c7cfb18
MW
243}
244
38fb67fb 245METHOD(payload_t, get_header_length, int,
147fe503 246 private_encrypted_payload_t *this)
38fb67fb 247{
3ecfc83c 248 if (this->type == PLV2_ENCRYPTED)
6f5f8ee4
TB
249 {
250 return 4;
251 }
252 return 0;
38fb67fb
MW
253}
254
0cca7427 255METHOD(payload_t, get_type, payload_type_t,
147fe503 256 private_encrypted_payload_t *this)
0c7cfb18 257{
6f5f8ee4 258 return this->type;
0c7cfb18
MW
259}
260
0cca7427 261METHOD(payload_t, get_next_type, payload_type_t,
147fe503 262 private_encrypted_payload_t *this)
0c7cfb18 263{
0cca7427 264 return this->next_payload;
0c7cfb18
MW
265}
266
0cca7427 267METHOD(payload_t, set_next_type, void,
147fe503 268 private_encrypted_payload_t *this, payload_type_t type)
0c7cfb18 269{
6f5f8ee4
TB
270 /* the next payload is set during add, still allow this for IKEv1 */
271 this->next_payload = type;
0c7cfb18
MW
272}
273
44996b58
TB
274/**
275 * Get length of encryption/integrity overhead for the given plaintext length
276 */
277static size_t compute_overhead(aead_t *aead, size_t len)
278{
279 size_t bs, overhead;
280
281 /* padding */
282 bs = aead->get_block_size(aead);
283 overhead = bs - (len % bs);
284 /* add iv */
285 overhead += aead->get_iv_size(aead);
286 /* add icv */
287 overhead += aead->get_icv_size(aead);
288 return overhead;
289}
290
60356f33 291/**
f3bb1bd0 292 * Compute the length of the whole payload
60356f33 293 */
147fe503 294static void compute_length(private_encrypted_payload_t *this)
60356f33 295{
0cca7427
MW
296 enumerator_t *enumerator;
297 payload_t *payload;
44996b58 298 size_t length = 0;
60356f33 299
b5190712 300 if (this->encrypted.len)
60356f33 301 {
b5190712 302 length = this->encrypted.len;
60356f33 303 }
b5190712 304 else
60356f33 305 {
b5190712
MW
306 enumerator = this->payloads->create_enumerator(this->payloads);
307 while (enumerator->enumerate(enumerator, &payload))
308 {
309 length += payload->get_length(payload);
310 }
311 enumerator->destroy(enumerator);
312
313 if (this->aead)
314 {
44996b58 315 length += compute_overhead(this->aead, length);
b5190712 316 }
60356f33 317 }
38fb67fb 318 length += get_header_length(this);
60356f33
MW
319 this->payload_length = length;
320}
321
147fe503
TB
322METHOD2(payload_t, encrypted_payload_t, get_length, size_t,
323 private_encrypted_payload_t *this)
0c7cfb18 324{
60356f33 325 compute_length(this);
0c7cfb18
MW
326 return this->payload_length;
327}
328
62721936
TB
329METHOD2(payload_t, encrypted_payload_t, get_length_plain, size_t,
330 private_encrypted_payload_t *this)
331{
332 /* contains only the decrypted payload data, no IV, padding or ICV */
333 this->payload_length = this->encrypted.len;
334
335 if (this->aead)
336 {
337 this->payload_length += compute_overhead(this->aead,
338 this->payload_length);
339 }
340 this->payload_length += get_header_length(this);
341 return this->payload_length;
342}
343
147fe503
TB
344METHOD(encrypted_payload_t, add_payload, void,
345 private_encrypted_payload_t *this, payload_t *payload)
0c7cfb18
MW
346{
347 payload_t *last_payload;
0cca7427 348
3fe05870 349 if (this->payloads->get_count(this->payloads) > 0)
0c7cfb18 350 {
0cca7427 351 this->payloads->get_last(this->payloads, (void **)&last_payload);
0f803b47 352 last_payload->set_next_type(last_payload, payload->get_type(payload));
0c7cfb18
MW
353 }
354 else
355 {
0f803b47 356 this->next_payload = payload->get_type(payload);
0c7cfb18 357 }
3ecfc83c 358 payload->set_next_type(payload, PL_NONE);
0cca7427 359 this->payloads->insert_last(this->payloads, payload);
60356f33 360 compute_length(this);
0c7cfb18
MW
361}
362
147fe503
TB
363METHOD(encrypted_payload_t, remove_payload, payload_t *,
364 private_encrypted_payload_t *this)
bc788302 365{
b5190712
MW
366 payload_t *payload;
367
368 if (this->payloads->remove_first(this->payloads,
369 (void**)&payload) == SUCCESS)
370 {
371 return payload;
372 }
373 return NULL;
bc788302
MW
374}
375
60356f33 376/**
b5190712 377 * Generate payload before encryption
60356f33 378 */
147fe503 379static chunk_t generate(private_encrypted_payload_t *this,
b5190712 380 generator_t *generator)
60356f33 381{
0cca7427 382 payload_t *current, *next;
0cca7427 383 enumerator_t *enumerator;
b12c53ce 384 uint32_t *lenpos;
b5190712 385 chunk_t chunk = chunk_empty;
7daf5226 386
0cca7427
MW
387 enumerator = this->payloads->create_enumerator(this->payloads);
388 if (enumerator->enumerate(enumerator, &current))
60356f33 389 {
0cca7427
MW
390 this->next_payload = current->get_type(current);
391
0cca7427
MW
392 while (enumerator->enumerate(enumerator, &next))
393 {
394 current->set_next_type(current, next->get_type(next));
395 generator->generate_payload(generator, current);
396 current = next;
397 }
3ecfc83c 398 current->set_next_type(current, PL_NONE);
0cca7427
MW
399 generator->generate_payload(generator, current);
400
b5190712 401 chunk = generator->get_chunk(generator, &lenpos);
147fe503 402 DBG2(DBG_ENC, "generated content in encrypted payload");
60356f33 403 }
0cca7427 404 enumerator->destroy(enumerator);
b5190712 405 return chunk;
60356f33 406}
bc788302 407
1e0d8f3e
TB
408METHOD(encrypted_payload_t, generate_payloads, void,
409 private_encrypted_payload_t *this, generator_t *generator)
410{
411 generate(this, generator);
412}
413
b5190712 414/**
147fe503 415 * Append the encrypted payload header to the associated data
b5190712 416 */
147fe503 417static chunk_t append_header(private_encrypted_payload_t *this, chunk_t assoc)
b5190712
MW
418{
419 struct {
b12c53ce
AS
420 uint8_t next_payload;
421 uint8_t flags;
422 uint16_t length;
b5190712
MW
423 } __attribute__((packed)) header = {
424 .next_payload = this->next_payload,
425 .flags = this->flags,
426 .length = htons(get_length(this)),
427 };
428 return chunk_cat("cc", assoc, chunk_from_thing(header));
429}
430
44996b58
TB
431/**
432 * Encrypts the data in plain and returns it in an allocated chunk.
433 */
b12c53ce 434static status_t encrypt_content(char *label, aead_t *aead, uint64_t mid,
44996b58 435 chunk_t plain, chunk_t assoc, chunk_t *encrypted)
0c7cfb18 436{
44996b58 437 chunk_t iv, padding, icv, crypt;
b5010707 438 iv_gen_t *iv_gen;
6a365f07 439 rng_t *rng;
b5190712 440 size_t bs;
7daf5226 441
6a365f07
MW
442 rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
443 if (!rng)
444 {
44996b58 445 DBG1(DBG_ENC, "encrypting %s failed, no RNG found", label);
511f0b18 446 return NOT_SUPPORTED;
6a365f07 447 }
7daf5226 448
44996b58 449 iv_gen = aead->get_iv_gen(aead);
b5010707
TB
450 if (!iv_gen)
451 {
44996b58 452 DBG1(DBG_ENC, "encrypting %s failed, no IV generator", label);
b5010707
TB
453 return NOT_SUPPORTED;
454 }
455
44996b58 456 bs = aead->get_block_size(aead);
b5190712
MW
457 /* we need at least one byte padding to store the padding length */
458 padding.len = bs - (plain.len % bs);
44996b58
TB
459 iv.len = aead->get_iv_size(aead);
460 icv.len = aead->get_icv_size(aead);
b5190712
MW
461
462 /* prepare data to authenticate-encrypt:
463 * | IV | plain | padding | ICV |
464 * \____crypt______/ ^
465 * | /
466 * v /
467 * assoc -> + ------->/
468 */
44996b58
TB
469 *encrypted = chunk_alloc(iv.len + plain.len + padding.len + icv.len);
470 iv.ptr = encrypted->ptr;
b5190712
MW
471 memcpy(iv.ptr + iv.len, plain.ptr, plain.len);
472 plain.ptr = iv.ptr + iv.len;
473 padding.ptr = plain.ptr + plain.len;
474 icv.ptr = padding.ptr + padding.len;
475 crypt = chunk_create(plain.ptr, plain.len + padding.len);
b5190712 476
e8229ad5 477 if (!iv_gen->get_iv(iv_gen, mid, iv.len, iv.ptr) ||
ca9b68eb
TB
478 !rng->get_bytes(rng, padding.len - 1, padding.ptr))
479 {
44996b58 480 DBG1(DBG_ENC, "encrypting %s failed, no IV or padding", label);
ca9b68eb 481 rng->destroy(rng);
44996b58 482
511f0b18 483 return FAILED;
ca9b68eb 484 }
b5190712
MW
485 padding.ptr[padding.len - 1] = padding.len - 1;
486 rng->destroy(rng);
7daf5226 487
44996b58 488 DBG3(DBG_ENC, "%s encryption:", label);
b5190712
MW
489 DBG3(DBG_ENC, "IV %B", &iv);
490 DBG3(DBG_ENC, "plain %B", &plain);
491 DBG3(DBG_ENC, "padding %B", &padding);
492 DBG3(DBG_ENC, "assoc %B", &assoc);
7daf5226 493
44996b58 494 if (!aead->encrypt(aead, crypt, assoc, iv, NULL))
e2ed7bfd 495 {
511f0b18 496 return FAILED;
e2ed7bfd 497 }
b5190712
MW
498 DBG3(DBG_ENC, "encrypted %B", &crypt);
499 DBG3(DBG_ENC, "ICV %B", &icv);
44996b58
TB
500 return SUCCESS;
501}
7daf5226 502
44996b58 503METHOD(encrypted_payload_t, encrypt, status_t,
b12c53ce 504 private_encrypted_payload_t *this, uint64_t mid, chunk_t assoc)
44996b58
TB
505{
506 generator_t *generator;
507 chunk_t plain;
508 status_t status;
7daf5226 509
44996b58
TB
510 if (this->aead == NULL)
511 {
512 DBG1(DBG_ENC, "encrypting encrypted payload failed, transform missing");
513 return INVALID_STATE;
514 }
515
516 free(this->encrypted.ptr);
517 generator = generator_create();
518 plain = generate(this, generator);
519 assoc = append_header(this, assoc);
62e0abe7
MW
520 /* lower 32-bits are for fragment number, if used */
521 mid <<= 32;
44996b58
TB
522 status = encrypt_content("encrypted payload", this->aead, mid, plain, assoc,
523 &this->encrypted);
524 generator->destroy(generator);
525 free(assoc.ptr);
526 return status;
0c7cfb18
MW
527}
528
147fe503 529METHOD(encrypted_payload_t, encrypt_v1, status_t,
b12c53ce 530 private_encrypted_payload_t *this, uint64_t mid, chunk_t iv)
6f5f8ee4
TB
531{
532 generator_t *generator;
533 chunk_t plain, padding;
534 size_t bs;
535
536 if (this->aead == NULL)
537 {
538 DBG1(DBG_ENC, "encryption failed, transform missing");
511f0b18 539 return INVALID_STATE;
6f5f8ee4
TB
540 }
541
542 generator = generator_create();
543 plain = generate(this, generator);
544 bs = this->aead->get_block_size(this->aead);
545 padding.len = bs - (plain.len % bs);
546
547 /* prepare data to encrypt:
548 * | plain | padding | */
549 free(this->encrypted.ptr);
550 this->encrypted = chunk_alloc(plain.len + padding.len);
551 memcpy(this->encrypted.ptr, plain.ptr, plain.len);
552 plain.ptr = this->encrypted.ptr;
553 padding.ptr = plain.ptr + plain.len;
554 memset(padding.ptr, 0, padding.len);
555 generator->destroy(generator);
556
557 DBG3(DBG_ENC, "encrypting payloads:");
2e62f51b 558 DBG3(DBG_ENC, "IV %B", &iv);
6f5f8ee4
TB
559 DBG3(DBG_ENC, "plain %B", &plain);
560 DBG3(DBG_ENC, "padding %B", &padding);
561
e2ed7bfd
MW
562 if (!this->aead->encrypt(this->aead, this->encrypted, chunk_empty, iv, NULL))
563 {
511f0b18 564 return FAILED;
e2ed7bfd 565 }
6f5f8ee4
TB
566
567 DBG3(DBG_ENC, "encrypted %B", &this->encrypted);
568
511f0b18 569 return SUCCESS;
6f5f8ee4
TB
570}
571
60356f33
MW
572/**
573 * Parse the payloads after decryption.
574 */
147fe503 575static status_t parse(private_encrypted_payload_t *this, chunk_t plain)
60356f33
MW
576{
577 parser_t *parser;
0cca7427 578 payload_type_t type;
7daf5226 579
b5190712 580 parser = parser_create(plain);
42e0a317 581 parser->set_major_version(parser, this->type == PLV1_ENCRYPTED ? 1 : 2);
0cca7427 582 type = this->next_payload;
3ecfc83c 583 while (type != PL_NONE)
60356f33 584 {
0cca7427 585 payload_t *payload;
7daf5226 586
dd5c3787
MW
587 if (plain.len < 4 || untoh16(plain.ptr + 2) > plain.len)
588 {
589 DBG1(DBG_ENC, "invalid %N payload length, decryption failed?",
590 payload_type_names, type);
591 parser->destroy(parser);
592 return PARSE_ERROR;
593 }
b5190712 594 if (parser->parse_payload(parser, type, &payload) != SUCCESS)
60356f33
MW
595 {
596 parser->destroy(parser);
e5c6ebb6 597 return PARSE_ERROR;
60356f33 598 }
b5190712 599 if (payload->verify(payload) != SUCCESS)
60356f33 600 {
b83806d8 601 DBG1(DBG_ENC, "%N verification failed",
0cca7427
MW
602 payload_type_names, payload->get_type(payload));
603 payload->destroy(payload);
60356f33 604 parser->destroy(parser);
e5c6ebb6 605 return VERIFY_ERROR;
60356f33 606 }
0cca7427
MW
607 type = payload->get_next_type(payload);
608 this->payloads->insert_last(this->payloads, payload);
60356f33
MW
609 }
610 parser->destroy(parser);
147fe503 611 DBG2(DBG_ENC, "parsed content of encrypted payload");
e5c6ebb6 612 return SUCCESS;
60356f33
MW
613}
614
44996b58
TB
615/**
616 * Decrypts the given data in-place and returns a chunk pointing to the
617 * resulting plaintext.
618 */
619static status_t decrypt_content(char *label, aead_t *aead, chunk_t encrypted,
620 chunk_t assoc, chunk_t *plain)
0c7cfb18 621{
44996b58 622 chunk_t iv, padding, icv, crypt;
b5190712 623 size_t bs;
7daf5226 624
b5190712
MW
625 /* prepare data to authenticate-decrypt:
626 * | IV | plain | padding | ICV |
627 * \____crypt______/ ^
628 * | /
629 * v /
630 * assoc -> + ------->/
631 */
44996b58
TB
632 bs = aead->get_block_size(aead);
633 iv.len = aead->get_iv_size(aead);
634 iv.ptr = encrypted.ptr;
635 icv.len = aead->get_icv_size(aead);
636 icv.ptr = encrypted.ptr + encrypted.len - icv.len;
b5190712 637 crypt.ptr = iv.ptr + iv.len;
44996b58 638 crypt.len = encrypted.len - iv.len;
7daf5226 639
44996b58 640 if (iv.len + icv.len > encrypted.len ||
b5190712 641 (crypt.len - icv.len) % bs)
0c7cfb18 642 {
44996b58 643 DBG1(DBG_ENC, "decrypting %s payload failed, invalid length", label);
e5c6ebb6 644 return FAILED;
0c7cfb18 645 }
7daf5226 646
44996b58 647 DBG3(DBG_ENC, "%s decryption:", label);
b5190712
MW
648 DBG3(DBG_ENC, "IV %B", &iv);
649 DBG3(DBG_ENC, "encrypted %B", &crypt);
650 DBG3(DBG_ENC, "ICV %B", &icv);
651 DBG3(DBG_ENC, "assoc %B", &assoc);
7daf5226 652
44996b58 653 if (!aead->decrypt(aead, crypt, assoc, iv, NULL))
0c7cfb18 654 {
44996b58 655 DBG1(DBG_ENC, "verifying %s integrity failed", label);
e5c6ebb6 656 return FAILED;
0c7cfb18 657 }
7daf5226 658
44996b58
TB
659 *plain = chunk_create(crypt.ptr, crypt.len - icv.len);
660 padding.len = plain->ptr[plain->len - 1] + 1;
661 if (padding.len > plain->len)
0c7cfb18 662 {
44996b58
TB
663 DBG1(DBG_ENC, "decrypting %s failed, padding invalid %B", label,
664 &crypt);
e5c6ebb6 665 return PARSE_ERROR;
0c7cfb18 666 }
44996b58
TB
667 plain->len -= padding.len;
668 padding.ptr = plain->ptr + plain->len;
7daf5226 669
44996b58 670 DBG3(DBG_ENC, "plain %B", plain);
b5190712 671 DBG3(DBG_ENC, "padding %B", &padding);
44996b58
TB
672 return SUCCESS;
673}
674
675METHOD(encrypted_payload_t, decrypt, status_t,
676 private_encrypted_payload_t *this, chunk_t assoc)
677{
678 chunk_t plain;
679 status_t status;
7daf5226 680
44996b58
TB
681 if (this->aead == NULL)
682 {
683 DBG1(DBG_ENC, "decrypting encrypted payload failed, transform missing");
684 return INVALID_STATE;
685 }
686
687 assoc = append_header(this, assoc);
688 status = decrypt_content("encrypted payload", this->aead, this->encrypted,
689 assoc, &plain);
690 free(assoc.ptr);
691
692 if (status != SUCCESS)
693 {
694 return status;
695 }
b5190712
MW
696 return parse(this, plain);
697}
7daf5226 698
edfd3345
TB
699METHOD(encrypted_payload_t, decrypt_plain, status_t,
700 private_encrypted_payload_t *this, chunk_t assoc)
701{
702 if (!this->encrypted.ptr)
703 {
704 return FAILED;
705 }
706 return parse(this, this->encrypted);
707}
708
147fe503
TB
709METHOD(encrypted_payload_t, decrypt_v1, status_t,
710 private_encrypted_payload_t *this, chunk_t iv)
6f5f8ee4
TB
711{
712 if (this->aead == NULL)
713 {
714 DBG1(DBG_ENC, "decryption failed, transform missing");
6f5f8ee4
TB
715 return INVALID_STATE;
716 }
717
718 /* data must be a multiple of block size */
719 if (iv.len != this->aead->get_block_size(this->aead) ||
720 this->encrypted.len < iv.len || this->encrypted.len % iv.len)
721 {
722 DBG1(DBG_ENC, "decryption failed, invalid length");
6f5f8ee4
TB
723 return FAILED;
724 }
725
726 DBG3(DBG_ENC, "decrypting payloads:");
727 DBG3(DBG_ENC, "encrypted %B", &this->encrypted);
728
511f0b18
MW
729 if (!this->aead->decrypt(this->aead, this->encrypted, chunk_empty, iv, NULL))
730 {
731 return FAILED;
732 }
6f5f8ee4
TB
733
734 DBG3(DBG_ENC, "plain %B", &this->encrypted);
735
736 return parse(this, this->encrypted);
737}
738
147fe503
TB
739METHOD(encrypted_payload_t, set_transform, void,
740 private_encrypted_payload_t *this, aead_t* aead)
b5190712
MW
741{
742 this->aead = aead;
0c7cfb18
MW
743}
744
cc1f01e0
TB
745METHOD(encrypted_payload_t, get_transform, aead_t*,
746 private_encrypted_payload_t *this)
747{
748 return this->aead;
749}
750
147fe503
TB
751METHOD2(payload_t, encrypted_payload_t, destroy, void,
752 private_encrypted_payload_t *this)
ccf783d2 753{
55bbff11 754 this->payloads->destroy_offset(this->payloads, offsetof(payload_t, destroy));
5113680f 755 free(this->encrypted.ptr);
5113680f 756 free(this);
ccf783d2
MW
757}
758
0c7cfb18
MW
759/*
760 * Described in header
761 */
147fe503 762encrypted_payload_t *encrypted_payload_create(payload_type_t type)
0c7cfb18 763{
147fe503 764 private_encrypted_payload_t *this;
0cca7427
MW
765
766 INIT(this,
767 .public = {
768 .payload_interface = {
769 .verify = _verify,
770 .get_encoding_rules = _get_encoding_rules,
38fb67fb 771 .get_header_length = _get_header_length,
0cca7427
MW
772 .get_length = _get_length,
773 .get_next_type = _get_next_type,
774 .set_next_type = _set_next_type,
775 .get_type = _get_type,
776 .destroy = _destroy,
777 },
b5190712 778 .get_length = _get_length,
0cca7427 779 .add_payload = _add_payload,
b5190712 780 .remove_payload = _remove_payload,
1e0d8f3e 781 .generate_payloads = _generate_payloads,
b5190712 782 .set_transform = _set_transform,
cc1f01e0 783 .get_transform = _get_transform,
0cca7427
MW
784 .encrypt = _encrypt,
785 .decrypt = _decrypt,
0cca7427
MW
786 .destroy = _destroy,
787 },
3ecfc83c 788 .next_payload = PL_NONE,
0cca7427 789 .payloads = linked_list_create(),
6f5f8ee4 790 .type = type,
0cca7427 791 );
f3d98a6b 792 this->payload_length = get_header_length(this);
0cca7427 793
3ecfc83c 794 if (type == PLV1_ENCRYPTED)
6f5f8ee4
TB
795 {
796 this->public.encrypt = _encrypt_v1;
797 this->public.decrypt = _decrypt_v1;
798 }
799
0cca7427 800 return &this->public;
0c7cfb18 801}
edfd3345
TB
802
803/*
804 * Described in header
805 */
806encrypted_payload_t *encrypted_payload_create_from_plain(payload_type_t next,
807 chunk_t plain)
808{
809 private_encrypted_payload_t *this;
810
811 this = (private_encrypted_payload_t*)encrypted_payload_create(PLV2_ENCRYPTED);
62721936
TB
812 this->public.payload_interface.get_length = _get_length_plain;
813 this->public.get_length = _get_length_plain;
edfd3345
TB
814 this->public.decrypt = _decrypt_plain;
815 this->next_payload = next;
816 this->encrypted = plain;
edfd3345
TB
817
818 return &this->public;
819}
4c345b15
TB
820
821METHOD(payload_t, frag_verify, status_t,
822 private_encrypted_fragment_payload_t *this)
823{
824 if (!this->fragment_number || !this->total_fragments ||
825 this->fragment_number > this->total_fragments)
826 {
827 DBG1(DBG_ENC, "invalid fragment number (%u) or total fragments (%u)",
828 this->fragment_number, this->total_fragments);
829 return FAILED;
830 }
831 if (this->fragment_number > 1 && this->next_payload != 0)
832 {
833 DBG1(DBG_ENC, "invalid next payload (%u) for fragment %u, ignored",
834 this->next_payload, this->fragment_number);
835 this->next_payload = 0;
836 }
837 return SUCCESS;
838}
839
840METHOD(payload_t, frag_get_encoding_rules, int,
841 private_encrypted_fragment_payload_t *this, encoding_rule_t **rules)
842{
843 *rules = encodings_fragment;
844 return countof(encodings_fragment);
845}
846
847METHOD(payload_t, frag_get_header_length, int,
848 private_encrypted_fragment_payload_t *this)
849{
850 return 8;
851}
852
853METHOD(payload_t, frag_get_type, payload_type_t,
854 private_encrypted_fragment_payload_t *this)
855{
856 return PLV2_FRAGMENT;
857}
858
859METHOD(payload_t, frag_get_next_type, payload_type_t,
860 private_encrypted_fragment_payload_t *this)
861{
862 return this->next_payload;
863}
864
865METHOD(payload_t, frag_set_next_type, void,
866 private_encrypted_fragment_payload_t *this, payload_type_t type)
867{
868 if (this->fragment_number == 1 && this->next_payload == PL_NONE)
869 {
870 this->next_payload = type;
871 }
872}
873
874METHOD2(payload_t, encrypted_payload_t, frag_get_length, size_t,
875 private_encrypted_fragment_payload_t *this)
876{
877 if (this->encrypted.len)
878 {
879 this->payload_length = this->encrypted.len;
880 }
881 else
882 {
883 this->payload_length = this->plain.len;
884
885 if (this->aead)
886 {
887 this->payload_length += compute_overhead(this->aead,
888 this->payload_length);
889 }
890 }
891 this->payload_length += frag_get_header_length(this);
892 return this->payload_length;
893}
894
b12c53ce 895METHOD(encrypted_fragment_payload_t, get_fragment_number, uint16_t,
4c345b15
TB
896 private_encrypted_fragment_payload_t *this)
897{
898 return this->fragment_number;
899}
900
b12c53ce 901METHOD(encrypted_fragment_payload_t, get_total_fragments, uint16_t,
4c345b15
TB
902 private_encrypted_fragment_payload_t *this)
903{
904 return this->total_fragments;
905}
906
907METHOD(encrypted_fragment_payload_t, frag_get_content, chunk_t,
908 private_encrypted_fragment_payload_t *this)
909{
910 return this->plain;
911}
912
913METHOD(encrypted_payload_t, frag_add_payload, void,
914 private_encrypted_fragment_payload_t *this, payload_t* payload)
915{
916 payload->destroy(payload);
917}
918
919METHOD(encrypted_payload_t, frag_set_transform, void,
920 private_encrypted_fragment_payload_t *this, aead_t* aead)
921{
922 this->aead = aead;
923}
924
cc1f01e0
TB
925METHOD(encrypted_payload_t, frag_get_transform, aead_t*,
926 private_encrypted_fragment_payload_t *this)
927{
928 return this->aead;
929}
930
4c345b15
TB
931/**
932 * Append the encrypted fragment payload header to the associated data
933 */
934static chunk_t append_header_frag(private_encrypted_fragment_payload_t *this,
935 chunk_t assoc)
936{
937 struct {
b12c53ce
AS
938 uint8_t next_payload;
939 uint8_t flags;
940 uint16_t length;
941 uint16_t fragment_number;
942 uint16_t total_fragments;
4c345b15
TB
943 } __attribute__((packed)) header = {
944 .next_payload = this->next_payload,
945 .flags = this->flags,
946 .length = htons(frag_get_length(this)),
947 .fragment_number = htons(this->fragment_number),
948 .total_fragments = htons(this->total_fragments),
949 };
950 return chunk_cat("cc", assoc, chunk_from_thing(header));
951}
952
953METHOD(encrypted_payload_t, frag_encrypt, status_t,
b12c53ce 954 private_encrypted_fragment_payload_t *this, uint64_t mid, chunk_t assoc)
4c345b15
TB
955{
956 status_t status;
957
958 if (!this->aead)
959 {
960 DBG1(DBG_ENC, "encrypting encrypted fragment payload failed, "
961 "transform missing");
962 return INVALID_STATE;
963 }
964 free(this->encrypted.ptr);
965 assoc = append_header_frag(this, assoc);
62e0abe7
MW
966 /* IKEv2 message IDs are not unique if fragmentation is used, hence include
967 * the fragment number to make it unique */
968 mid = mid << 32 | this->fragment_number;
4c345b15
TB
969 status = encrypt_content("encrypted fragment payload", this->aead, mid,
970 this->plain, assoc, &this->encrypted);
971 free(assoc.ptr);
972 return status;
973}
974
975METHOD(encrypted_payload_t, frag_decrypt, status_t,
976 private_encrypted_fragment_payload_t *this, chunk_t assoc)
977{
978 status_t status;
979
980 if (!this->aead)
981 {
982 DBG1(DBG_ENC, "decrypting encrypted fragment payload failed, "
983 "transform missing");
984 return INVALID_STATE;
985 }
986 free(this->plain.ptr);
987 assoc = append_header_frag(this, assoc);
988 status = decrypt_content("encrypted fragment payload", this->aead,
989 this->encrypted, assoc, &this->plain);
990 this->plain = chunk_clone(this->plain);
991 free(assoc.ptr);
992 return status;
993}
994
995METHOD2(payload_t, encrypted_payload_t, frag_destroy, void,
996 private_encrypted_fragment_payload_t *this)
997{
998 free(this->encrypted.ptr);
999 free(this->plain.ptr);
1000 free(this);
1001}
1002
1003/*
1004 * Described in header
1005 */
1006encrypted_fragment_payload_t *encrypted_fragment_payload_create()
1007{
1008 private_encrypted_fragment_payload_t *this;
1009
1010 INIT(this,
1011 .public = {
1012 .encrypted = {
1013 .payload_interface = {
1014 .verify = _frag_verify,
1015 .get_encoding_rules = _frag_get_encoding_rules,
1016 .get_header_length = _frag_get_header_length,
1017 .get_length = _frag_get_length,
1018 .get_next_type = _frag_get_next_type,
1019 .set_next_type = _frag_set_next_type,
1020 .get_type = _frag_get_type,
1021 .destroy = _frag_destroy,
1022 },
1023 .get_length = _frag_get_length,
1024 .add_payload = _frag_add_payload,
1025 .remove_payload = (void*)return_null,
1026 .generate_payloads = nop,
1027 .set_transform = _frag_set_transform,
cc1f01e0 1028 .get_transform = _frag_get_transform,
4c345b15
TB
1029 .encrypt = _frag_encrypt,
1030 .decrypt = _frag_decrypt,
1031 .destroy = _frag_destroy,
1032 },
1033 .get_fragment_number = _get_fragment_number,
1034 .get_total_fragments = _get_total_fragments,
1035 .get_content = _frag_get_content,
1036 },
1037 .next_payload = PL_NONE,
1038 );
1039 this->payload_length = frag_get_header_length(this);
1040
1041 return &this->public;
1042}
1043
1044/*
1045 * Described in header
1046 */
1047encrypted_fragment_payload_t *encrypted_fragment_payload_create_from_data(
b12c53ce 1048 uint16_t num, uint16_t total, chunk_t plain)
4c345b15
TB
1049{
1050 private_encrypted_fragment_payload_t *this;
1051
1052 this = (private_encrypted_fragment_payload_t*)encrypted_fragment_payload_create();
1053 this->fragment_number = num;
1054 this->total_fragments = total;
1055 this->plain = chunk_clone(plain);
1056
1057 return &this->public;
1058}