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