]> The Tcpdump Group git mirrors - tcpdump/blob - print-esp.c
Cleanups.
[tcpdump] / print-esp.c
1 /* $NetBSD: print-ah.c,v 1.4 1996/05/20 00:41:16 fvdl Exp $ */
2
3 /*
4 * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994
5 * The Regents of the University of California. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that: (1) source code distributions
9 * retain the above copyright notice and this paragraph in its entirety, (2)
10 * distributions including binary code include the above copyright notice and
11 * this paragraph in its entirety in the documentation or other materials
12 * provided with the distribution, and (3) all advertising materials mentioning
13 * features or use of this software display the following acknowledgement:
14 * ``This product includes software developed by the University of California,
15 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
16 * the University nor the names of its contributors may be used to endorse
17 * or promote products derived from this software without specific prior
18 * written permission.
19 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
20 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
21 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
22 */
23
24 /* \summary: IPSEC Encapsulating Security Payload (ESP) printer */
25
26 #ifdef HAVE_CONFIG_H
27 #include "config.h"
28 #endif
29
30 #include <netdissect-stdinc.h>
31
32 #include <string.h>
33 #include <stdlib.h>
34
35 /* Any code in this file that depends on HAVE_LIBCRYPTO depends on
36 * HAVE_OPENSSL_EVP_H too. Undefining the former when the latter isn't defined
37 * is the simplest way of handling the dependency.
38 */
39 #ifdef HAVE_LIBCRYPTO
40 #ifdef HAVE_OPENSSL_EVP_H
41 #include <openssl/evp.h>
42 #else
43 #undef HAVE_LIBCRYPTO
44 #endif
45 #endif
46
47 #include "netdissect.h"
48 #include "strtoaddr.h"
49 #include "extract.h"
50
51 #include "ascii_strcasecmp.h"
52
53 #include "ip.h"
54 #include "ip6.h"
55
56 /*
57 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
58 * All rights reserved.
59 *
60 * Redistribution and use in source and binary forms, with or without
61 * modification, are permitted provided that the following conditions
62 * are met:
63 * 1. Redistributions of source code must retain the above copyright
64 * notice, this list of conditions and the following disclaimer.
65 * 2. Redistributions in binary form must reproduce the above copyright
66 * notice, this list of conditions and the following disclaimer in the
67 * documentation and/or other materials provided with the distribution.
68 * 3. Neither the name of the project nor the names of its contributors
69 * may be used to endorse or promote products derived from this software
70 * without specific prior written permission.
71 *
72 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
73 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
74 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
75 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
76 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
77 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
78 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
79 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
80 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
81 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
82 * SUCH DAMAGE.
83 */
84
85 /*
86 * RFC1827/2406 Encapsulated Security Payload.
87 */
88
89 struct newesp {
90 uint32_t esp_spi; /* ESP */
91 uint32_t esp_seq; /* Sequence number */
92 /*variable size*/ /* (IV and) Payload data */
93 /*variable size*/ /* padding */
94 /*8bit*/ /* pad size */
95 /*8bit*/ /* next header */
96 /*8bit*/ /* next header */
97 /*variable size, 32bit bound*/ /* Authentication data */
98 };
99
100 #ifdef HAVE_LIBCRYPTO
101 union inaddr_u {
102 struct in_addr in4;
103 struct in6_addr in6;
104 };
105 struct sa_list {
106 struct sa_list *next;
107 u_int daddr_version;
108 union inaddr_u daddr;
109 uint32_t spi; /* if == 0, then IKEv2 */
110 int initiator;
111 u_char spii[8]; /* for IKEv2 */
112 u_char spir[8];
113 const EVP_CIPHER *evp;
114 int ivlen;
115 int authlen;
116 u_char authsecret[256];
117 int authsecret_len;
118 u_char secret[256]; /* is that big enough for all secrets? */
119 int secretlen;
120 };
121
122 #ifndef HAVE_EVP_CIPHER_CTX_NEW
123 /*
124 * Allocate an EVP_CIPHER_CTX.
125 * Used if we have an older version of OpenSSL that doesn't provide
126 * routines to allocate and free them.
127 */
128 static EVP_CIPHER_CTX *
129 EVP_CIPHER_CTX_new(void)
130 {
131 EVP_CIPHER_CTX *ctx;
132
133 ctx = malloc(sizeof(*ctx));
134 if (ctx == NULL)
135 return (NULL);
136 memset(ctx, 0, sizeof(*ctx));
137 return (ctx);
138 }
139
140 static void
141 EVP_CIPHER_CTX_free(EVP_CIPHER_CTX *ctx)
142 {
143 EVP_CIPHER_CTX_cleanup(ctx);
144 free(ctx);
145 }
146 #endif
147
148 /*
149 * this will adjust ndo_packetp and ndo_snapend to new buffer!
150 */
151 USES_APPLE_DEPRECATED_API
152 int esp_print_decrypt_buffer_by_ikev2(netdissect_options *ndo,
153 int initiator,
154 u_char spii[8], u_char spir[8],
155 const u_char *buf, const u_char *end)
156 {
157 struct sa_list *sa;
158 const u_char *iv;
159 unsigned int len;
160 EVP_CIPHER_CTX *ctx;
161 unsigned int block_size, output_buffer_size;
162 u_char *output_buffer;
163
164 /* initiator arg is any non-zero value */
165 if(initiator) initiator=1;
166
167 /* see if we can find the SA, and if so, decode it */
168 for (sa = ndo->ndo_sa_list_head; sa != NULL; sa = sa->next) {
169 if (sa->spi == 0
170 && initiator == sa->initiator
171 && memcmp(spii, sa->spii, 8) == 0
172 && memcmp(spir, sa->spir, 8) == 0)
173 break;
174 }
175
176 if(sa == NULL) return 0;
177 if(sa->evp == NULL) return 0;
178
179 /*
180 * remove authenticator, and see if we still have something to
181 * work with
182 */
183 end = end - sa->authlen;
184 iv = buf;
185 buf = buf + sa->ivlen;
186 len = end-buf;
187
188 if(end <= buf) return 0;
189
190 ctx = EVP_CIPHER_CTX_new();
191 if (ctx == NULL)
192 return 0;
193 /*
194 * Allocate a buffer for the decrypted data.
195 * The output buffer must be separate from the input buffer, and
196 * its size must be a multiple of the cipher block size.
197 */
198 block_size = (unsigned int)EVP_CIPHER_CTX_block_size(ctx);
199 output_buffer_size = len + (block_size - len % block_size);
200 output_buffer = (u_char *)malloc(output_buffer_size);
201 if (output_buffer == NULL) {
202 (*ndo->ndo_warning)(ndo, "can't allocate memory for decryption buffer");
203 return 0;
204 }
205 if (EVP_CipherInit(ctx, sa->evp, sa->secret, NULL, 0) < 0)
206 (*ndo->ndo_warning)(ndo, "espkey init failed");
207 EVP_CipherInit(ctx, NULL, NULL, iv, 0);
208 EVP_Cipher(ctx, output_buffer, buf, len);
209 EVP_CIPHER_CTX_free(ctx);
210
211 /*
212 * XXX - of course this is wrong, because buf is a const buffer,
213 * but changing this would require a more complicated fix.
214 */
215 memcpy(buf, output_buffer, len);
216 free(output_buffer);
217
218 ndo->ndo_packetp = buf;
219 ndo->ndo_snapend = end;
220
221 return 1;
222 }
223 USES_APPLE_RST
224
225 static void esp_print_addsa(netdissect_options *ndo,
226 struct sa_list *sa, int sa_def)
227 {
228 /* copy the "sa" */
229
230 struct sa_list *nsa;
231
232 nsa = (struct sa_list *)malloc(sizeof(struct sa_list));
233 if (nsa == NULL)
234 (*ndo->ndo_error)(ndo, "ran out of memory to allocate sa structure");
235
236 *nsa = *sa;
237
238 if (sa_def)
239 ndo->ndo_sa_default = nsa;
240
241 nsa->next = ndo->ndo_sa_list_head;
242 ndo->ndo_sa_list_head = nsa;
243 }
244
245
246 static u_int hexdigit(netdissect_options *ndo, char hex)
247 {
248 if (hex >= '0' && hex <= '9')
249 return (hex - '0');
250 else if (hex >= 'A' && hex <= 'F')
251 return (hex - 'A' + 10);
252 else if (hex >= 'a' && hex <= 'f')
253 return (hex - 'a' + 10);
254 else {
255 (*ndo->ndo_error)(ndo, "invalid hex digit %c in espsecret\n", hex);
256 return 0;
257 }
258 }
259
260 static u_int hex2byte(netdissect_options *ndo, char *hexstring)
261 {
262 u_int byte;
263
264 byte = (hexdigit(ndo, hexstring[0]) << 4) + hexdigit(ndo, hexstring[1]);
265 return byte;
266 }
267
268 /*
269 * returns size of binary, 0 on failure.
270 */
271 static
272 int espprint_decode_hex(netdissect_options *ndo,
273 u_char *binbuf, unsigned int binbuf_len,
274 char *hex)
275 {
276 unsigned int len;
277 int i;
278
279 len = strlen(hex) / 2;
280
281 if (len > binbuf_len) {
282 (*ndo->ndo_warning)(ndo, "secret is too big: %d\n", len);
283 return 0;
284 }
285
286 i = 0;
287 while (hex[0] != '\0' && hex[1]!='\0') {
288 binbuf[i] = hex2byte(ndo, hex);
289 hex += 2;
290 i++;
291 }
292
293 return i;
294 }
295
296 /*
297 * decode the form: SPINUM@IP <tab> ALGONAME:0xsecret
298 */
299
300 USES_APPLE_DEPRECATED_API
301 static int
302 espprint_decode_encalgo(netdissect_options *ndo,
303 char *decode, struct sa_list *sa)
304 {
305 size_t i;
306 const EVP_CIPHER *evp;
307 int authlen = 0;
308 char *colon, *p;
309
310 colon = strchr(decode, ':');
311 if (colon == NULL) {
312 (*ndo->ndo_warning)(ndo, "failed to decode espsecret: %s\n", decode);
313 return 0;
314 }
315 *colon = '\0';
316
317 if (strlen(decode) > strlen("-hmac96") &&
318 !strcmp(decode + strlen(decode) - strlen("-hmac96"),
319 "-hmac96")) {
320 p = strstr(decode, "-hmac96");
321 *p = '\0';
322 authlen = 12;
323 }
324 if (strlen(decode) > strlen("-cbc") &&
325 !strcmp(decode + strlen(decode) - strlen("-cbc"), "-cbc")) {
326 p = strstr(decode, "-cbc");
327 *p = '\0';
328 }
329 evp = EVP_get_cipherbyname(decode);
330
331 if (!evp) {
332 (*ndo->ndo_warning)(ndo, "failed to find cipher algo %s\n", decode);
333 sa->evp = NULL;
334 sa->authlen = 0;
335 sa->ivlen = 0;
336 return 0;
337 }
338
339 sa->evp = evp;
340 sa->authlen = authlen;
341 sa->ivlen = EVP_CIPHER_iv_length(evp);
342
343 colon++;
344 if (colon[0] == '0' && colon[1] == 'x') {
345 /* decode some hex! */
346
347 colon += 2;
348 sa->secretlen = espprint_decode_hex(ndo, sa->secret, sizeof(sa->secret), colon);
349 if(sa->secretlen == 0) return 0;
350 } else {
351 i = strlen(colon);
352
353 if (i < sizeof(sa->secret)) {
354 memcpy(sa->secret, colon, i);
355 sa->secretlen = i;
356 } else {
357 memcpy(sa->secret, colon, sizeof(sa->secret));
358 sa->secretlen = sizeof(sa->secret);
359 }
360 }
361
362 return 1;
363 }
364 USES_APPLE_RST
365
366 /*
367 * for the moment, ignore the auth algorith, just hard code the authenticator
368 * length. Need to research how openssl looks up HMAC stuff.
369 */
370 static int
371 espprint_decode_authalgo(netdissect_options *ndo,
372 char *decode, struct sa_list *sa)
373 {
374 char *colon;
375
376 colon = strchr(decode, ':');
377 if (colon == NULL) {
378 (*ndo->ndo_warning)(ndo, "failed to decode espsecret: %s\n", decode);
379 return 0;
380 }
381 *colon = '\0';
382
383 if(ascii_strcasecmp(colon,"sha1") == 0 ||
384 ascii_strcasecmp(colon,"md5") == 0) {
385 sa->authlen = 12;
386 }
387 return 1;
388 }
389
390 static void esp_print_decode_ikeline(netdissect_options *ndo, char *line,
391 const char *file, int lineno)
392 {
393 /* it's an IKEv2 secret, store it instead */
394 struct sa_list sa1;
395
396 char *init;
397 char *icookie, *rcookie;
398 int ilen, rlen;
399 char *authkey;
400 char *enckey;
401
402 init = strsep(&line, " \t");
403 icookie = strsep(&line, " \t");
404 rcookie = strsep(&line, " \t");
405 authkey = strsep(&line, " \t");
406 enckey = strsep(&line, " \t");
407
408 /* if any fields are missing */
409 if(!init || !icookie || !rcookie || !authkey || !enckey) {
410 (*ndo->ndo_warning)(ndo, "print_esp: failed to find all fields for ikev2 at %s:%u",
411 file, lineno);
412
413 return;
414 }
415
416 ilen = strlen(icookie);
417 rlen = strlen(rcookie);
418
419 if((init[0]!='I' && init[0]!='R')
420 || icookie[0]!='0' || icookie[1]!='x'
421 || rcookie[0]!='0' || rcookie[1]!='x'
422 || ilen!=18
423 || rlen!=18) {
424 (*ndo->ndo_warning)(ndo, "print_esp: line %s:%u improperly formatted.",
425 file, lineno);
426
427 (*ndo->ndo_warning)(ndo, "init=%s icookie=%s(%u) rcookie=%s(%u)",
428 init, icookie, ilen, rcookie, rlen);
429
430 return;
431 }
432
433 sa1.spi = 0;
434 sa1.initiator = (init[0] == 'I');
435 if(espprint_decode_hex(ndo, sa1.spii, sizeof(sa1.spii), icookie+2)!=8)
436 return;
437
438 if(espprint_decode_hex(ndo, sa1.spir, sizeof(sa1.spir), rcookie+2)!=8)
439 return;
440
441 if(!espprint_decode_encalgo(ndo, enckey, &sa1)) return;
442
443 if(!espprint_decode_authalgo(ndo, authkey, &sa1)) return;
444
445 esp_print_addsa(ndo, &sa1, FALSE);
446 }
447
448 /*
449 *
450 * special form: file /name
451 * causes us to go read from this file instead.
452 *
453 */
454 static void esp_print_decode_onesecret(netdissect_options *ndo, char *line,
455 const char *file, int lineno)
456 {
457 struct sa_list sa1;
458 int sa_def;
459
460 char *spikey;
461 char *decode;
462
463 spikey = strsep(&line, " \t");
464 sa_def = 0;
465 memset(&sa1, 0, sizeof(struct sa_list));
466
467 /* if there is only one token, then it is an algo:key token */
468 if (line == NULL) {
469 decode = spikey;
470 spikey = NULL;
471 /* sa1.daddr.version = 0; */
472 /* memset(&sa1.daddr, 0, sizeof(sa1.daddr)); */
473 /* sa1.spi = 0; */
474 sa_def = 1;
475 } else
476 decode = line;
477
478 if (spikey && ascii_strcasecmp(spikey, "file") == 0) {
479 /* open file and read it */
480 FILE *secretfile;
481 char fileline[1024];
482 int subfile_lineno=0;
483 char *nl;
484 char *filename = line;
485
486 secretfile = fopen(filename, FOPEN_READ_TXT);
487 if (secretfile == NULL) {
488 (*ndo->ndo_error)(ndo, "print_esp: can't open %s: %s\n",
489 filename, strerror(errno));
490 return;
491 }
492
493 while (fgets(fileline, sizeof(fileline)-1, secretfile) != NULL) {
494 subfile_lineno++;
495 /* remove newline from the line */
496 nl = strchr(fileline, '\n');
497 if (nl)
498 *nl = '\0';
499 if (fileline[0] == '#') continue;
500 if (fileline[0] == '\0') continue;
501
502 esp_print_decode_onesecret(ndo, fileline, filename, subfile_lineno);
503 }
504 fclose(secretfile);
505
506 return;
507 }
508
509 if (spikey && ascii_strcasecmp(spikey, "ikev2") == 0) {
510 esp_print_decode_ikeline(ndo, line, file, lineno);
511 return;
512 }
513
514 if (spikey) {
515
516 char *spistr, *foo;
517 uint32_t spino;
518
519 spistr = strsep(&spikey, "@");
520
521 spino = strtoul(spistr, &foo, 0);
522 if (spistr == foo || !spikey) {
523 (*ndo->ndo_warning)(ndo, "print_esp: failed to decode spi# %s\n", foo);
524 return;
525 }
526
527 sa1.spi = spino;
528
529 if (strtoaddr6(spikey, &sa1.daddr.in6) == 1) {
530 sa1.daddr_version = 6;
531 } else if (strtoaddr(spikey, &sa1.daddr.in4) == 1) {
532 sa1.daddr_version = 4;
533 } else {
534 (*ndo->ndo_warning)(ndo, "print_esp: can not decode IP# %s\n", spikey);
535 return;
536 }
537 }
538
539 if (decode) {
540 /* skip any blank spaces */
541 while (isspace((unsigned char)*decode))
542 decode++;
543
544 if(!espprint_decode_encalgo(ndo, decode, &sa1)) {
545 return;
546 }
547 }
548
549 esp_print_addsa(ndo, &sa1, sa_def);
550 }
551
552 USES_APPLE_DEPRECATED_API
553 static void esp_init(netdissect_options *ndo _U_)
554 {
555 /*
556 * 0.9.6 doesn't appear to define OPENSSL_API_COMPAT, so
557 * we check whether it's undefined or it's less than the
558 * value for 1.1.0.
559 */
560 #if !defined(OPENSSL_API_COMPAT) || OPENSSL_API_COMPAT < 0x10100000L
561 OpenSSL_add_all_algorithms();
562 #endif
563 EVP_add_cipher_alias(SN_des_ede3_cbc, "3des");
564 }
565 USES_APPLE_RST
566
567 void esp_print_decodesecret(netdissect_options *ndo)
568 {
569 char *line;
570 char *p;
571 static int initialized = 0;
572
573 if (!initialized) {
574 esp_init(ndo);
575 initialized = 1;
576 }
577
578 p = ndo->ndo_espsecret;
579
580 while (p && p[0] != '\0') {
581 /* pick out the first line or first thing until a comma */
582 if ((line = strsep(&p, "\n,")) == NULL) {
583 line = p;
584 p = NULL;
585 }
586
587 esp_print_decode_onesecret(ndo, line, "cmdline", 0);
588 }
589
590 ndo->ndo_espsecret = NULL;
591 }
592
593 #endif
594
595 #ifdef HAVE_LIBCRYPTO
596 USES_APPLE_DEPRECATED_API
597 #endif
598 int
599 esp_print(netdissect_options *ndo,
600 const u_char *bp, const int length, const u_char *bp2
601 #ifndef HAVE_LIBCRYPTO
602 _U_
603 #endif
604 ,
605 int *nhdr
606 #ifndef HAVE_LIBCRYPTO
607 _U_
608 #endif
609 ,
610 int *padlen
611 #ifndef HAVE_LIBCRYPTO
612 _U_
613 #endif
614 )
615 {
616 register const struct newesp *esp;
617 register const u_char *ep;
618 #ifdef HAVE_LIBCRYPTO
619 const struct ip *ip;
620 struct sa_list *sa = NULL;
621 const struct ip6_hdr *ip6 = NULL;
622 int advance;
623 int len;
624 u_char *secret;
625 int ivlen = 0;
626 const u_char *ivoff;
627 const u_char *p;
628 EVP_CIPHER_CTX *ctx;
629 unsigned int block_size, output_buffer_size;
630 u_char *output_buffer;
631 #endif
632
633 esp = (const struct newesp *)bp;
634
635 #ifdef HAVE_LIBCRYPTO
636 secret = NULL;
637 advance = 0;
638 #endif
639
640 #if 0
641 /* keep secret out of a register */
642 p = (u_char *)&secret;
643 #endif
644
645 /* 'ep' points to the end of available data. */
646 ep = ndo->ndo_snapend;
647
648 if ((const u_char *)(esp + 1) >= ep) {
649 ND_PRINT((ndo, "[|ESP]"));
650 goto fail;
651 }
652 ND_PRINT((ndo, "ESP(spi=0x%08x", EXTRACT_32BITS(&esp->esp_spi)));
653 ND_PRINT((ndo, ",seq=0x%x)", EXTRACT_32BITS(&esp->esp_seq)));
654 ND_PRINT((ndo, ", length %u", length));
655
656 #ifndef HAVE_LIBCRYPTO
657 goto fail;
658 #else
659 /* initiailize SAs */
660 if (ndo->ndo_sa_list_head == NULL) {
661 if (!ndo->ndo_espsecret)
662 goto fail;
663
664 esp_print_decodesecret(ndo);
665 }
666
667 if (ndo->ndo_sa_list_head == NULL)
668 goto fail;
669
670 ip = (const struct ip *)bp2;
671 switch (IP_V(ip)) {
672 case 6:
673 ip6 = (const struct ip6_hdr *)bp2;
674 /* we do not attempt to decrypt jumbograms */
675 if (!EXTRACT_16BITS(&ip6->ip6_plen))
676 goto fail;
677 /* if we can't get nexthdr, we do not need to decrypt it */
678 len = sizeof(struct ip6_hdr) + EXTRACT_16BITS(&ip6->ip6_plen);
679
680 /* see if we can find the SA, and if so, decode it */
681 for (sa = ndo->ndo_sa_list_head; sa != NULL; sa = sa->next) {
682 if (sa->spi == EXTRACT_32BITS(&esp->esp_spi) &&
683 sa->daddr_version == 6 &&
684 UNALIGNED_MEMCMP(&sa->daddr.in6, &ip6->ip6_dst,
685 sizeof(struct in6_addr)) == 0) {
686 break;
687 }
688 }
689 break;
690 case 4:
691 /* nexthdr & padding are in the last fragment */
692 if (EXTRACT_16BITS(&ip->ip_off) & IP_MF)
693 goto fail;
694 len = EXTRACT_16BITS(&ip->ip_len);
695
696 /* see if we can find the SA, and if so, decode it */
697 for (sa = ndo->ndo_sa_list_head; sa != NULL; sa = sa->next) {
698 if (sa->spi == EXTRACT_32BITS(&esp->esp_spi) &&
699 sa->daddr_version == 4 &&
700 UNALIGNED_MEMCMP(&sa->daddr.in4, &ip->ip_dst,
701 sizeof(struct in_addr)) == 0) {
702 break;
703 }
704 }
705 break;
706 default:
707 goto fail;
708 }
709
710 /* if we didn't find the specific one, then look for
711 * an unspecified one.
712 */
713 if (sa == NULL)
714 sa = ndo->ndo_sa_default;
715
716 /* if not found fail */
717 if (sa == NULL)
718 goto fail;
719
720 /* if we can't get nexthdr, we do not need to decrypt it */
721 if (ep - bp2 < len)
722 goto fail;
723 if (ep - bp2 > len) {
724 /* FCS included at end of frame (NetBSD 1.6 or later) */
725 ep = bp2 + len;
726 }
727
728 /* pointer to the IV, if there is one */
729 ivoff = (const u_char *)(esp + 1) + 0;
730 /* length of the IV, if there is one; 0, if there isn't */
731 ivlen = sa->ivlen;
732 secret = sa->secret;
733 ep = ep - sa->authlen;
734
735 if (sa->evp) {
736 ctx = EVP_CIPHER_CTX_new();
737 if (ctx != NULL) {
738 /*
739 * Allocate a buffer for the decrypted data.
740 * The output buffer must be separate from the
741 * input buffer, and its size must be a multiple
742 * of the cipher block size.
743 */
744 block_size = (unsigned int)EVP_CIPHER_CTX_block_size(ctx);
745 output_buffer_size = len + (block_size - len % block_size);
746 output_buffer = (u_char *)malloc(output_buffer_size);
747 if (output_buffer == NULL) {
748 (*ndo->ndo_warning)(ndo, "can't allocate memory for decryption buffer");
749 return -1;
750 }
751
752 if (EVP_CipherInit(ctx, sa->evp, secret, NULL, 0) < 0)
753 (*ndo->ndo_warning)(ndo, "espkey init failed");
754
755 p = ivoff;
756 EVP_CipherInit(ctx, NULL, NULL, p, 0);
757 len = ep - (p + ivlen);
758
759 EVP_Cipher(ctx, output_buffer, p + ivlen, len);
760 EVP_CIPHER_CTX_free(ctx);
761 /*
762 * XXX - of course this is wrong, because buf is a
763 * const buffer, but changing this would require a
764 * more complicated fix.
765 */
766 memcpy(p + ivlen, output_buffer, len);
767 free(output_buffer);
768 advance = ivoff - (const u_char *)esp + ivlen;
769 } else
770 advance = sizeof(struct newesp);
771 } else
772 advance = sizeof(struct newesp);
773
774 /* sanity check for pad length */
775 if (ep - bp < *(ep - 2))
776 goto fail;
777
778 if (padlen)
779 *padlen = *(ep - 2) + 2;
780
781 if (nhdr)
782 *nhdr = *(ep - 1);
783
784 ND_PRINT((ndo, ": "));
785 return advance;
786 #endif
787
788 fail:
789 return -1;
790 }
791 #ifdef HAVE_LIBCRYPTO
792 USES_APPLE_RST
793 #endif
794
795 /*
796 * Local Variables:
797 * c-style: whitesmith
798 * c-basic-offset: 8
799 * End:
800 */