Annotation of embedaddon/strongswan/src/libipsec/esp_packet.c, revision 1.1.1.1
1.1 misho 1: /*
2: * Copyright (C) 2012-2013 Tobias Brunner
3: * Copyright (C) 2012 Giuliano Grassi
4: * Copyright (C) 2012 Ralf Sager
5: * HSR Hochschule fuer Technik Rapperswil
6: *
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>.
11: *
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
15: * for more details.
16: */
17:
18:
19: #include "esp_packet.h"
20:
21: #include <library.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>
27:
28: #ifndef WIN32
29: #include <netinet/in.h>
30: #endif
31:
32: typedef struct private_esp_packet_t private_esp_packet_t;
33:
34: /**
35: * Private additions to esp_packet_t.
36: */
37: struct private_esp_packet_t {
38:
39: /**
40: * Public members
41: */
42: esp_packet_t public;
43:
44: /**
45: * Raw ESP packet
46: */
47: packet_t *packet;
48:
49: /**
50: * Payload of this packet
51: */
52: ip_packet_t *payload;
53:
54: /**
55: * Next Header info (e.g. IPPROTO_IPIP)
56: */
57: uint8_t next_header;
58:
59: };
60:
61: /**
62: * Forward declaration for clone()
63: */
64: static private_esp_packet_t *esp_packet_create_internal(packet_t *packet);
65:
66: METHOD(packet_t, set_source, void,
67: private_esp_packet_t *this, host_t *src)
68: {
69: return this->packet->set_source(this->packet, src);
70: }
71:
72: METHOD2(esp_packet_t, packet_t, get_source, host_t*,
73: private_esp_packet_t *this)
74: {
75: return this->packet->get_source(this->packet);
76: }
77:
78: METHOD(packet_t, set_destination, void,
79: private_esp_packet_t *this, host_t *dst)
80: {
81: return this->packet->set_destination(this->packet, dst);
82: }
83:
84: METHOD2(esp_packet_t, packet_t, get_destination, host_t*,
85: private_esp_packet_t *this)
86: {
87: return this->packet->get_destination(this->packet);
88: }
89:
90: METHOD(packet_t, get_data, chunk_t,
91: private_esp_packet_t *this)
92: {
93: return this->packet->get_data(this->packet);
94: }
95:
96: METHOD(packet_t, set_data, void,
97: private_esp_packet_t *this, chunk_t data)
98: {
99: return this->packet->set_data(this->packet, data);
100: }
101:
102: METHOD(packet_t, get_dscp, uint8_t,
103: private_esp_packet_t *this)
104: {
105: return this->packet->get_dscp(this->packet);
106: }
107:
108: METHOD(packet_t, set_dscp, void,
109: private_esp_packet_t *this, uint8_t value)
110: {
111: this->packet->set_dscp(this->packet, value);
112: }
113:
114: METHOD(packet_t, skip_bytes, void,
115: private_esp_packet_t *this, size_t bytes)
116: {
117: return this->packet->skip_bytes(this->packet, bytes);
118: }
119:
120: METHOD(packet_t, clone_, packet_t*,
121: private_esp_packet_t *this)
122: {
123: private_esp_packet_t *pkt;
124:
125: pkt = esp_packet_create_internal(this->packet->clone(this->packet));
126: pkt->payload = this->payload ? this->payload->clone(this->payload) : NULL;
127: pkt->next_header = this->next_header;
128: return &pkt->public.packet;
129: }
130:
131: METHOD(esp_packet_t, parse_header, bool,
132: private_esp_packet_t *this, uint32_t *spi)
133: {
134: bio_reader_t *reader;
135: uint32_t seq;
136:
137: reader = bio_reader_create(this->packet->get_data(this->packet));
138: if (!reader->read_uint32(reader, spi) ||
139: !reader->read_uint32(reader, &seq))
140: {
141: DBG1(DBG_ESP, "failed to parse ESP header: invalid length");
142: reader->destroy(reader);
143: return FALSE;
144: }
145: reader->destroy(reader);
146:
147: DBG2(DBG_ESP, "parsed ESP header with SPI %.8x [seq %u]", *spi, seq);
148: *spi = htonl(*spi);
149: return TRUE;
150: }
151:
152: /**
153: * Check padding as specified in RFC 4303
154: */
155: static bool check_padding(chunk_t padding)
156: {
157: size_t i;
158:
159: for (i = 0; i < padding.len; ++i)
160: {
161: if (padding.ptr[i] != (uint8_t)(i + 1))
162: {
163: return FALSE;
164: }
165: }
166: return TRUE;
167: }
168:
169: /**
170: * Remove the padding from the payload and set the next header info
171: */
172: static bool remove_padding(private_esp_packet_t *this, chunk_t plaintext)
173: {
174: uint8_t next_header, pad_length;
175: chunk_t padding, payload;
176: bio_reader_t *reader;
177:
178: reader = bio_reader_create(plaintext);
179: if (!reader->read_uint8_end(reader, &next_header) ||
180: !reader->read_uint8_end(reader, &pad_length))
181: {
182: DBG1(DBG_ESP, "parsing ESP payload failed: invalid length");
183: goto failed;
184: }
185: if (!reader->read_data_end(reader, pad_length, &padding) ||
186: !check_padding(padding))
187: {
188: DBG1(DBG_ESP, "parsing ESP payload failed: invalid padding");
189: goto failed;
190: }
191: this->payload = ip_packet_create(reader->peek(reader));
192: reader->destroy(reader);
193: if (!this->payload)
194: {
195: DBG1(DBG_ESP, "parsing ESP payload failed: unsupported payload");
196: return FALSE;
197: }
198: this->next_header = next_header;
199: payload = this->payload->get_encoding(this->payload);
200:
201: DBG3(DBG_ESP, "ESP payload:\n payload %B\n padding %B\n "
202: "padding length = %hhu, next header = %hhu", &payload, &padding,
203: pad_length, this->next_header);
204: return TRUE;
205:
206: failed:
207: reader->destroy(reader);
208: chunk_free(&plaintext);
209: return FALSE;
210: }
211:
212: METHOD(esp_packet_t, decrypt, status_t,
213: private_esp_packet_t *this, esp_context_t *esp_context)
214: {
215: bio_reader_t *reader;
216: uint32_t spi, seq;
217: chunk_t data, iv, icv, aad, ciphertext, plaintext;
218: aead_t *aead;
219:
220: DESTROY_IF(this->payload);
221: this->payload = NULL;
222:
223: data = this->packet->get_data(this->packet);
224: aead = esp_context->get_aead(esp_context);
225:
226: reader = bio_reader_create(data);
227: if (!reader->read_uint32(reader, &spi) ||
228: !reader->read_uint32(reader, &seq) ||
229: !reader->read_data(reader, aead->get_iv_size(aead), &iv) ||
230: !reader->read_data_end(reader, aead->get_icv_size(aead), &icv) ||
231: reader->remaining(reader) % aead->get_block_size(aead))
232: {
233: DBG1(DBG_ESP, "ESP decryption failed: invalid length");
234: return PARSE_ERROR;
235: }
236: ciphertext = reader->peek(reader);
237: reader->destroy(reader);
238:
239: if (!esp_context->verify_seqno(esp_context, seq))
240: {
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);
244: return VERIFY_ERROR;
245: }
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);
248:
249: /* include ICV in ciphertext for decryption/verification */
250: ciphertext.len += icv.len;
251: /* aad = spi + seq */
252: aad = chunk_create(data.ptr, 8);
253:
254: if (!aead->decrypt(aead, ciphertext, aad, iv, &plaintext))
255: {
256: DBG1(DBG_ESP, "ESP decryption or ICV verification failed");
257: return FAILED;
258: }
259: esp_context->set_authenticated_seqno(esp_context, seq);
260:
261: if (!remove_padding(this, plaintext))
262: {
263: return PARSE_ERROR;
264: }
265: return SUCCESS;
266: }
267:
268: /**
269: * Generate the padding as specified in RFC4303
270: */
271: static void generate_padding(chunk_t padding)
272: {
273: size_t i;
274:
275: for (i = 0; i < padding.len; ++i)
276: {
277: padding.ptr[i] = (uint8_t)(i + 1);
278: }
279: }
280:
281: METHOD(esp_packet_t, encrypt, status_t,
282: private_esp_packet_t *this, esp_context_t *esp_context, uint32_t spi)
283: {
284: chunk_t iv, icv, aad, padding, payload, ciphertext;
285: bio_writer_t *writer;
286: uint32_t next_seqno;
287: size_t blocksize, plainlen;
288: aead_t *aead;
289: iv_gen_t *iv_gen;
290:
291: this->packet->set_data(this->packet, chunk_empty);
292:
293: if (!esp_context->next_seqno(esp_context, &next_seqno))
294: {
295: DBG1(DBG_ESP, "ESP encapsulation failed: sequence numbers cycled");
296: return FAILED;
297: }
298:
299: aead = esp_context->get_aead(esp_context);
300: iv_gen = aead->get_iv_gen(aead);
301: if (!iv_gen)
302: {
303: DBG1(DBG_ESP, "ESP encryption failed: no IV generator");
304: return NOT_FOUND;
305: }
306:
307: blocksize = aead->get_block_size(aead);
308: iv.len = aead->get_iv_size(aead);
309: icv.len = aead->get_icv_size(aead);
310:
311: /* plaintext = payload, padding, pad_length, next_header */
312: payload = this->payload ? this->payload->get_encoding(this->payload)
313: : chunk_empty;
314: plainlen = payload.len + 2;
315: padding.len = pad_len(plainlen, blocksize);
316: /* ICV must be on a 4-byte boundary */
317: padding.len += pad_len(iv.len + plainlen + padding.len, 4);
318: plainlen += padding.len;
319:
320: /* len = spi, seq, IV, plaintext, ICV */
321: writer = bio_writer_create(2 * sizeof(uint32_t) + iv.len + plainlen +
322: icv.len);
323: writer->write_uint32(writer, ntohl(spi));
324: writer->write_uint32(writer, next_seqno);
325:
326: iv = writer->skip(writer, iv.len);
327: if (!iv_gen->get_iv(iv_gen, next_seqno, iv.len, iv.ptr))
328: {
329: DBG1(DBG_ESP, "ESP encryption failed: could not generate IV");
330: writer->destroy(writer);
331: return FAILED;
332: }
333:
334: /* plain-/ciphertext will start here */
335: ciphertext = writer->get_buf(writer);
336: ciphertext.ptr += ciphertext.len;
337: ciphertext.len = plainlen;
338:
339: writer->write_data(writer, payload);
340:
341: padding = writer->skip(writer, padding.len);
342: generate_padding(padding);
343:
344: writer->write_uint8(writer, padding.len);
345: writer->write_uint8(writer, this->next_header);
346:
347: /* aad = spi + seq */
348: aad = writer->get_buf(writer);
349: aad.len = 8;
350: icv = writer->skip(writer, icv.len);
351:
352: DBG3(DBG_ESP, "ESP before encryption:\n payload = %B\n padding = %B\n "
353: "padding length = %hhu, next header = %hhu", &payload, &padding,
354: (uint8_t)padding.len, this->next_header);
355:
356: /* encrypt/authenticate the content inline */
357: if (!aead->encrypt(aead, ciphertext, aad, iv, NULL))
358: {
359: DBG1(DBG_ESP, "ESP encryption or ICV generation failed");
360: writer->destroy(writer);
361: return FAILED;
362: }
363:
364: DBG3(DBG_ESP, "ESP packet:\n SPI %.8x [seq %u]\n IV %B\n "
365: "encrypted %B\n ICV %B", ntohl(spi), next_seqno, &iv,
366: &ciphertext, &icv);
367:
368: this->packet->set_data(this->packet, writer->extract_buf(writer));
369: writer->destroy(writer);
370: return SUCCESS;
371: }
372:
373: METHOD(esp_packet_t, get_next_header, uint8_t,
374: private_esp_packet_t *this)
375: {
376: return this->next_header;
377: }
378:
379: METHOD(esp_packet_t, get_payload, ip_packet_t*,
380: private_esp_packet_t *this)
381: {
382: return this->payload;
383: }
384:
385: METHOD(esp_packet_t, extract_payload, ip_packet_t*,
386: private_esp_packet_t *this)
387: {
388: ip_packet_t *payload;
389:
390: payload = this->payload;
391: this->payload = NULL;
392: return payload;
393: }
394:
395: METHOD2(esp_packet_t, packet_t, destroy, void,
396: private_esp_packet_t *this)
397: {
398: DESTROY_IF(this->payload);
399: this->packet->destroy(this->packet);
400: free(this);
401: }
402:
403: static private_esp_packet_t *esp_packet_create_internal(packet_t *packet)
404: {
405: private_esp_packet_t *this;
406:
407: INIT(this,
408: .public = {
409: .packet = {
410: .set_source = _set_source,
411: .get_source = _get_source,
412: .set_destination = _set_destination,
413: .get_destination = _get_destination,
414: .get_data = _get_data,
415: .set_data = _set_data,
416: .get_dscp = _get_dscp,
417: .set_dscp = _set_dscp,
418: .skip_bytes = _skip_bytes,
419: .clone = _clone_,
420: .destroy = _destroy,
421: },
422: .get_source = _get_source,
423: .get_destination = _get_destination,
424: .get_next_header = _get_next_header,
425: .parse_header = _parse_header,
426: .decrypt = _decrypt,
427: .encrypt = _encrypt,
428: .get_payload = _get_payload,
429: .extract_payload = _extract_payload,
430: .destroy = _destroy,
431: },
432: .packet = packet,
433: .next_header = IPPROTO_NONE,
434: );
435: return this;
436: }
437:
438: /**
439: * Described in header.
440: */
441: esp_packet_t *esp_packet_create_from_packet(packet_t *packet)
442: {
443: private_esp_packet_t *this;
444:
445: this = esp_packet_create_internal(packet);
446:
447: return &this->public;
448: }
449:
450: /**
451: * Described in header.
452: */
453: esp_packet_t *esp_packet_create_from_payload(host_t *src, host_t *dst,
454: ip_packet_t *payload)
455: {
456: private_esp_packet_t *this;
457: packet_t *packet;
458:
459: packet = packet_create_from_data(src, dst, chunk_empty);
460: this = esp_packet_create_internal(packet);
461: this->payload = payload;
462: if (payload)
463: {
464: this->next_header = payload->get_version(payload) == 4 ? IPPROTO_IPIP
465: : IPPROTO_IPV6;
466: }
467: else
468: {
469: this->next_header = IPPROTO_NONE;
470: }
471: return &this->public;
472: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>