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