2 * Copyright (C) 2012-2013 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
, aad
, ciphertext
, plaintext
;
218 DESTROY_IF(this->payload
);
219 this->payload
= NULL
;
221 data
= this->packet
->get_data(this->packet
);
222 aead
= esp_context
->get_aead(esp_context
);
224 reader
= bio_reader_create(data
);
225 if (!reader
->read_uint32(reader
, &spi
) ||
226 !reader
->read_uint32(reader
, &seq
) ||
227 !reader
->read_data(reader
, aead
->get_iv_size(aead
), &iv
) ||
228 !reader
->read_data_end(reader
, aead
->get_icv_size(aead
), &icv
) ||
229 reader
->remaining(reader
) % aead
->get_block_size(aead
))
231 DBG1(DBG_ESP
, "ESP decryption failed: invalid length");
234 ciphertext
= reader
->peek(reader
);
235 ciphertext
.len
+= icv
.len
;
236 reader
->destroy(reader
);
238 if (!esp_context
->verify_seqno(esp_context
, seq
))
240 DBG1(DBG_ESP
, "ESP sequence number verification failed:\n "
241 "src %H, dst %H, SPI %.8x [seq %u]",
242 get_source(this), get_destination(this), spi
, seq
);
245 DBG3(DBG_ESP
, "ESP decryption:\n SPI %.8x [seq %u]\n IV %B\n "
246 "encrypted %B\n ICV %B", spi
, seq
, &iv
, &ciphertext
, &icv
);
248 /* aad = spi + seq */
249 aad
= chunk_create(data
.ptr
, 8);
251 if (!aead
->decrypt(aead
, ciphertext
, aad
, iv
, &plaintext
))
253 DBG1(DBG_ESP
, "ESP decryption or ICV verification failed");
256 esp_context
->set_authenticated_seqno(esp_context
, seq
);
258 if (!remove_padding(this, plaintext
))
266 * Generate the padding as specified in RFC4303
268 static void generate_padding(chunk_t padding
)
272 for (i
= 0; i
< padding
.len
; ++i
)
274 padding
.ptr
[i
] = (u_int8_t
)(i
+ 1);
278 METHOD(esp_packet_t
, encrypt
, status_t
,
279 private_esp_packet_t
*this, esp_context_t
*esp_context
, u_int32_t spi
)
281 chunk_t iv
, icv
, aad
, padding
, payload
, ciphertext
;
282 bio_writer_t
*writer
;
283 u_int32_t next_seqno
;
284 size_t blocksize
, plainlen
;
288 this->packet
->set_data(this->packet
, chunk_empty
);
290 if (!esp_context
->next_seqno(esp_context
, &next_seqno
))
292 DBG1(DBG_ESP
, "ESP encapsulation failed: sequence numbers cycled");
296 aead
= esp_context
->get_aead(esp_context
);
297 iv_gen
= aead
->get_iv_gen(aead
);
300 DBG1(DBG_ESP
, "ESP encryption failed: no IV generator");
304 blocksize
= aead
->get_block_size(aead
);
305 iv
.len
= aead
->get_iv_size(aead
);
306 icv
.len
= aead
->get_icv_size(aead
);
308 /* plaintext = payload, padding, pad_length, next_header */
309 payload
= this->payload ?
this->payload
->get_encoding(this->payload
)
311 plainlen
= payload
.len
+ 2;
312 padding
.len
= blocksize
- (plainlen
% blocksize
);
313 plainlen
+= padding
.len
;
315 /* len = spi, seq, IV, plaintext, ICV */
316 writer
= bio_writer_create(2 * sizeof(u_int32_t
) + iv
.len
+ plainlen
+
318 writer
->write_uint32(writer
, ntohl(spi
));
319 writer
->write_uint32(writer
, next_seqno
);
321 iv
= writer
->skip(writer
, iv
.len
);
322 if (!iv_gen
->get_iv(iv_gen
, next_seqno
, iv
.len
, iv
.ptr
))
324 DBG1(DBG_ESP
, "ESP encryption failed: could not generate IV");
325 writer
->destroy(writer
);
329 /* plain-/ciphertext will start here */
330 ciphertext
= writer
->get_buf(writer
);
331 ciphertext
.ptr
+= ciphertext
.len
;
332 ciphertext
.len
= plainlen
;
334 writer
->write_data(writer
, payload
);
336 padding
= writer
->skip(writer
, padding
.len
);
337 generate_padding(padding
);
339 writer
->write_uint8(writer
, padding
.len
);
340 writer
->write_uint8(writer
, this->next_header
);
342 /* aad = spi + seq */
343 aad
= writer
->get_buf(writer
);
345 icv
= writer
->skip(writer
, icv
.len
);
347 DBG3(DBG_ESP
, "ESP before encryption:\n payload = %B\n padding = %B\n "
348 "padding length = %hhu, next header = %hhu", &payload
, &padding
,
349 (u_int8_t
)padding
.len
, this->next_header
);
351 /* encrypt/authenticate the content inline */
352 if (!aead
->encrypt(aead
, ciphertext
, aad
, iv
, NULL
))
354 DBG1(DBG_ESP
, "ESP encryption or ICV generation failed");
355 writer
->destroy(writer
);
359 DBG3(DBG_ESP
, "ESP packet:\n SPI %.8x [seq %u]\n IV %B\n "
360 "encrypted %B\n ICV %B", ntohl(spi
), next_seqno
, &iv
,
363 this->packet
->set_data(this->packet
, writer
->extract_buf(writer
));
364 writer
->destroy(writer
);
368 METHOD(esp_packet_t
, get_next_header
, u_int8_t
,
369 private_esp_packet_t
*this)
371 return this->next_header
;
374 METHOD(esp_packet_t
, get_payload
, ip_packet_t
*,
375 private_esp_packet_t
*this)
377 return this->payload
;
380 METHOD(esp_packet_t
, extract_payload
, ip_packet_t
*,
381 private_esp_packet_t
*this)
383 ip_packet_t
*payload
;
385 payload
= this->payload
;
386 this->payload
= NULL
;
390 METHOD2(esp_packet_t
, packet_t
, destroy
, void,
391 private_esp_packet_t
*this)
393 DESTROY_IF(this->payload
);
394 this->packet
->destroy(this->packet
);
398 static private_esp_packet_t
*esp_packet_create_internal(packet_t
*packet
)
400 private_esp_packet_t
*this;
405 .set_source
= _set_source
,
406 .get_source
= _get_source
,
407 .set_destination
= _set_destination
,
408 .get_destination
= _get_destination
,
409 .get_data
= _get_data
,
410 .set_data
= _set_data
,
411 .get_dscp
= _get_dscp
,
412 .set_dscp
= _set_dscp
,
413 .skip_bytes
= _skip_bytes
,
417 .get_source
= _get_source
,
418 .get_destination
= _get_destination
,
419 .get_next_header
= _get_next_header
,
420 .parse_header
= _parse_header
,
423 .get_payload
= _get_payload
,
424 .extract_payload
= _extract_payload
,
428 .next_header
= IPPROTO_NONE
,
434 * Described in header.
436 esp_packet_t
*esp_packet_create_from_packet(packet_t
*packet
)
438 private_esp_packet_t
*this;
440 this = esp_packet_create_internal(packet
);
442 return &this->public;
446 * Described in header.
448 esp_packet_t
*esp_packet_create_from_payload(host_t
*src
, host_t
*dst
,
449 ip_packet_t
*payload
)
451 private_esp_packet_t
*this;
454 packet
= packet_create_from_data(src
, dst
, chunk_empty
);
455 this = esp_packet_create_internal(packet
);
456 this->payload
= payload
;
459 this->next_header
= payload
->get_version(payload
) == 4 ? IPPROTO_IPIP
464 this->next_header
= IPPROTO_NONE
;
466 return &this->public;