Home | History | Annotate | Download | only in tcpdump
      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
    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 
    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 
    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 
    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
    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
    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
    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 
    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  */
    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
    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 
    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
    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