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 #ifndef lint
     25 static const char rcsid[] _U_ =
     26     "@(#) $Header: /tcpdump/master/tcpdump/print-esp.c,v 1.58 2007-12-07 00:03:07 mcr Exp $ (LBL)";
     27 #endif
     28 
     29 #ifdef HAVE_CONFIG_H
     30 #include "config.h"
     31 #endif
     32 
     33 #include <string.h>
     34 
     35 #include <tcpdump-stdinc.h>
     36 
     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 <stdio.h>
     52 
     53 #include "ip.h"
     54 #include "esp.h"
     55 #ifdef INET6
     56 #include "ip6.h"
     57 #endif
     58 
     59 #include "netdissect.h"
     60 #include "addrtoname.h"
     61 #include "extract.h"
     62 
     63 #ifndef HAVE_SOCKADDR_STORAGE
     64 #ifdef INET6
     65 struct sockaddr_storage {
     66 	union {
     67 		struct sockaddr_in sin;
     68 		struct sockaddr_in6 sin6;
     69 	} un;
     70 };
     71 #else
     72 #define sockaddr_storage sockaddr
     73 #endif
     74 #endif /* HAVE_SOCKADDR_STORAGE */
     75 
     76 #ifdef HAVE_LIBCRYPTO
     77 struct sa_list {
     78 	struct sa_list	*next;
     79 	struct sockaddr_storage daddr;
     80 	u_int32_t	spi;          /* if == 0, then IKEv2 */
     81 	int             initiator;
     82 	u_char          spii[8];      /* for IKEv2 */
     83 	u_char          spir[8];
     84 	const EVP_CIPHER *evp;
     85 	int		ivlen;
     86 	int		authlen;
     87 	u_char          authsecret[256];
     88 	int             authsecret_len;
     89 	u_char		secret[256];  /* is that big enough for all secrets? */
     90 	int		secretlen;
     91 };
     92 
     93 /*
     94  * this will adjust ndo_packetp and ndo_snapend to new buffer!
     95  */
     96 USES_APPLE_DEPRECATED_API
     97 int esp_print_decrypt_buffer_by_ikev2(netdissect_options *ndo,
     98 				      int initiator,
     99 				      u_char spii[8], u_char spir[8],
    100 				      u_char *buf, u_char *end)
    101 {
    102 	struct sa_list *sa;
    103 	u_char *iv;
    104 	int len;
    105 	EVP_CIPHER_CTX ctx;
    106 
    107 	/* initiator arg is any non-zero value */
    108 	if(initiator) initiator=1;
    109 
    110 	/* see if we can find the SA, and if so, decode it */
    111 	for (sa = ndo->ndo_sa_list_head; sa != NULL; sa = sa->next) {
    112 		if (sa->spi == 0
    113 		    && initiator == sa->initiator
    114 		    && memcmp(spii, sa->spii, 8) == 0
    115 		    && memcmp(spir, sa->spir, 8) == 0)
    116 			break;
    117 	}
    118 
    119 	if(sa == NULL) return 0;
    120 	if(sa->evp == NULL) return 0;
    121 
    122 	/*
    123 	 * remove authenticator, and see if we still have something to
    124 	 * work with
    125 	 */
    126 	end = end - sa->authlen;
    127 	iv  = buf;
    128 	buf = buf + sa->ivlen;
    129 	len = end-buf;
    130 
    131 	if(end <= buf) return 0;
    132 
    133 	memset(&ctx, 0, sizeof(ctx));
    134 	if (EVP_CipherInit(&ctx, sa->evp, sa->secret, NULL, 0) < 0)
    135 		(*ndo->ndo_warning)(ndo, "espkey init failed");
    136 	EVP_CipherInit(&ctx, NULL, NULL, iv, 0);
    137 	EVP_Cipher(&ctx, buf, buf, len);
    138 	EVP_CIPHER_CTX_cleanup(&ctx);
    139 
    140 	ndo->ndo_packetp = buf;
    141 	ndo->ndo_snapend = end;
    142 
    143 	return 1;
    144 
    145 }
    146 USES_APPLE_RST
    147 
    148 static void esp_print_addsa(netdissect_options *ndo,
    149 			    struct sa_list *sa, int sa_def)
    150 {
    151 	/* copy the "sa" */
    152 
    153 	struct sa_list *nsa;
    154 
    155 	nsa = (struct sa_list *)malloc(sizeof(struct sa_list));
    156 	if (nsa == NULL)
    157 		(*ndo->ndo_error)(ndo, "ran out of memory to allocate sa structure");
    158 
    159 	*nsa = *sa;
    160 
    161 	if (sa_def)
    162 		ndo->ndo_sa_default = nsa;
    163 
    164 	nsa->next = ndo->ndo_sa_list_head;
    165 	ndo->ndo_sa_list_head = nsa;
    166 }
    167 
    168 
    169 static u_int hexdigit(netdissect_options *ndo, char hex)
    170 {
    171 	if (hex >= '0' && hex <= '9')
    172 		return (hex - '0');
    173 	else if (hex >= 'A' && hex <= 'F')
    174 		return (hex - 'A' + 10);
    175 	else if (hex >= 'a' && hex <= 'f')
    176 		return (hex - 'a' + 10);
    177 	else {
    178 		(*ndo->ndo_error)(ndo, "invalid hex digit %c in espsecret\n", hex);
    179 		return 0;
    180 	}
    181 }
    182 
    183 static u_int hex2byte(netdissect_options *ndo, char *hexstring)
    184 {
    185 	u_int byte;
    186 
    187 	byte = (hexdigit(ndo, hexstring[0]) << 4) + hexdigit(ndo, hexstring[1]);
    188 	return byte;
    189 }
    190 
    191 /*
    192  * returns size of binary, 0 on failure.
    193  */
    194 static
    195 int espprint_decode_hex(netdissect_options *ndo,
    196 			u_char *binbuf, unsigned int binbuf_len,
    197 			char *hex)
    198 {
    199 	unsigned int len;
    200 	int i;
    201 
    202 	len = strlen(hex) / 2;
    203 
    204 	if (len > binbuf_len) {
    205 		(*ndo->ndo_warning)(ndo, "secret is too big: %d\n", len);
    206 		return 0;
    207 	}
    208 
    209 	i = 0;
    210 	while (hex[0] != '\0' && hex[1]!='\0') {
    211 		binbuf[i] = hex2byte(ndo, hex);
    212 		hex += 2;
    213 		i++;
    214 	}
    215 
    216 	return i;
    217 }
    218 
    219 /*
    220  * decode the form:    SPINUM@IP <tab> ALGONAME:0xsecret
    221  */
    222 
    223 USES_APPLE_DEPRECATED_API
    224 static int
    225 espprint_decode_encalgo(netdissect_options *ndo,
    226 			char *decode, struct sa_list *sa)
    227 {
    228 	size_t i;
    229 	const EVP_CIPHER *evp;
    230 	int authlen = 0;
    231 	char *colon, *p;
    232 
    233 	colon = strchr(decode, ':');
    234 	if (colon == NULL) {
    235 		(*ndo->ndo_warning)(ndo, "failed to decode espsecret: %s\n", decode);
    236 		return 0;
    237 	}
    238 	*colon = '\0';
    239 
    240 	if (strlen(decode) > strlen("-hmac96") &&
    241 	    !strcmp(decode + strlen(decode) - strlen("-hmac96"),
    242 		    "-hmac96")) {
    243 		p = strstr(decode, "-hmac96");
    244 		*p = '\0';
    245 		authlen = 12;
    246 	}
    247 	if (strlen(decode) > strlen("-cbc") &&
    248 	    !strcmp(decode + strlen(decode) - strlen("-cbc"), "-cbc")) {
    249 		p = strstr(decode, "-cbc");
    250 		*p = '\0';
    251 	}
    252 	evp = EVP_get_cipherbyname(decode);
    253 
    254 	if (!evp) {
    255 		(*ndo->ndo_warning)(ndo, "failed to find cipher algo %s\n", decode);
    256 		sa->evp = NULL;
    257 		sa->authlen = 0;
    258 		sa->ivlen = 0;
    259 		return 0;
    260 	}
    261 
    262 	sa->evp = evp;
    263 	sa->authlen = authlen;
    264 	sa->ivlen = EVP_CIPHER_iv_length(evp);
    265 
    266 	colon++;
    267 	if (colon[0] == '0' && colon[1] == 'x') {
    268 		/* decode some hex! */
    269 
    270 		colon += 2;
    271 		sa->secretlen = espprint_decode_hex(ndo, sa->secret, sizeof(sa->secret), colon);
    272 		if(sa->secretlen == 0) return 0;
    273 	} else {
    274 		i = strlen(colon);
    275 
    276 		if (i < sizeof(sa->secret)) {
    277 			memcpy(sa->secret, colon, i);
    278 			sa->secretlen = i;
    279 		} else {
    280 			memcpy(sa->secret, colon, sizeof(sa->secret));
    281 			sa->secretlen = sizeof(sa->secret);
    282 		}
    283 	}
    284 
    285 	return 1;
    286 }
    287 USES_APPLE_RST
    288 
    289 /*
    290  * for the moment, ignore the auth algorith, just hard code the authenticator
    291  * length. Need to research how openssl looks up HMAC stuff.
    292  */
    293 static int
    294 espprint_decode_authalgo(netdissect_options *ndo,
    295 			 char *decode, struct sa_list *sa)
    296 {
    297 	char *colon;
    298 
    299 	colon = strchr(decode, ':');
    300 	if (colon == NULL) {
    301 		(*ndo->ndo_warning)(ndo, "failed to decode espsecret: %s\n", decode);
    302 		return 0;
    303 	}
    304 	*colon = '\0';
    305 
    306 	if(strcasecmp(colon,"sha1") == 0 ||
    307 	   strcasecmp(colon,"md5") == 0) {
    308 		sa->authlen = 12;
    309 	}
    310 	return 1;
    311 }
    312 
    313 static void esp_print_decode_ikeline(netdissect_options *ndo, char *line,
    314 				     const char *file, int lineno)
    315 {
    316 	/* it's an IKEv2 secret, store it instead */
    317 	struct sa_list sa1;
    318 
    319 	char *init;
    320 	char *icookie, *rcookie;
    321 	int   ilen, rlen;
    322 	char *authkey;
    323 	char *enckey;
    324 
    325 	init = strsep(&line, " \t");
    326 	icookie = strsep(&line, " \t");
    327 	rcookie = strsep(&line, " \t");
    328 	authkey = strsep(&line, " \t");
    329 	enckey  = strsep(&line, " \t");
    330 
    331 	/* if any fields are missing */
    332 	if(!init || !icookie || !rcookie || !authkey || !enckey) {
    333 		(*ndo->ndo_warning)(ndo, "print_esp: failed to find all fields for ikev2 at %s:%u",
    334 				    file, lineno);
    335 
    336 		return;
    337 	}
    338 
    339 	ilen = strlen(icookie);
    340 	rlen = strlen(rcookie);
    341 
    342 	if((init[0]!='I' && init[0]!='R')
    343 	   || icookie[0]!='0' || icookie[1]!='x'
    344 	   || rcookie[0]!='0' || rcookie[1]!='x'
    345 	   || ilen!=18
    346 	   || rlen!=18) {
    347 		(*ndo->ndo_warning)(ndo, "print_esp: line %s:%u improperly formatted.",
    348 				    file, lineno);
    349 
    350 		(*ndo->ndo_warning)(ndo, "init=%s icookie=%s(%u) rcookie=%s(%u)",
    351 				    init, icookie, ilen, rcookie, rlen);
    352 
    353 		return;
    354 	}
    355 
    356 	sa1.spi = 0;
    357 	sa1.initiator = (init[0] == 'I');
    358 	if(espprint_decode_hex(ndo, sa1.spii, sizeof(sa1.spii), icookie+2)!=8)
    359 		return;
    360 
    361 	if(espprint_decode_hex(ndo, sa1.spir, sizeof(sa1.spir), rcookie+2)!=8)
    362 		return;
    363 
    364 	if(!espprint_decode_encalgo(ndo, enckey, &sa1)) return;
    365 
    366 	if(!espprint_decode_authalgo(ndo, authkey, &sa1)) return;
    367 
    368 	esp_print_addsa(ndo, &sa1, FALSE);
    369 }
    370 
    371 /*
    372  *
    373  * special form: file /name
    374  * causes us to go read from this file instead.
    375  *
    376  */
    377 static void esp_print_decode_onesecret(netdissect_options *ndo, char *line,
    378 				       const char *file, int lineno)
    379 {
    380 	struct sa_list sa1;
    381 	int sa_def;
    382 
    383 	char *spikey;
    384 	char *decode;
    385 
    386 	spikey = strsep(&line, " \t");
    387 	sa_def = 0;
    388 	memset(&sa1, 0, sizeof(struct sa_list));
    389 
    390 	/* if there is only one token, then it is an algo:key token */
    391 	if (line == NULL) {
    392 		decode = spikey;
    393 		spikey = NULL;
    394 		/* memset(&sa1.daddr, 0, sizeof(sa1.daddr)); */
    395 		/* sa1.spi = 0; */
    396 		sa_def    = 1;
    397 	} else
    398 		decode = line;
    399 
    400 	if (spikey && strcasecmp(spikey, "file") == 0) {
    401 		/* open file and read it */
    402 		FILE *secretfile;
    403 		char  fileline[1024];
    404 		int   lineno=0;
    405 		char  *nl;
    406 		char *filename = line;
    407 
    408 		secretfile = fopen(filename, FOPEN_READ_TXT);
    409 		if (secretfile == NULL) {
    410 			perror(filename);
    411 			exit(3);
    412 		}
    413 
    414 		while (fgets(fileline, sizeof(fileline)-1, secretfile) != NULL) {
    415 			lineno++;
    416 			/* remove newline from the line */
    417 			nl = strchr(fileline, '\n');
    418 			if (nl)
    419 				*nl = '\0';
    420 			if (fileline[0] == '#') continue;
    421 			if (fileline[0] == '\0') continue;
    422 
    423 			esp_print_decode_onesecret(ndo, fileline, filename, lineno);
    424 		}
    425 		fclose(secretfile);
    426 
    427 		return;
    428 	}
    429 
    430 	if (spikey && strcasecmp(spikey, "ikev2") == 0) {
    431 		esp_print_decode_ikeline(ndo, line, file, lineno);
    432 		return;
    433 	}
    434 
    435 	if (spikey) {
    436 
    437 		char *spistr, *foo;
    438 		u_int32_t spino;
    439 		struct sockaddr_in *sin;
    440 #ifdef INET6
    441 		struct sockaddr_in6 *sin6;
    442 #endif
    443 
    444 		spistr = strsep(&spikey, "@");
    445 
    446 		spino = strtoul(spistr, &foo, 0);
    447 		if (spistr == foo || !spikey) {
    448 			(*ndo->ndo_warning)(ndo, "print_esp: failed to decode spi# %s\n", foo);
    449 			return;
    450 		}
    451 
    452 		sa1.spi = spino;
    453 
    454 		sin = (struct sockaddr_in *)&sa1.daddr;
    455 #ifdef INET6
    456 		sin6 = (struct sockaddr_in6 *)&sa1.daddr;
    457 		if (inet_pton(AF_INET6, spikey, &sin6->sin6_addr) == 1) {
    458 #ifdef HAVE_SOCKADDR_SA_LEN
    459 			sin6->sin6_len = sizeof(struct sockaddr_in6);
    460 #endif
    461 			sin6->sin6_family = AF_INET6;
    462 		} else
    463 #endif
    464 			if (inet_pton(AF_INET, spikey, &sin->sin_addr) == 1) {
    465 #ifdef HAVE_SOCKADDR_SA_LEN
    466 				sin->sin_len = sizeof(struct sockaddr_in);
    467 #endif
    468 				sin->sin_family = AF_INET;
    469 			} else {
    470 				(*ndo->ndo_warning)(ndo, "print_esp: can not decode IP# %s\n", spikey);
    471 				return;
    472 			}
    473 	}
    474 
    475 	if (decode) {
    476 		/* skip any blank spaces */
    477 		while (isspace((unsigned char)*decode))
    478 			decode++;
    479 
    480 		if(!espprint_decode_encalgo(ndo, decode, &sa1)) {
    481 			return;
    482 		}
    483 	}
    484 
    485 	esp_print_addsa(ndo, &sa1, sa_def);
    486 }
    487 
    488 USES_APPLE_DEPRECATED_API
    489 static void esp_init(netdissect_options *ndo _U_)
    490 {
    491 
    492 	OpenSSL_add_all_algorithms();
    493 	EVP_add_cipher_alias(SN_des_ede3_cbc, "3des");
    494 }
    495 USES_APPLE_RST
    496 
    497 void esp_print_decodesecret(netdissect_options *ndo)
    498 {
    499 	char *line;
    500 	char *p;
    501 	static int initialized = 0;
    502 
    503 	if (!initialized) {
    504 		esp_init(ndo);
    505 		initialized = 1;
    506 	}
    507 
    508 	p = ndo->ndo_espsecret;
    509 
    510 	while (p && p[0] != '\0') {
    511 		/* pick out the first line or first thing until a comma */
    512 		if ((line = strsep(&p, "\n,")) == NULL) {
    513 			line = p;
    514 			p = NULL;
    515 		}
    516 
    517 		esp_print_decode_onesecret(ndo, line, "cmdline", 0);
    518 	}
    519 
    520 	ndo->ndo_espsecret = NULL;
    521 }
    522 
    523 #endif
    524 
    525 #ifdef HAVE_LIBCRYPTO
    526 USES_APPLE_DEPRECATED_API
    527 #endif
    528 int
    529 esp_print(netdissect_options *ndo,
    530 	  const u_char *bp, const int length, const u_char *bp2
    531 #ifndef HAVE_LIBCRYPTO
    532 	_U_
    533 #endif
    534 	,
    535 	int *nhdr
    536 #ifndef HAVE_LIBCRYPTO
    537 	_U_
    538 #endif
    539 	,
    540 	int *padlen
    541 #ifndef HAVE_LIBCRYPTO
    542 	_U_
    543 #endif
    544 	)
    545 {
    546 	register const struct newesp *esp;
    547 	register const u_char *ep;
    548 #ifdef HAVE_LIBCRYPTO
    549 	struct ip *ip;
    550 	struct sa_list *sa = NULL;
    551 #ifdef INET6
    552 	struct ip6_hdr *ip6 = NULL;
    553 #endif
    554 	int advance;
    555 	int len;
    556 	u_char *secret;
    557 	int ivlen = 0;
    558 	u_char *ivoff;
    559 	u_char *p;
    560 	EVP_CIPHER_CTX ctx;
    561 #endif
    562 
    563 	esp = (struct newesp *)bp;
    564 
    565 #ifdef HAVE_LIBCRYPTO
    566 	secret = NULL;
    567 	advance = 0;
    568 #endif
    569 
    570 #if 0
    571 	/* keep secret out of a register */
    572 	p = (u_char *)&secret;
    573 #endif
    574 
    575 	/* 'ep' points to the end of available data. */
    576 	ep = ndo->ndo_snapend;
    577 
    578 	if ((u_char *)(esp + 1) >= ep) {
    579 		fputs("[|ESP]", stdout);
    580 		goto fail;
    581 	}
    582 	(*ndo->ndo_printf)(ndo, "ESP(spi=0x%08x", EXTRACT_32BITS(&esp->esp_spi));
    583 	(*ndo->ndo_printf)(ndo, ",seq=0x%x)", EXTRACT_32BITS(&esp->esp_seq));
    584         (*ndo->ndo_printf)(ndo, ", length %u", length);
    585 
    586 #ifndef HAVE_LIBCRYPTO
    587 	goto fail;
    588 #else
    589 	/* initiailize SAs */
    590 	if (ndo->ndo_sa_list_head == NULL) {
    591 		if (!ndo->ndo_espsecret)
    592 			goto fail;
    593 
    594 		esp_print_decodesecret(ndo);
    595 	}
    596 
    597 	if (ndo->ndo_sa_list_head == NULL)
    598 		goto fail;
    599 
    600 	ip = (struct ip *)bp2;
    601 	switch (IP_V(ip)) {
    602 #ifdef INET6
    603 	case 6:
    604 		ip6 = (struct ip6_hdr *)bp2;
    605 		/* we do not attempt to decrypt jumbograms */
    606 		if (!EXTRACT_16BITS(&ip6->ip6_plen))
    607 			goto fail;
    608 		/* if we can't get nexthdr, we do not need to decrypt it */
    609 		len = sizeof(struct ip6_hdr) + EXTRACT_16BITS(&ip6->ip6_plen);
    610 
    611 		/* see if we can find the SA, and if so, decode it */
    612 		for (sa = ndo->ndo_sa_list_head; sa != NULL; sa = sa->next) {
    613 			struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&sa->daddr;
    614 			if (sa->spi == EXTRACT_32BITS(&esp->esp_spi) &&
    615 			    sin6->sin6_family == AF_INET6 &&
    616 			    UNALIGNED_MEMCMP(&sin6->sin6_addr, &ip6->ip6_dst,
    617 				   sizeof(struct in6_addr)) == 0) {
    618 				break;
    619 			}
    620 		}
    621 		break;
    622 #endif /*INET6*/
    623 	case 4:
    624 		/* nexthdr & padding are in the last fragment */
    625 		if (EXTRACT_16BITS(&ip->ip_off) & IP_MF)
    626 			goto fail;
    627 		len = EXTRACT_16BITS(&ip->ip_len);
    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 			struct sockaddr_in *sin = (struct sockaddr_in *)&sa->daddr;
    632 			if (sa->spi == EXTRACT_32BITS(&esp->esp_spi) &&
    633 			    sin->sin_family == AF_INET &&
    634 			    UNALIGNED_MEMCMP(&sin->sin_addr, &ip->ip_dst,
    635 				   sizeof(struct in_addr)) == 0) {
    636 				break;
    637 			}
    638 		}
    639 		break;
    640 	default:
    641 		goto fail;
    642 	}
    643 
    644 	/* if we didn't find the specific one, then look for
    645 	 * an unspecified one.
    646 	 */
    647 	if (sa == NULL)
    648 		sa = ndo->ndo_sa_default;
    649 
    650 	/* if not found fail */
    651 	if (sa == NULL)
    652 		goto fail;
    653 
    654 	/* if we can't get nexthdr, we do not need to decrypt it */
    655 	if (ep - bp2 < len)
    656 		goto fail;
    657 	if (ep - bp2 > len) {
    658 		/* FCS included at end of frame (NetBSD 1.6 or later) */
    659 		ep = bp2 + len;
    660 	}
    661 
    662 	ivoff = (u_char *)(esp + 1) + 0;
    663 	ivlen = sa->ivlen;
    664 	secret = sa->secret;
    665 	ep = ep - sa->authlen;
    666 
    667 	if (sa->evp) {
    668 		memset(&ctx, 0, sizeof(ctx));
    669 		if (EVP_CipherInit(&ctx, sa->evp, secret, NULL, 0) < 0)
    670 			(*ndo->ndo_warning)(ndo, "espkey init failed");
    671 
    672 		p = ivoff;
    673 		EVP_CipherInit(&ctx, NULL, NULL, p, 0);
    674 		EVP_Cipher(&ctx, p + ivlen, p + ivlen, ep - (p + ivlen));
    675 		EVP_CIPHER_CTX_cleanup(&ctx);
    676 		advance = ivoff - (u_char *)esp + ivlen;
    677 	} else
    678 		advance = sizeof(struct newesp);
    679 
    680 	/* sanity check for pad length */
    681 	if (ep - bp < *(ep - 2))
    682 		goto fail;
    683 
    684 	if (padlen)
    685 		*padlen = *(ep - 2) + 2;
    686 
    687 	if (nhdr)
    688 		*nhdr = *(ep - 1);
    689 
    690 	(ndo->ndo_printf)(ndo, ": ");
    691 	return advance;
    692 #endif
    693 
    694 fail:
    695 	return -1;
    696 }
    697 #ifdef HAVE_LIBCRYPTO
    698 USES_APPLE_RST
    699 #endif
    700 
    701 /*
    702  * Local Variables:
    703  * c-style: whitesmith
    704  * c-basic-offset: 8
    705  * End:
    706  */
    707