]> git.ipfire.org Git - people/ms/strongswan.git/blame - programs/charon/charon/encoding/payloads/encryption_payload.c
- import of strongswan-2.7.0
[people/ms/strongswan.git] / programs / charon / charon / encoding / payloads / encryption_payload.c
CommitLineData
0c7cfb18
MW
1/**
2 * @file encryption_payload.c
3 *
4 * @brief Implementation of encryption_payload_t.
5 *
6 */
7
8/*
9 * Copyright (C) 2005 Jan Hutter, Martin Willi
10 * Hochschule fuer Technik Rapperswil
11 *
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>.
16 *
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
20 * for more details.
21 */
5113680f 22
0c7cfb18 23#include <stddef.h>
5113680f 24#include <string.h>
0c7cfb18
MW
25
26#include "encryption_payload.h"
27
ccf783d2 28#include <daemon.h>
0c7cfb18 29#include <encoding/payloads/encodings.h>
0c7cfb18 30#include <utils/linked_list.h>
ccf783d2 31#include <utils/logger.h>
0c7cfb18
MW
32#include <encoding/generator.h>
33#include <encoding/parser.h>
34#include <utils/iterator.h>
35#include <utils/randomizer.h>
68621281 36#include <crypto/signers/signer.h>
0c7cfb18
MW
37
38
39
40
41typedef struct private_encryption_payload_t private_encryption_payload_t;
42
43/**
3fe05870 44 * Private data of an encryption_payload_t' Object.
0c7cfb18
MW
45 *
46 */
47struct private_encryption_payload_t {
c3dc864e 48
0c7cfb18 49 /**
3fe05870 50 * Public encryption_payload_t interface.
0c7cfb18
MW
51 */
52 encryption_payload_t public;
53
54 /**
55 * There is no next payload for an encryption payload,
56 * since encryption payload MUST be the last one.
57 * next_payload means here the first payload of the
58 * contained, encrypted payload.
59 */
60 u_int8_t next_payload;
61
62 /**
3fe05870 63 * Critical flag.
0c7cfb18
MW
64 */
65 bool critical;
66
67 /**
68 * Length of this payload
69 */
70 u_int16_t payload_length;
71
0c7cfb18 72 /**
3fe05870
JH
73 * Chunk containing the iv, data, padding,
74 * and (an eventually not calculated) signature.
0c7cfb18
MW
75 */
76 chunk_t encrypted;
77
78 /**
3fe05870 79 * Chunk containing the data in decrypted (unpadded) form.
0c7cfb18
MW
80 */
81 chunk_t decrypted;
82
83 /**
3fe05870 84 * Signer set by set_signer.
0c7cfb18
MW
85 */
86 signer_t *signer;
87
0f803b47
MW
88 /**
89 * Crypter, supplied by encrypt/decrypt
90 */
91 crypter_t *crypter;
92
0c7cfb18 93 /**
3fe05870 94 * Contained payloads of this encrpytion_payload.
0c7cfb18
MW
95 */
96 linked_list_t *payloads;
97
ccf783d2
MW
98 /**
99 * logger for this payload, uses MESSAGE context
100 */
101 logger_t *logger;
102
0c7cfb18
MW
103 /**
104 * @brief Computes the length of this payload.
105 *
106 * @param this calling private_encryption_payload_t object
0c7cfb18 107 */
3fe05870 108 void (*compute_length) (private_encryption_payload_t *this);
0c7cfb18
MW
109
110 /**
111 * @brief Generate payloads (unencrypted) in chunk decrypted.
112 *
113 * @param this calling private_encryption_payload_t object
0c7cfb18 114 */
3fe05870 115 void (*generate) (private_encryption_payload_t *this);
ccf783d2
MW
116
117 /**
118 * @brief Parse payloads from a (unencrypted) chunk.
119 *
120 * @param this calling private_encryption_payload_t object
121 */
0c7cfb18
MW
122 status_t (*parse) (private_encryption_payload_t *this);
123};
124
125/**
3fe05870 126 * Encoding rules to parse or generate a IKEv2-Encryption Payload.
0c7cfb18
MW
127 *
128 * The defined offsets are the positions in a object of type
129 * private_encryption_payload_t.
130 *
131 */
132encoding_rule_t encryption_payload_encodings[] = {
133 /* 1 Byte next payload type, stored in the field next_payload */
134 { U_INT_8, offsetof(private_encryption_payload_t, next_payload) },
135 /* the critical bit */
136 { FLAG, offsetof(private_encryption_payload_t, critical) },
137 /* 7 Bit reserved bits, nowhere stored */
138 { RESERVED_BIT, 0 },
139 { RESERVED_BIT, 0 },
140 { RESERVED_BIT, 0 },
141 { RESERVED_BIT, 0 },
142 { RESERVED_BIT, 0 },
143 { RESERVED_BIT, 0 },
144 { RESERVED_BIT, 0 },
145 /* Length of the whole encryption payload*/
146 { PAYLOAD_LENGTH, offsetof(private_encryption_payload_t, payload_length) },
147 /* encrypted data, stored in a chunk. contains iv, data, padding */
148 { ENCRYPTED_DATA, offsetof(private_encryption_payload_t, encrypted) },
149};
150
151/*
152 1 2 3
153 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
154 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
155 ! Next Payload !C! RESERVED ! Payload Length !
156 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
157 ! Initialization Vector !
158 ! (length is block size for encryption algorithm) !
159 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
160 ! Encrypted IKE Payloads !
161 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
162 ! ! Padding (0-255 octets) !
163 +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+
164 ! ! Pad Length !
165 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
166 ~ Integrity Checksum Data ~
167 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
168*/
169
170/**
3fe05870 171 * Implementation of payload_t.verify.
0c7cfb18
MW
172 */
173static status_t verify(private_encryption_payload_t *this)
174{
ee29afd4 175 return SUCCESS;
0c7cfb18
MW
176}
177
0c7cfb18 178/**
3fe05870 179 * Implementation of payload_t.get_encoding_rules.
0c7cfb18 180 */
3fe05870 181static void get_encoding_rules(private_encryption_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
0c7cfb18
MW
182{
183 *rules = encryption_payload_encodings;
184 *rule_count = sizeof(encryption_payload_encodings) / sizeof(encoding_rule_t);
0c7cfb18
MW
185}
186
187/**
3fe05870 188 * Implementation of payload_t.get_type.
0c7cfb18
MW
189 */
190static payload_type_t get_type(private_encryption_payload_t *this)
191{
192 return ENCRYPTED;
193}
194
195/**
3fe05870 196 * Implementation of payload_t.get_next_type.
0c7cfb18
MW
197 */
198static payload_type_t get_next_type(private_encryption_payload_t *this)
199{
200 /* returns first contained payload here */
201 return (this->next_payload);
202}
203
204/**
3fe05870 205 * Implementation of payload_t.set_next_type.
0c7cfb18 206 */
3fe05870 207static void set_next_type(private_encryption_payload_t *this, payload_type_t type)
0c7cfb18 208{
3fe05870
JH
209 /* set next type is not allowed, since this payload MUST be the last one
210 * and so nothing is done in here*/
0c7cfb18
MW
211}
212
213/**
3fe05870 214 * Implementation of payload_t.get_length.
0c7cfb18
MW
215 */
216static size_t get_length(private_encryption_payload_t *this)
217{
218 this->compute_length(this);
219 return this->payload_length;
220}
221
222/**
3fe05870 223 * Implementation of payload_t.create_payload_iterator.
0c7cfb18 224 */
a0753941 225static iterator_t *create_payload_iterator (private_encryption_payload_t *this, bool forward)
0c7cfb18 226{
a0753941 227 return (this->payloads->create_iterator(this->payloads, forward));
0c7cfb18
MW
228}
229
230/**
3fe05870 231 * Implementation of payload_t.add_payload.
0c7cfb18 232 */
3fe05870 233static void add_payload(private_encryption_payload_t *this, payload_t *payload)
0c7cfb18
MW
234{
235 payload_t *last_payload;
3fe05870 236 if (this->payloads->get_count(this->payloads) > 0)
0c7cfb18 237 {
3fe05870 238 this->payloads->get_last(this->payloads,(void **) &last_payload);
0f803b47 239 last_payload->set_next_type(last_payload, payload->get_type(payload));
0c7cfb18
MW
240 }
241 else
242 {
0f803b47 243 this->next_payload = payload->get_type(payload);
0c7cfb18
MW
244 }
245 payload->set_next_type(payload, NO_PAYLOAD);
0f803b47 246 this->payloads->insert_last(this->payloads, (void*)payload);
0c7cfb18 247 this->compute_length(this);
0c7cfb18
MW
248}
249
bc788302
MW
250/**
251 * Implementation of encryption_payload_t.remove_first_payload.
252 */
253static status_t remove_first_payload(private_encryption_payload_t *this, payload_t **payload)
254{
255 return this->payloads->remove_first(this->payloads, (void**)payload);
256}
257
258/**
259 * Implementation of encryption_payload_t.get_payload_count.
260 */
261static size_t get_payload_count(private_encryption_payload_t *this)
262{
263 return this->payloads->get_count(this->payloads);
264}
265
266
0c7cfb18 267/**
3fe05870 268 * Implementation of encryption_payload_t.encrypt.
0c7cfb18 269 */
0f803b47 270static status_t encrypt(private_encryption_payload_t *this)
0c7cfb18 271{
0f803b47 272 chunk_t iv, padding, to_crypt, result;
0c7cfb18
MW
273 randomizer_t *randomizer;
274 status_t status;
0f803b47 275 size_t block_size;
0c7cfb18 276
0f803b47 277 if (this->signer == NULL || this->crypter == NULL)
0c7cfb18 278 {
ccf783d2 279 this->logger->log(this->logger, ERROR, "could not encrypt, signer/crypter not set");
0c7cfb18
MW
280 return INVALID_STATE;
281 }
282
283 /* for random data in iv and padding */
284 randomizer = randomizer_create();
0c7cfb18 285
ccf783d2 286
0c7cfb18 287 /* build payload chunk */
3fe05870 288 this->generate(this);
0c7cfb18 289
aee3eb52 290 this->logger->log(this->logger, CONTROL|LEVEL2, "encrypting payloads");
16b9a73c 291 this->logger->log_chunk(this->logger, RAW|LEVEL2, "data to encrypt", this->decrypted);
ccf783d2 292
0c7cfb18 293 /* build padding */
0f803b47
MW
294 block_size = this->crypter->get_block_size(this->crypter);
295 padding.len = block_size - ((this->decrypted.len + 1) % block_size);
68621281
MW
296 status = randomizer->allocate_pseudo_random_bytes(randomizer, padding.len, &padding);
297 if (status != SUCCESS)
298 {
299 randomizer->destroy(randomizer);
300 return status;
301 }
0c7cfb18
MW
302
303 /* concatenate payload data, padding, padding len */
0f803b47 304 to_crypt.len = this->decrypted.len + padding.len + 1;
5113680f 305 to_crypt.ptr = malloc(to_crypt.len);
0c7cfb18 306
0f803b47
MW
307 memcpy(to_crypt.ptr, this->decrypted.ptr, this->decrypted.len);
308 memcpy(to_crypt.ptr + this->decrypted.len, padding.ptr, padding.len);
309 *(to_crypt.ptr + to_crypt.len - 1) = padding.len;
0c7cfb18
MW
310
311 /* build iv */
0f803b47 312 iv.len = block_size;
68621281 313 status = randomizer->allocate_pseudo_random_bytes(randomizer, iv.len, &iv);
0c7cfb18 314 randomizer->destroy(randomizer);
68621281
MW
315 if (status != SUCCESS)
316 {
5113680f
MW
317 chunk_free(&to_crypt);
318 chunk_free(&padding);
68621281
MW
319 return status;
320 }
30b5b412 321
16b9a73c 322 this->logger->log_chunk(this->logger, RAW|LEVEL2, "data before encryption with padding", to_crypt);
0c7cfb18 323
0f803b47 324 /* encrypt to_crypt chunk */
5113680f 325 free(this->encrypted.ptr);
0f803b47 326 status = this->crypter->encrypt(this->crypter, to_crypt, iv, &result);
5113680f
MW
327 free(padding.ptr);
328 free(to_crypt.ptr);
0c7cfb18
MW
329 if (status != SUCCESS)
330 {
aee3eb52 331 this->logger->log(this->logger, ERROR|LEVEL1, "encryption failed");
5113680f 332 free(iv.ptr);
0c7cfb18
MW
333 return status;
334 }
16b9a73c 335 this->logger->log_chunk(this->logger, RAW|LEVEL2, "data after encryption", result);
30b5b412 336
0c7cfb18 337
0f803b47
MW
338 /* build encrypted result with iv and signature */
339 this->encrypted.len = iv.len + result.len + this->signer->get_block_size(this->signer);
5113680f
MW
340 free(this->encrypted.ptr);
341 this->encrypted.ptr = malloc(this->encrypted.len);
0f803b47
MW
342
343 /* fill in result, signature is left out */
344 memcpy(this->encrypted.ptr, iv.ptr, iv.len);
345 memcpy(this->encrypted.ptr + iv.len, result.ptr, result.len);
346
5113680f
MW
347 free(result.ptr);
348 free(iv.ptr);
16b9a73c 349 this->logger->log_chunk(this->logger, RAW|LEVEL2, "data after encryption with IV and (invalid) signature", this->encrypted);
30b5b412 350
0c7cfb18
MW
351 return SUCCESS;
352}
353
354/**
3fe05870 355 * Implementation of encryption_payload_t.encrypt.
0c7cfb18 356 */
0f803b47 357static status_t decrypt(private_encryption_payload_t *this)
0c7cfb18
MW
358{
359 chunk_t iv, concatenated;
360 u_int8_t padding_length;
361 status_t status;
362
ccf783d2 363
aee3eb52 364 this->logger->log(this->logger, CONTROL|LEVEL2, "decrypting encryption payload");
16b9a73c 365 this->logger->log_chunk(this->logger, RAW|LEVEL2, "data before decryption with IV and (invalid) signature", this->encrypted);
30b5b412 366
ccf783d2 367
0f803b47 368 if (this->signer == NULL || this->crypter == NULL)
0c7cfb18 369 {
ccf783d2 370 this->logger->log(this->logger, ERROR, "could not decrypt, no crypter/signer set");
0c7cfb18
MW
371 return INVALID_STATE;
372 }
bc788302 373
0c7cfb18 374 /* get IV */
0f803b47 375 iv.len = this->crypter->get_block_size(this->crypter);
01de2f3c 376
0c7cfb18
MW
377 iv.ptr = this->encrypted.ptr;
378
379 /* point concatenated to data + padding + padding_length*/
380 concatenated.ptr = this->encrypted.ptr + iv.len;
381 concatenated.len = this->encrypted.len - iv.len - this->signer->get_block_size(this->signer);
0f803b47 382
0c7cfb18
MW
383 /* check the size of input:
384 * concatenated must be at least on block_size of crypter
385 */
386 if (concatenated.len < iv.len)
387 {
aee3eb52 388 this->logger->log(this->logger, ERROR|LEVEL1, "could not decrypt, invalid input");
0c7cfb18
MW
389 return FAILED;
390 }
391
392 /* free previus data, if any */
5113680f 393 free(this->decrypted.ptr);
0c7cfb18 394
16b9a73c 395 this->logger->log_chunk(this->logger, RAW|LEVEL2, "data before decryption", concatenated);
30b5b412 396
0f803b47 397 status = this->crypter->decrypt(this->crypter, concatenated, iv, &(this->decrypted));
0c7cfb18
MW
398 if (status != SUCCESS)
399 {
aee3eb52 400 this->logger->log(this->logger, ERROR|LEVEL1, "could not decrypt, decryption failed");
0c7cfb18
MW
401 return FAILED;
402 }
16b9a73c 403 this->logger->log_chunk(this->logger, RAW|LEVEL2, "data after decryption with padding", this->decrypted);
30b5b412 404
0c7cfb18
MW
405
406 /* get padding length, sits just bevore signature */
407 padding_length = *(this->decrypted.ptr + this->decrypted.len - 1);
0f803b47
MW
408 /* add one byte to the padding length, since the padding_length field is not included */
409 padding_length++;
0c7cfb18
MW
410 this->decrypted.len -= padding_length;
411
412 /* check size again */
413 if (padding_length > concatenated.len || this->decrypted.len < 0)
414 {
aee3eb52 415 this->logger->log(this->logger, ERROR|LEVEL1, "decryption failed, invalid padding length found. Invalid key?");
0c7cfb18
MW
416 /* decryption failed :-/ */
417 return FAILED;
418 }
419
420 /* free padding */
5113680f 421 this->decrypted.ptr = realloc(this->decrypted.ptr, this->decrypted.len);
16b9a73c 422 this->logger->log_chunk(this->logger, RAW|LEVEL2, "data after decryption without padding", this->decrypted);
aee3eb52 423 this->logger->log(this->logger, CONTROL|LEVEL2, "decryption successful, trying to parse content");
1b3f92d2 424 return (this->parse(this));
0c7cfb18
MW
425}
426
427/**
0f803b47 428 * Implementation of encryption_payload_t.set_transforms.
0c7cfb18 429 */
0f803b47 430static void set_transforms(private_encryption_payload_t *this, crypter_t* crypter, signer_t* signer)
0c7cfb18
MW
431{
432 this->signer = signer;
0f803b47 433 this->crypter = crypter;
0c7cfb18
MW
434}
435
436/**
3fe05870 437 * Implementation of encryption_payload_t.build_signature.
0c7cfb18
MW
438 */
439static status_t build_signature(private_encryption_payload_t *this, chunk_t data)
440{
441 chunk_t data_without_sig = data;
442 chunk_t sig;
443
444 if (this->signer == NULL)
445 {
ccf783d2 446 this->logger->log(this->logger, ERROR, "unable to build signature, no signer set");
0c7cfb18
MW
447 return INVALID_STATE;
448 }
449
450 sig.len = this->signer->get_block_size(this->signer);
451 data_without_sig.len -= sig.len;
452 sig.ptr = data.ptr + data_without_sig.len;
aee3eb52 453 this->logger->log(this->logger, CONTROL|LEVEL2, "building signature");
0c7cfb18
MW
454 this->signer->get_signature(this->signer, data_without_sig, sig.ptr);
455 return SUCCESS;
456}
457
458/**
3fe05870 459 * Implementation of encryption_payload_t.verify_signature.
0c7cfb18
MW
460 */
461static status_t verify_signature(private_encryption_payload_t *this, chunk_t data)
462{
463 chunk_t sig, data_without_sig;
464 bool valid;
465
466 if (this->signer == NULL)
467 {
ccf783d2 468 this->logger->log(this->logger, ERROR, "unable to verify signature, no signer set");
0c7cfb18
MW
469 return INVALID_STATE;
470 }
471 /* find signature in data chunk */
472 sig.len = this->signer->get_block_size(this->signer);
473 if (data.len <= sig.len)
474 {
aee3eb52 475 this->logger->log(this->logger, ERROR|LEVEL1, "unable to verify signature, invalid input");
0c7cfb18
MW
476 return FAILED;
477 }
478 sig.ptr = data.ptr + data.len - sig.len;
479
480 /* verify it */
481 data_without_sig.len = data.len - sig.len;
482 data_without_sig.ptr = data.ptr;
f1046648 483 valid = this->signer->verify_signature(this->signer, data_without_sig, sig);
0c7cfb18
MW
484
485 if (!valid)
486 {
aee3eb52 487 this->logger->log(this->logger, ERROR|LEVEL1, "signature verification failed");
0c7cfb18
MW
488 return FAILED;
489 }
490
aee3eb52 491 this->logger->log(this->logger, CONTROL|LEVEL2, "signature verification successful");
0c7cfb18
MW
492 return SUCCESS;
493}
494
495/**
3fe05870 496 * Implementation of private_encryption_payload_t.generate.
0c7cfb18 497 */
3fe05870 498static void generate(private_encryption_payload_t *this)
0c7cfb18 499{
0c7cfb18
MW
500 payload_t *current_payload, *next_payload;
501 generator_t *generator;
502 iterator_t *iterator;
503
0f803b47
MW
504 /* recalculate length before generating */
505 this->compute_length(this);
506
0c7cfb18 507 /* create iterator */
a0753941 508 iterator = this->payloads->create_iterator(this->payloads, TRUE);
0c7cfb18
MW
509
510 /* get first payload */
511 if (iterator->has_next(iterator))
512 {
513 iterator->current(iterator, (void**)&current_payload);
514 this->next_payload = current_payload->get_type(current_payload);
515 }
516 else
517 {
518 /* no paylads? */
aee3eb52 519 this->logger->log(this->logger, CONTROL|LEVEL1, "generating contained payloads, but no available");
5113680f 520 free(this->decrypted.ptr);
0c7cfb18
MW
521 this->decrypted = CHUNK_INITIALIZER;
522 iterator->destroy(iterator);
3fe05870 523 return;
0c7cfb18
MW
524 }
525
526 generator = generator_create();
0c7cfb18
MW
527
528 /* build all payload, except last */
529 while(iterator->has_next(iterator))
530 {
531 iterator->current(iterator, (void**)&next_payload);
532 current_payload->set_next_type(current_payload, next_payload->get_type(next_payload));
0f30f568 533 generator->generate_payload(generator, current_payload);
0c7cfb18
MW
534 current_payload = next_payload;
535 }
536 iterator->destroy(iterator);
537
538 /* build last payload */
539 current_payload->set_next_type(current_payload, NO_PAYLOAD);
0f30f568 540 generator->generate_payload(generator, current_payload);
0c7cfb18
MW
541
542 /* free already generated data */
5113680f 543 free(this->decrypted.ptr);
0c7cfb18 544
0f30f568 545 generator->write_to_chunk(generator, &(this->decrypted));
0c7cfb18 546 generator->destroy(generator);
aee3eb52 547 this->logger->log(this->logger, CONTROL|LEVEL1, "successfully generated content in encrpytion payload");
0c7cfb18
MW
548}
549
3fe05870
JH
550/**
551 * Implementation of private_encryption_payload_t.parse.
552 */
0c7cfb18
MW
553static status_t parse(private_encryption_payload_t *this)
554{
555 parser_t *parser;
556 status_t status;
557 payload_type_t current_payload_type;
558
559 /* check if there is decrypted data */
560 if (this->decrypted.ptr == NULL)
561 {
ccf783d2 562 this->logger->log(this->logger, ERROR, "unable to parse, no input!");
0c7cfb18
MW
563 return INVALID_STATE;
564 }
565
566 /* build a parser on the decrypted data */
567 parser = parser_create(this->decrypted);
0c7cfb18
MW
568
569 current_payload_type = this->next_payload;
570 /* parse all payloads */
571 while (current_payload_type != NO_PAYLOAD)
572 {
573 payload_t *current_payload;
574
575 status = parser->parse_payload(parser, current_payload_type, (payload_t**)&current_payload);
576 if (status != SUCCESS)
577 {
0f803b47 578 parser->destroy(parser);
0c7cfb18
MW
579 return PARSE_ERROR;
580 }
1b3f92d2 581
0c7cfb18
MW
582 status = current_payload->verify(current_payload);
583 if (status != SUCCESS)
584 {
aee3eb52 585 this->logger->log(this->logger, ERROR|LEVEL1, "%s verification failed: %s",
ccf783d2
MW
586 mapping_find(payload_type_m,current_payload->get_type(current_payload)),
587 mapping_find(status_m, status));
1b3f92d2 588 current_payload->destroy(current_payload);
0f803b47 589 parser->destroy(parser);
0c7cfb18
MW
590 return VERIFY_ERROR;
591 }
592
593 /* get next payload type */
594 current_payload_type = current_payload->get_next_type(current_payload);
595
3fe05870 596 this->payloads->insert_last(this->payloads,current_payload);
0c7cfb18 597 }
0f803b47 598 parser->destroy(parser);
aee3eb52 599 this->logger->log(this->logger, CONTROL|LEVEL1, "succesfully parsed content of encryption payload");
0c7cfb18
MW
600 return SUCCESS;
601}
602
603/**
3fe05870 604 * Implementation of private_encryption_payload_t.compute_length.
0c7cfb18 605 */
3fe05870 606static void compute_length(private_encryption_payload_t *this)
0c7cfb18
MW
607{
608 iterator_t *iterator;
0f803b47 609 size_t block_size, length = 0;
a0753941 610 iterator = this->payloads->create_iterator(this->payloads, TRUE);
3fe05870 611
0f803b47 612 /* count payload length */
0c7cfb18
MW
613 while (iterator->has_next(iterator))
614 {
615 payload_t *current_payload;
616 iterator->current(iterator, (void **) &current_payload);
617 length += current_payload->get_length(current_payload);
618 }
619 iterator->destroy(iterator);
620
0f803b47
MW
621 if (this->crypter && this->signer)
622 {
623 /* append one byte for padding length */
624 length++;
625 /* append padding */
626 block_size = this->crypter->get_block_size(this->crypter);
627 length += block_size - length % block_size;
628 /* add iv */
629 length += block_size;
630 /* add signature */
631 length += this->signer->get_block_size(this->signer);
632 }
633 length += ENCRYPTION_PAYLOAD_HEADER_LENGTH;
0c7cfb18 634 this->payload_length = length;
0c7cfb18
MW
635}
636
ccf783d2
MW
637
638/**
639 * Implementation of payload_t.destroy.
640 */
641static void destroy(private_encryption_payload_t *this)
642{
643 /* all proposals are getting destroyed */
644 while (this->payloads->get_count(this->payloads) > 0)
645 {
646 payload_t *current_payload;
647 this->payloads->remove_last(this->payloads,(void **)&current_payload);
648 current_payload->destroy(current_payload);
649 }
650 this->payloads->destroy(this->payloads);
5113680f
MW
651 free(this->encrypted.ptr);
652 free(this->decrypted.ptr);
653 free(this);
ccf783d2
MW
654}
655
0c7cfb18
MW
656/*
657 * Described in header
658 */
659encryption_payload_t *encryption_payload_create()
660{
5113680f 661 private_encryption_payload_t *this = malloc_thing(private_encryption_payload_t);
0c7cfb18
MW
662
663 /* payload_t interface functions */
664 this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
3fe05870 665 this->public.payload_interface.get_encoding_rules = (void (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules;
0c7cfb18
MW
666 this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length;
667 this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type;
3fe05870 668 this->public.payload_interface.set_next_type = (void (*) (payload_t *,payload_type_t)) set_next_type;
0c7cfb18 669 this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_type;
3fe05870 670 this->public.payload_interface.destroy = (void (*) (payload_t *))destroy;
0c7cfb18
MW
671
672 /* public functions */
a0753941 673 this->public.create_payload_iterator = (iterator_t * (*) (encryption_payload_t *,bool)) create_payload_iterator;
3fe05870 674 this->public.add_payload = (void (*) (encryption_payload_t *,payload_t *)) add_payload;
bc788302
MW
675 this->public.remove_first_payload = (status_t (*)(encryption_payload_t*, payload_t **)) remove_first_payload;
676 this->public.get_payload_count = (size_t (*)(encryption_payload_t*)) get_payload_count;
677
0f803b47
MW
678 this->public.encrypt = (status_t (*) (encryption_payload_t *)) encrypt;
679 this->public.decrypt = (status_t (*) (encryption_payload_t *)) decrypt;
680 this->public.set_transforms = (void (*) (encryption_payload_t*,crypter_t*,signer_t*)) set_transforms;
0c7cfb18
MW
681 this->public.build_signature = (status_t (*) (encryption_payload_t*, chunk_t)) build_signature;
682 this->public.verify_signature = (status_t (*) (encryption_payload_t*, chunk_t)) verify_signature;
3fe05870 683 this->public.destroy = (void (*) (encryption_payload_t *)) destroy;
0c7cfb18
MW
684
685 /* private functions */
686 this->compute_length = compute_length;
687 this->generate = generate;
688 this->parse = parse;
5113680f 689 this->logger = logger_manager->get_logger(logger_manager, ENCRYPTION_PAYLOAD);
0c7cfb18
MW
690
691 /* set default values of the fields */
dec59822 692 this->critical = FALSE;
0c7cfb18
MW
693 this->next_payload = NO_PAYLOAD;
694 this->payload_length = ENCRYPTION_PAYLOAD_HEADER_LENGTH;
0c7cfb18
MW
695 this->encrypted = CHUNK_INITIALIZER;
696 this->decrypted = CHUNK_INITIALIZER;
0c7cfb18 697 this->signer = NULL;
0f803b47 698 this->crypter = NULL;
0c7cfb18
MW
699 this->payloads = linked_list_create();
700
0c7cfb18
MW
701 return (&(this->public));
702}