]>
Commit | Line | Data |
---|---|---|
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 | 30 | typedef struct private_encrypted_payload_t private_encrypted_payload_t; |
4c345b15 | 31 | typedef struct private_encrypted_fragment_payload_t private_encrypted_fragment_payload_t; |
0c7cfb18 | 32 | |
147fe503 | 33 | struct 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 |
79 | struct 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 | 135 | static 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 | */ |
171 | static 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 | */ | |
192 | static 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 | 227 | METHOD(payload_t, verify, status_t, |
147fe503 | 228 | private_encrypted_payload_t *this) |
0c7cfb18 | 229 | { |
ee29afd4 | 230 | return SUCCESS; |
0c7cfb18 MW |
231 | } |
232 | ||
e9b55b83 | 233 | METHOD(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 | 245 | METHOD(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 | 255 | METHOD(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 | 261 | METHOD(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 | 267 | METHOD(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 | */ | |
277 | static 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 | 294 | static 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 |
322 | METHOD2(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 |
329 | METHOD2(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 |
344 | METHOD(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 |
363 | METHOD(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 | 379 | static 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, ¤t)) | |
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 |
408 | METHOD(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 | 417 | static 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 | 434 | static 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 | 503 | METHOD(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 | 529 | METHOD(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 | 575 | static 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 | */ | |
619 | static 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 | ||
675 | METHOD(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 |
699 | METHOD(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 |
709 | METHOD(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 |
739 | METHOD(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 |
745 | METHOD(encrypted_payload_t, get_transform, aead_t*, |
746 | private_encrypted_payload_t *this) | |
747 | { | |
748 | return this->aead; | |
749 | } | |
750 | ||
147fe503 TB |
751 | METHOD2(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 | 762 | encrypted_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 | */ | |
806 | encrypted_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 | |
821 | METHOD(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 | ||
840 | METHOD(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 | ||
847 | METHOD(payload_t, frag_get_header_length, int, | |
848 | private_encrypted_fragment_payload_t *this) | |
849 | { | |
850 | return 8; | |
851 | } | |
852 | ||
853 | METHOD(payload_t, frag_get_type, payload_type_t, | |
854 | private_encrypted_fragment_payload_t *this) | |
855 | { | |
856 | return PLV2_FRAGMENT; | |
857 | } | |
858 | ||
859 | METHOD(payload_t, frag_get_next_type, payload_type_t, | |
860 | private_encrypted_fragment_payload_t *this) | |
861 | { | |
862 | return this->next_payload; | |
863 | } | |
864 | ||
865 | METHOD(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 | ||
874 | METHOD2(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 | 895 | METHOD(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 | 901 | METHOD(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 | ||
907 | METHOD(encrypted_fragment_payload_t, frag_get_content, chunk_t, | |
908 | private_encrypted_fragment_payload_t *this) | |
909 | { | |
910 | return this->plain; | |
911 | } | |
912 | ||
913 | METHOD(encrypted_payload_t, frag_add_payload, void, | |
914 | private_encrypted_fragment_payload_t *this, payload_t* payload) | |
915 | { | |
916 | payload->destroy(payload); | |
917 | } | |
918 | ||
919 | METHOD(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 |
925 | METHOD(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 | */ | |
934 | static 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 | ||
953 | METHOD(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 | ||
975 | METHOD(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 | ||
995 | METHOD2(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 | */ | |
1006 | encrypted_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 | */ | |
1047 | encrypted_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 | } |