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