2 * Copyright (C) 2012 Tobias Brunner
3 * Copyright (C) 2012 Giuliano Grassi
4 * Copyright (C) 2012 Ralf Sager
5 * Hochschule fuer Technik Rapperswil
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19 #include "esp_packet.h"
22 #include <utils/debug.h>
23 #include <crypto/crypters/crypter.h>
24 #include <crypto/signers/signer.h>
25 #include <bio/bio_reader.h>
26 #include <bio/bio_writer.h>
28 #include <netinet/in.h>
30 typedef struct private_esp_packet_t private_esp_packet_t
;
33 * Private additions to esp_packet_t.
35 struct private_esp_packet_t
{
48 * Payload of this packet
53 * Next Header info (e.g. IPPROTO_IPIP)
60 * Forward declaration for clone()
62 static private_esp_packet_t
*esp_packet_create_internal(packet_t
*packet
);
64 METHOD(packet_t
, set_source
, void,
65 private_esp_packet_t
*this, host_t
*src
)
67 return this->packet
->set_source(this->packet
, src
);
70 METHOD2(esp_packet_t
, packet_t
, get_source
, host_t
*,
71 private_esp_packet_t
*this)
73 return this->packet
->get_source(this->packet
);
76 METHOD(packet_t
, set_destination
, void,
77 private_esp_packet_t
*this, host_t
*dst
)
79 return this->packet
->set_destination(this->packet
, dst
);
82 METHOD2(esp_packet_t
, packet_t
, get_destination
, host_t
*,
83 private_esp_packet_t
*this)
85 return this->packet
->get_destination(this->packet
);
88 METHOD(packet_t
, get_data
, chunk_t
,
89 private_esp_packet_t
*this)
91 return this->packet
->get_data(this->packet
);
94 METHOD(packet_t
, set_data
, void,
95 private_esp_packet_t
*this, chunk_t data
)
97 return this->packet
->set_data(this->packet
, data
);
100 METHOD(packet_t
, get_dscp
, u_int8_t
,
101 private_esp_packet_t
*this)
103 return this->packet
->get_dscp(this->packet
);
106 METHOD(packet_t
, set_dscp
, void,
107 private_esp_packet_t
*this, u_int8_t value
)
109 this->packet
->set_dscp(this->packet
, value
);
112 METHOD(packet_t
, skip_bytes
, void,
113 private_esp_packet_t
*this, size_t bytes
)
115 return this->packet
->skip_bytes(this->packet
, bytes
);
118 METHOD(packet_t
, clone
, packet_t
*,
119 private_esp_packet_t
*this)
121 private_esp_packet_t
*pkt
;
123 pkt
= esp_packet_create_internal(this->packet
->clone(this->packet
));
124 pkt
->payload
= this->payload ?
this->payload
->clone(this->payload
) : NULL
;
125 pkt
->next_header
= this->next_header
;
126 return &pkt
->public.packet
;
129 METHOD(esp_packet_t
, parse_header
, bool,
130 private_esp_packet_t
*this, u_int32_t
*spi
)
132 bio_reader_t
*reader
;
135 reader
= bio_reader_create(this->packet
->get_data(this->packet
));
136 if (!reader
->read_uint32(reader
, spi
) ||
137 !reader
->read_uint32(reader
, &seq
))
139 DBG1(DBG_ESP
, "failed to parse ESP header: invalid length");
140 reader
->destroy(reader
);
143 reader
->destroy(reader
);
145 DBG2(DBG_ESP
, "parsed ESP header with SPI %.8x [seq %u]", *spi
, seq
);
151 * Check padding as specified in RFC 4303
153 static bool check_padding(chunk_t padding
)
157 for (i
= 0; i
< padding
.len
; ++i
)
159 if (padding
.ptr
[i
] != (u_int8_t
)(i
+ 1))
168 * Remove the padding from the payload and set the next header info
170 static bool remove_padding(private_esp_packet_t
*this, chunk_t plaintext
)
172 u_int8_t next_header
, pad_length
;
173 chunk_t padding
, payload
;
174 bio_reader_t
*reader
;
176 reader
= bio_reader_create(plaintext
);
177 if (!reader
->read_uint8_end(reader
, &next_header
) ||
178 !reader
->read_uint8_end(reader
, &pad_length
))
180 DBG1(DBG_ESP
, "parsing ESP payload failed: invalid length");
183 if (!reader
->read_data_end(reader
, pad_length
, &padding
) ||
184 !check_padding(padding
))
186 DBG1(DBG_ESP
, "parsing ESP payload failed: invalid padding");
189 this->payload
= ip_packet_create(reader
->peek(reader
));
190 reader
->destroy(reader
);
193 DBG1(DBG_ESP
, "parsing ESP payload failed: unsupported payload");
196 this->next_header
= next_header
;
197 payload
= this->payload
->get_encoding(this->payload
);
199 DBG3(DBG_ESP
, "ESP payload:\n payload %B\n padding %B\n "
200 "padding length = %hhu, next header = %hhu", &payload
, &padding
,
201 pad_length
, this->next_header
);
205 reader
->destroy(reader
);
206 chunk_free(&plaintext
);
210 METHOD(esp_packet_t
, decrypt
, status_t
,
211 private_esp_packet_t
*this, esp_context_t
*esp_context
)
213 bio_reader_t
*reader
;
215 chunk_t data
, iv
, icv
, ciphertext
, plaintext
;
219 DESTROY_IF(this->payload
);
220 this->payload
= NULL
;
222 data
= this->packet
->get_data(this->packet
);
223 crypter
= esp_context
->get_crypter(esp_context
);
224 signer
= esp_context
->get_signer(esp_context
);
226 reader
= bio_reader_create(data
);
227 if (!reader
->read_uint32(reader
, &spi
) ||
228 !reader
->read_uint32(reader
, &seq
) ||
229 !reader
->read_data(reader
, crypter
->get_iv_size(crypter
), &iv
) ||
230 !reader
->read_data_end(reader
, signer
->get_block_size(signer
), &icv
) ||
231 reader
->remaining(reader
) % crypter
->get_block_size(crypter
))
233 DBG1(DBG_ESP
, "ESP decryption failed: invalid length");
236 ciphertext
= reader
->peek(reader
);
237 reader
->destroy(reader
);
239 if (!esp_context
->verify_seqno(esp_context
, seq
))
241 DBG1(DBG_ESP
, "ESP sequence number verification failed:\n "
242 "src %H, dst %H, SPI %.8x [seq %u]",
243 get_source(this), get_destination(this), spi
, seq
);
246 DBG3(DBG_ESP
, "ESP decryption:\n SPI %.8x [seq %u]\n IV %B\n "
247 "encrypted %B\n ICV %B", spi
, seq
, &iv
, &ciphertext
, &icv
);
249 if (!signer
->get_signature(signer
, chunk_create(data
.ptr
, 8), NULL
) ||
250 !signer
->get_signature(signer
, iv
, NULL
) ||
251 !signer
->verify_signature(signer
, ciphertext
, icv
))
253 DBG1(DBG_ESP
, "ICV verification failed!");
256 esp_context
->set_authenticated_seqno(esp_context
, seq
);
258 if (!crypter
->decrypt(crypter
, ciphertext
, iv
, &plaintext
))
260 DBG1(DBG_ESP
, "ESP decryption failed");
264 if (!remove_padding(this, plaintext
))
272 * Generate the padding as specified in RFC4303
274 static void generate_padding(chunk_t padding
)
278 for (i
= 0; i
< padding
.len
; ++i
)
280 padding
.ptr
[i
] = (u_int8_t
)(i
+ 1);
284 METHOD(esp_packet_t
, encrypt
, status_t
,
285 private_esp_packet_t
*this, esp_context_t
*esp_context
, u_int32_t spi
)
287 chunk_t iv
, icv
, padding
, payload
, ciphertext
, auth_data
;
288 bio_writer_t
*writer
;
289 u_int32_t next_seqno
;
290 size_t blocksize
, plainlen
;
295 this->packet
->set_data(this->packet
, chunk_empty
);
297 if (!esp_context
->next_seqno(esp_context
, &next_seqno
))
299 DBG1(DBG_ESP
, "ESP encapsulation failed: sequence numbers cycled");
303 rng
= lib
->crypto
->create_rng(lib
->crypto
, RNG_WEAK
);
306 DBG1(DBG_ESP
, "ESP encryption failed: could not find RNG");
309 crypter
= esp_context
->get_crypter(esp_context
);
310 signer
= esp_context
->get_signer(esp_context
);
312 blocksize
= crypter
->get_block_size(crypter
);
313 iv
.len
= crypter
->get_iv_size(crypter
);
314 icv
.len
= signer
->get_block_size(signer
);
316 /* plaintext = payload, padding, pad_length, next_header */
317 payload
= this->payload ?
this->payload
->get_encoding(this->payload
)
319 plainlen
= payload
.len
+ 2;
320 padding
.len
= blocksize
- (plainlen
% blocksize
);
321 plainlen
+= padding
.len
;
323 /* len = spi, seq, IV, plaintext, ICV */
324 writer
= bio_writer_create(2 * sizeof(u_int32_t
) + iv
.len
+ plainlen
+
326 writer
->write_uint32(writer
, ntohl(spi
));
327 writer
->write_uint32(writer
, next_seqno
);
329 iv
= writer
->skip(writer
, iv
.len
);
330 if (!rng
->get_bytes(rng
, iv
.len
, iv
.ptr
))
332 DBG1(DBG_ESP
, "ESP encryption failed: could not generate IV");
333 writer
->destroy(writer
);
339 /* plain-/ciphertext will start here */
340 ciphertext
= writer
->get_buf(writer
);
341 ciphertext
.ptr
+= ciphertext
.len
;
342 ciphertext
.len
= plainlen
;
344 writer
->write_data(writer
, payload
);
346 padding
= writer
->skip(writer
, padding
.len
);
347 generate_padding(padding
);
349 writer
->write_uint8(writer
, padding
.len
);
350 writer
->write_uint8(writer
, this->next_header
);
352 DBG3(DBG_ESP
, "ESP before encryption:\n payload = %B\n padding = %B\n "
353 "padding length = %hhu, next header = %hhu", &payload
, &padding
,
354 (u_int8_t
)padding
.len
, this->next_header
);
356 /* encrypt the content inline */
357 if (!crypter
->encrypt(crypter
, ciphertext
, iv
, NULL
))
359 DBG1(DBG_ESP
, "ESP encryption failed");
360 writer
->destroy(writer
);
364 /* calculate signature */
365 auth_data
= writer
->get_buf(writer
);
366 icv
= writer
->skip(writer
, icv
.len
);
367 if (!signer
->get_signature(signer
, auth_data
, icv
.ptr
))
369 DBG1(DBG_ESP
, "ESP encryption failed: signature generation failed");
370 writer
->destroy(writer
);
374 DBG3(DBG_ESP
, "ESP packet:\n SPI %.8x [seq %u]\n IV %B\n "
375 "encrypted %B\n ICV %B", ntohl(spi
), next_seqno
, &iv
,
378 this->packet
->set_data(this->packet
, writer
->extract_buf(writer
));
379 writer
->destroy(writer
);
383 METHOD(esp_packet_t
, get_next_header
, u_int8_t
,
384 private_esp_packet_t
*this)
386 return this->next_header
;
389 METHOD(esp_packet_t
, get_payload
, ip_packet_t
*,
390 private_esp_packet_t
*this)
392 return this->payload
;
395 METHOD(esp_packet_t
, extract_payload
, ip_packet_t
*,
396 private_esp_packet_t
*this)
398 ip_packet_t
*payload
;
400 payload
= this->payload
;
401 this->payload
= NULL
;
405 METHOD2(esp_packet_t
, packet_t
, destroy
, void,
406 private_esp_packet_t
*this)
408 DESTROY_IF(this->payload
);
409 this->packet
->destroy(this->packet
);
413 static private_esp_packet_t
*esp_packet_create_internal(packet_t
*packet
)
415 private_esp_packet_t
*this;
420 .set_source
= _set_source
,
421 .get_source
= _get_source
,
422 .set_destination
= _set_destination
,
423 .get_destination
= _get_destination
,
424 .get_data
= _get_data
,
425 .set_data
= _set_data
,
426 .get_dscp
= _get_dscp
,
427 .set_dscp
= _set_dscp
,
428 .skip_bytes
= _skip_bytes
,
432 .get_source
= _get_source
,
433 .get_destination
= _get_destination
,
434 .get_next_header
= _get_next_header
,
435 .parse_header
= _parse_header
,
438 .get_payload
= _get_payload
,
439 .extract_payload
= _extract_payload
,
443 .next_header
= IPPROTO_NONE
,
449 * Described in header.
451 esp_packet_t
*esp_packet_create_from_packet(packet_t
*packet
)
453 private_esp_packet_t
*this;
455 this = esp_packet_create_internal(packet
);
457 return &this->public;
461 * Described in header.
463 esp_packet_t
*esp_packet_create_from_payload(host_t
*src
, host_t
*dst
,
464 ip_packet_t
*payload
)
466 private_esp_packet_t
*this;
469 packet
= packet_create_from_data(src
, dst
, chunk_empty
);
470 this = esp_packet_create_internal(packet
);
471 this->payload
= payload
;
474 this->next_header
= payload
->get_version(payload
) == 4 ? IPPROTO_IPIP
479 this->next_header
= IPPROTO_NONE
;
481 return &this->public;