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"
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
, skip_bytes
, void,
101 private_esp_packet_t
*this, size_t bytes
)
103 return this->packet
->skip_bytes(this->packet
, bytes
);
106 METHOD(packet_t
, clone
, packet_t
*,
107 private_esp_packet_t
*this)
109 private_esp_packet_t
*pkt
;
111 pkt
= esp_packet_create_internal(this->packet
->clone(this->packet
));
112 pkt
->payload
= this->payload ?
this->payload
->clone(this->payload
) : NULL
;
113 pkt
->next_header
= this->next_header
;
114 return &pkt
->public.packet
;
117 METHOD(esp_packet_t
, parse_header
, bool,
118 private_esp_packet_t
*this, u_int32_t
*spi
)
120 bio_reader_t
*reader
;
123 reader
= bio_reader_create(this->packet
->get_data(this->packet
));
124 if (!reader
->read_uint32(reader
, spi
) ||
125 !reader
->read_uint32(reader
, &seq
))
127 DBG1(DBG_ESP
, "failed to parse ESP header: invalid length");
128 reader
->destroy(reader
);
131 reader
->destroy(reader
);
133 DBG2(DBG_ESP
, "parsed ESP header with SPI %.8x [seq %u]", *spi
, seq
);
139 * Check padding as specified in RFC 4303
141 static bool check_padding(chunk_t padding
)
145 for (i
= 0; i
< padding
.len
; ++i
)
147 if (padding
.ptr
[i
] != (u_int8_t
)(i
+ 1))
156 * Remove the padding from the payload and set the next header info
158 static bool remove_padding(private_esp_packet_t
*this, chunk_t plaintext
)
160 u_int8_t next_header
, pad_length
;
161 chunk_t padding
, payload
;
162 bio_reader_t
*reader
;
164 reader
= bio_reader_create(plaintext
);
165 if (!reader
->read_uint8_end(reader
, &next_header
) ||
166 !reader
->read_uint8_end(reader
, &pad_length
))
168 DBG1(DBG_ESP
, "parsing ESP payload failed: invalid length");
171 if (!reader
->read_data_end(reader
, pad_length
, &padding
) ||
172 !check_padding(padding
))
174 DBG1(DBG_ESP
, "parsing ESP payload failed: invalid padding");
177 this->payload
= ip_packet_create(reader
->peek(reader
));
178 reader
->destroy(reader
);
181 DBG1(DBG_ESP
, "parsing ESP payload failed: unsupported payload");
184 this->next_header
= next_header
;
185 payload
= this->payload
->get_encoding(this->payload
);
187 DBG3(DBG_ESP
, "ESP payload:\n payload %B\n padding %B\n "
188 "padding length = %hhu, next header = %hhu", &payload
, &padding
,
189 pad_length
, this->next_header
);
193 reader
->destroy(reader
);
194 chunk_free(&plaintext
);
198 METHOD(esp_packet_t
, decrypt
, status_t
,
199 private_esp_packet_t
*this, esp_context_t
*esp_context
)
201 bio_reader_t
*reader
;
203 chunk_t data
, iv
, icv
, ciphertext
, plaintext
;
207 DESTROY_IF(this->payload
);
208 this->payload
= NULL
;
210 data
= this->packet
->get_data(this->packet
);
211 crypter
= esp_context
->get_crypter(esp_context
);
212 signer
= esp_context
->get_signer(esp_context
);
214 reader
= bio_reader_create(data
);
215 if (!reader
->read_uint32(reader
, &spi
) ||
216 !reader
->read_uint32(reader
, &seq
) ||
217 !reader
->read_data(reader
, crypter
->get_iv_size(crypter
), &iv
) ||
218 !reader
->read_data_end(reader
, signer
->get_block_size(signer
), &icv
) ||
219 reader
->remaining(reader
) % crypter
->get_block_size(crypter
))
221 DBG1(DBG_ESP
, "ESP decryption failed: invalid length");
224 ciphertext
= reader
->peek(reader
);
225 reader
->destroy(reader
);
227 if (!esp_context
->verify_seqno(esp_context
, seq
))
229 DBG1(DBG_ESP
, "ESP sequence number verification failed:\n "
230 "src %H, dst %H, SPI %.8x [seq %u]",
231 get_source(this), get_destination(this), spi
, seq
);
234 DBG3(DBG_ESP
, "ESP decryption:\n SPI %.8x [seq %u]\n IV %B\n "
235 "encrypted %B\n ICV %B", spi
, seq
, &iv
, &ciphertext
, &icv
);
237 if (!signer
->get_signature(signer
, chunk_create(data
.ptr
, 8), NULL
) ||
238 !signer
->get_signature(signer
, iv
, NULL
) ||
239 !signer
->verify_signature(signer
, ciphertext
, icv
))
241 DBG1(DBG_ESP
, "ICV verification failed!");
244 esp_context
->set_authenticated_seqno(esp_context
, seq
);
246 if (!crypter
->decrypt(crypter
, ciphertext
, iv
, &plaintext
))
248 DBG1(DBG_ESP
, "ESP decryption failed");
252 if (!remove_padding(this, plaintext
))
260 * Generate the padding as specified in RFC4303
262 static void generate_padding(chunk_t padding
)
266 for (i
= 0; i
< padding
.len
; ++i
)
268 padding
.ptr
[i
] = (u_int8_t
)(i
+ 1);
272 METHOD(esp_packet_t
, encrypt
, status_t
,
273 private_esp_packet_t
*this, esp_context_t
*esp_context
, u_int32_t spi
)
275 chunk_t iv
, icv
, padding
, payload
, ciphertext
, auth_data
;
276 bio_writer_t
*writer
;
277 u_int32_t next_seqno
;
278 size_t blocksize
, plainlen
;
283 this->packet
->set_data(this->packet
, chunk_empty
);
285 if (!esp_context
->next_seqno(esp_context
, &next_seqno
))
287 DBG1(DBG_ESP
, "ESP encapsulation failed: sequence numbers cycled");
291 rng
= lib
->crypto
->create_rng(lib
->crypto
, RNG_WEAK
);
294 DBG1(DBG_ESP
, "ESP encryption failed: could not find RNG");
297 crypter
= esp_context
->get_crypter(esp_context
);
298 signer
= esp_context
->get_signer(esp_context
);
300 blocksize
= crypter
->get_block_size(crypter
);
301 iv
.len
= crypter
->get_iv_size(crypter
);
302 icv
.len
= signer
->get_block_size(signer
);
304 /* plaintext = payload, padding, pad_length, next_header */
305 payload
= this->payload ?
this->payload
->get_encoding(this->payload
)
307 plainlen
= payload
.len
+ 2;
308 padding
.len
= blocksize
- (plainlen
% blocksize
);
309 plainlen
+= padding
.len
;
311 /* len = spi, seq, IV, plaintext, ICV */
312 writer
= bio_writer_create(2 * sizeof(u_int32_t
) + iv
.len
+ plainlen
+
314 writer
->write_uint32(writer
, ntohl(spi
));
315 writer
->write_uint32(writer
, next_seqno
);
317 iv
= writer
->skip(writer
, iv
.len
);
318 if (!rng
->get_bytes(rng
, iv
.len
, iv
.ptr
))
320 DBG1(DBG_ESP
, "ESP encryption failed: could not generate IV");
321 writer
->destroy(writer
);
327 /* plain-/ciphertext will start here */
328 ciphertext
= writer
->get_buf(writer
);
329 ciphertext
.ptr
+= ciphertext
.len
;
330 ciphertext
.len
= plainlen
;
332 writer
->write_data(writer
, payload
);
334 padding
= writer
->skip(writer
, padding
.len
);
335 generate_padding(padding
);
337 writer
->write_uint8(writer
, padding
.len
);
338 writer
->write_uint8(writer
, this->next_header
);
340 DBG3(DBG_ESP
, "ESP before encryption:\n payload = %B\n padding = %B\n "
341 "padding length = %hhu, next header = %hhu", &payload
, &padding
,
342 (u_int8_t
)padding
.len
, this->next_header
);
344 /* encrypt the content inline */
345 if (!crypter
->encrypt(crypter
, ciphertext
, iv
, NULL
))
347 DBG1(DBG_ESP
, "ESP encryption failed");
348 writer
->destroy(writer
);
352 /* calculate signature */
353 auth_data
= writer
->get_buf(writer
);
354 icv
= writer
->skip(writer
, icv
.len
);
355 if (!signer
->get_signature(signer
, auth_data
, icv
.ptr
))
357 DBG1(DBG_ESP
, "ESP encryption failed: signature generation failed");
358 writer
->destroy(writer
);
362 DBG3(DBG_ESP
, "ESP packet:\n SPI %.8x [seq %u]\n IV %B\n "
363 "encrypted %B\n ICV %B", ntohl(spi
), next_seqno
, &iv
,
366 this->packet
->set_data(this->packet
, writer
->extract_buf(writer
));
367 writer
->destroy(writer
);
371 METHOD(esp_packet_t
, get_next_header
, u_int8_t
,
372 private_esp_packet_t
*this)
374 return this->next_header
;
377 METHOD(esp_packet_t
, get_payload
, ip_packet_t
*,
378 private_esp_packet_t
*this)
380 return this->payload
;
383 METHOD(esp_packet_t
, extract_payload
, ip_packet_t
*,
384 private_esp_packet_t
*this)
386 ip_packet_t
*payload
;
388 payload
= this->payload
;
389 this->payload
= NULL
;
393 METHOD2(esp_packet_t
, packet_t
, destroy
, void,
394 private_esp_packet_t
*this)
396 DESTROY_IF(this->payload
);
397 this->packet
->destroy(this->packet
);
401 static private_esp_packet_t
*esp_packet_create_internal(packet_t
*packet
)
403 private_esp_packet_t
*this;
408 .set_source
= _set_source
,
409 .get_source
= _get_source
,
410 .set_destination
= _set_destination
,
411 .get_destination
= _get_destination
,
412 .get_data
= _get_data
,
413 .set_data
= _set_data
,
414 .skip_bytes
= _skip_bytes
,
418 .get_source
= _get_source
,
419 .get_destination
= _get_destination
,
420 .get_next_header
= _get_next_header
,
421 .parse_header
= _parse_header
,
424 .get_payload
= _get_payload
,
425 .extract_payload
= _extract_payload
,
429 .next_header
= IPPROTO_NONE
,
435 * Described in header.
437 esp_packet_t
*esp_packet_create_from_packet(packet_t
*packet
)
439 private_esp_packet_t
*this;
441 this = esp_packet_create_internal(packet
);
443 return &this->public;
447 * Described in header.
449 esp_packet_t
*esp_packet_create_from_payload(host_t
*src
, host_t
*dst
,
450 ip_packet_t
*payload
)
452 private_esp_packet_t
*this;
455 packet
= packet_create_from_data(src
, dst
, chunk_empty
);
456 this = esp_packet_create_internal(packet
);
457 this->payload
= payload
;
460 this->next_header
= payload
->get_version(payload
) == 4 ? IPPROTO_IPIP
465 this->next_header
= IPPROTO_NONE
;
467 return &this->public;