xref: /netbsd-src/external/bsd/tcpdump/dist/print-esp.c (revision bdc22b2e01993381dcefeff2bc9b56ca75a4235c)
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.9 2017/09/08 14:01:13 christos 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 #ifdef HAVE_EVP_CIPHERINIT_EX
154 /*
155  * Initialize the cipher by calling EVP_CipherInit_ex(), because
156  * calling EVP_CipherInit() will reset the cipher context, clearing
157  * the cipher, so calling it twice, with the second call having a
158  * null cipher, will clear the already-set cipher.  EVP_CipherInit_ex(),
159  * however, won't reset the cipher context, so you can use it to specify
160  * the IV oin a second call after a first call to EVP_CipherInit_ex()
161  * to set the cipher and the key.
162  *
163  * XXX - is there some reason why we need to make two calls?
164  */
165 static int
166 set_cipher_parameters(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
167 		      const unsigned char *key,
168 		      const unsigned char *iv, int enc)
169 {
170 	return EVP_CipherInit_ex(ctx, cipher, NULL, key, iv, enc);
171 }
172 #else
173 /*
174  * Initialize the cipher by calling EVP_CipherInit(), because we don't
175  * have EVP_CipherInit_ex(); we rely on it not trashing the context.
176  */
177 static int
178 set_cipher_parameters(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
179 		      const unsigned char *key,
180 		      const unsigned char *iv, int enc)
181 {
182 	return EVP_CipherInit(ctx, cipher, key, iv, enc);
183 }
184 #endif
185 
186 /*
187  * this will adjust ndo_packetp and ndo_snapend to new buffer!
188  */
189 USES_APPLE_DEPRECATED_API
190 int esp_print_decrypt_buffer_by_ikev2(netdissect_options *ndo,
191 				      int initiator,
192 				      u_char spii[8], u_char spir[8],
193 				      const u_char *buf, const u_char *end)
194 {
195 	struct sa_list *sa;
196 	const u_char *iv;
197 	unsigned int len;
198 	EVP_CIPHER_CTX *ctx;
199 	unsigned int block_size, output_buffer_size;
200 	u_char *output_buffer;
201 
202 	/* initiator arg is any non-zero value */
203 	if(initiator) initiator=1;
204 
205 	/* see if we can find the SA, and if so, decode it */
206 	for (sa = ndo->ndo_sa_list_head; sa != NULL; sa = sa->next) {
207 		if (sa->spi == 0
208 		    && initiator == sa->initiator
209 		    && memcmp(spii, sa->spii, 8) == 0
210 		    && memcmp(spir, sa->spir, 8) == 0)
211 			break;
212 	}
213 
214 	if(sa == NULL) return 0;
215 	if(sa->evp == NULL) return 0;
216 
217 	/*
218 	 * remove authenticator, and see if we still have something to
219 	 * work with
220 	 */
221 	end = end - sa->authlen;
222 	iv  = buf;
223 	buf = buf + sa->ivlen;
224 	len = end-buf;
225 
226 	if(end <= buf) return 0;
227 
228 	ctx = EVP_CIPHER_CTX_new();
229 	if (ctx == NULL)
230 		return 0;
231 	if (set_cipher_parameters(ctx, sa->evp, sa->secret, NULL, 0) < 0)
232 		(*ndo->ndo_warning)(ndo, "espkey init failed");
233 	set_cipher_parameters(ctx, NULL, NULL, iv, 0);
234 	/*
235 	 * Allocate a buffer for the decrypted data.
236 	 * The output buffer must be separate from the input buffer, and
237 	 * its size must be a multiple of the cipher block size.
238 	 */
239 	block_size = (unsigned int)EVP_CIPHER_CTX_block_size(ctx);
240 	output_buffer_size = len + (block_size - len % block_size);
241 	output_buffer = (u_char *)malloc(output_buffer_size);
242 	if (output_buffer == NULL) {
243 		(*ndo->ndo_warning)(ndo, "can't allocate memory for decryption buffer");
244 		EVP_CIPHER_CTX_free(ctx);
245 		return 0;
246 	}
247 	EVP_Cipher(ctx, output_buffer, buf, len);
248 	EVP_CIPHER_CTX_free(ctx);
249 
250 	/*
251 	 * XXX - of course this is wrong, because buf is a const buffer,
252 	 * but changing this would require a more complicated fix.
253 	 */
254 	memcpy(__UNCONST(buf), output_buffer, len);
255 	free(output_buffer);
256 
257 	ndo->ndo_packetp = buf;
258 	ndo->ndo_snapend = end;
259 
260 	return 1;
261 }
262 USES_APPLE_RST
263 
264 static void esp_print_addsa(netdissect_options *ndo,
265 			    struct sa_list *sa, int sa_def)
266 {
267 	/* copy the "sa" */
268 
269 	struct sa_list *nsa;
270 
271 	nsa = (struct sa_list *)malloc(sizeof(struct sa_list));
272 	if (nsa == NULL)
273 		(*ndo->ndo_error)(ndo, "ran out of memory to allocate sa structure");
274 
275 	*nsa = *sa;
276 
277 	if (sa_def)
278 		ndo->ndo_sa_default = nsa;
279 
280 	nsa->next = ndo->ndo_sa_list_head;
281 	ndo->ndo_sa_list_head = nsa;
282 }
283 
284 
285 static u_int hexdigit(netdissect_options *ndo, char hex)
286 {
287 	if (hex >= '0' && hex <= '9')
288 		return (hex - '0');
289 	else if (hex >= 'A' && hex <= 'F')
290 		return (hex - 'A' + 10);
291 	else if (hex >= 'a' && hex <= 'f')
292 		return (hex - 'a' + 10);
293 	else {
294 		(*ndo->ndo_error)(ndo, "invalid hex digit %c in espsecret\n", hex);
295 		return 0;
296 	}
297 }
298 
299 static u_int hex2byte(netdissect_options *ndo, char *hexstring)
300 {
301 	u_int byte;
302 
303 	byte = (hexdigit(ndo, hexstring[0]) << 4) + hexdigit(ndo, hexstring[1]);
304 	return byte;
305 }
306 
307 /*
308  * returns size of binary, 0 on failure.
309  */
310 static
311 int espprint_decode_hex(netdissect_options *ndo,
312 			u_char *binbuf, unsigned int binbuf_len,
313 			char *hex)
314 {
315 	unsigned int len;
316 	int i;
317 
318 	len = strlen(hex) / 2;
319 
320 	if (len > binbuf_len) {
321 		(*ndo->ndo_warning)(ndo, "secret is too big: %d\n", len);
322 		return 0;
323 	}
324 
325 	i = 0;
326 	while (hex[0] != '\0' && hex[1]!='\0') {
327 		binbuf[i] = hex2byte(ndo, hex);
328 		hex += 2;
329 		i++;
330 	}
331 
332 	return i;
333 }
334 
335 /*
336  * decode the form:    SPINUM@IP <tab> ALGONAME:0xsecret
337  */
338 
339 USES_APPLE_DEPRECATED_API
340 static int
341 espprint_decode_encalgo(netdissect_options *ndo,
342 			char *decode, struct sa_list *sa)
343 {
344 	size_t i;
345 	const EVP_CIPHER *evp;
346 	int authlen = 0;
347 	char *colon, *p;
348 
349 	colon = strchr(decode, ':');
350 	if (colon == NULL) {
351 		(*ndo->ndo_warning)(ndo, "failed to decode espsecret: %s\n", decode);
352 		return 0;
353 	}
354 	*colon = '\0';
355 
356 	if (strlen(decode) > strlen("-hmac96") &&
357 	    !strcmp(decode + strlen(decode) - strlen("-hmac96"),
358 		    "-hmac96")) {
359 		p = strstr(decode, "-hmac96");
360 		*p = '\0';
361 		authlen = 12;
362 	}
363 	if (strlen(decode) > strlen("-cbc") &&
364 	    !strcmp(decode + strlen(decode) - strlen("-cbc"), "-cbc")) {
365 		p = strstr(decode, "-cbc");
366 		*p = '\0';
367 	}
368 	evp = EVP_get_cipherbyname(decode);
369 
370 	if (!evp) {
371 		(*ndo->ndo_warning)(ndo, "failed to find cipher algo %s\n", decode);
372 		sa->evp = NULL;
373 		sa->authlen = 0;
374 		sa->ivlen = 0;
375 		return 0;
376 	}
377 
378 	sa->evp = evp;
379 	sa->authlen = authlen;
380 	sa->ivlen = EVP_CIPHER_iv_length(evp);
381 
382 	colon++;
383 	if (colon[0] == '0' && colon[1] == 'x') {
384 		/* decode some hex! */
385 
386 		colon += 2;
387 		sa->secretlen = espprint_decode_hex(ndo, sa->secret, sizeof(sa->secret), colon);
388 		if(sa->secretlen == 0) return 0;
389 	} else {
390 		i = strlen(colon);
391 
392 		if (i < sizeof(sa->secret)) {
393 			memcpy(sa->secret, colon, i);
394 			sa->secretlen = i;
395 		} else {
396 			memcpy(sa->secret, colon, sizeof(sa->secret));
397 			sa->secretlen = sizeof(sa->secret);
398 		}
399 	}
400 
401 	return 1;
402 }
403 USES_APPLE_RST
404 
405 /*
406  * for the moment, ignore the auth algorith, just hard code the authenticator
407  * length. Need to research how openssl looks up HMAC stuff.
408  */
409 static int
410 espprint_decode_authalgo(netdissect_options *ndo,
411 			 char *decode, struct sa_list *sa)
412 {
413 	char *colon;
414 
415 	colon = strchr(decode, ':');
416 	if (colon == NULL) {
417 		(*ndo->ndo_warning)(ndo, "failed to decode espsecret: %s\n", decode);
418 		return 0;
419 	}
420 	*colon = '\0';
421 
422 	if(ascii_strcasecmp(colon,"sha1") == 0 ||
423 	   ascii_strcasecmp(colon,"md5") == 0) {
424 		sa->authlen = 12;
425 	}
426 	return 1;
427 }
428 
429 static void esp_print_decode_ikeline(netdissect_options *ndo, char *line,
430 				     const char *file, int lineno)
431 {
432 	/* it's an IKEv2 secret, store it instead */
433 	struct sa_list sa1;
434 
435 	char *init;
436 	char *icookie, *rcookie;
437 	int   ilen, rlen;
438 	char *authkey;
439 	char *enckey;
440 
441 	init = strsep(&line, " \t");
442 	icookie = strsep(&line, " \t");
443 	rcookie = strsep(&line, " \t");
444 	authkey = strsep(&line, " \t");
445 	enckey  = strsep(&line, " \t");
446 
447 	/* if any fields are missing */
448 	if(!init || !icookie || !rcookie || !authkey || !enckey) {
449 		(*ndo->ndo_warning)(ndo, "print_esp: failed to find all fields for ikev2 at %s:%u",
450 				    file, lineno);
451 
452 		return;
453 	}
454 
455 	ilen = strlen(icookie);
456 	rlen = strlen(rcookie);
457 
458 	if((init[0]!='I' && init[0]!='R')
459 	   || icookie[0]!='0' || icookie[1]!='x'
460 	   || rcookie[0]!='0' || rcookie[1]!='x'
461 	   || ilen!=18
462 	   || rlen!=18) {
463 		(*ndo->ndo_warning)(ndo, "print_esp: line %s:%u improperly formatted.",
464 				    file, lineno);
465 
466 		(*ndo->ndo_warning)(ndo, "init=%s icookie=%s(%u) rcookie=%s(%u)",
467 				    init, icookie, ilen, rcookie, rlen);
468 
469 		return;
470 	}
471 
472 	sa1.spi = 0;
473 	sa1.initiator = (init[0] == 'I');
474 	if(espprint_decode_hex(ndo, sa1.spii, sizeof(sa1.spii), icookie+2)!=8)
475 		return;
476 
477 	if(espprint_decode_hex(ndo, sa1.spir, sizeof(sa1.spir), rcookie+2)!=8)
478 		return;
479 
480 	if(!espprint_decode_encalgo(ndo, enckey, &sa1)) return;
481 
482 	if(!espprint_decode_authalgo(ndo, authkey, &sa1)) return;
483 
484 	esp_print_addsa(ndo, &sa1, FALSE);
485 }
486 
487 /*
488  *
489  * special form: file /name
490  * causes us to go read from this file instead.
491  *
492  */
493 static void esp_print_decode_onesecret(netdissect_options *ndo, char *line,
494 				       const char *file, int lineno)
495 {
496 	struct sa_list sa1;
497 	int sa_def;
498 
499 	char *spikey;
500 	char *decode;
501 
502 	spikey = strsep(&line, " \t");
503 	sa_def = 0;
504 	memset(&sa1, 0, sizeof(struct sa_list));
505 
506 	/* if there is only one token, then it is an algo:key token */
507 	if (line == NULL) {
508 		decode = spikey;
509 		spikey = NULL;
510 		/* sa1.daddr.version = 0; */
511 		/* memset(&sa1.daddr, 0, sizeof(sa1.daddr)); */
512 		/* sa1.spi = 0; */
513 		sa_def    = 1;
514 	} else
515 		decode = line;
516 
517 	if (spikey && ascii_strcasecmp(spikey, "file") == 0) {
518 		/* open file and read it */
519 		FILE *secretfile;
520 		char  fileline[1024];
521 		int   subfile_lineno=0;
522 		char  *nl;
523 		char *filename = line;
524 
525 		secretfile = fopen(filename, FOPEN_READ_TXT);
526 		if (secretfile == NULL) {
527 			(*ndo->ndo_error)(ndo, "print_esp: can't open %s: %s\n",
528 			    filename, strerror(errno));
529 			return;
530 		}
531 
532 		while (fgets(fileline, sizeof(fileline)-1, secretfile) != NULL) {
533 			subfile_lineno++;
534 			/* remove newline from the line */
535 			nl = strchr(fileline, '\n');
536 			if (nl)
537 				*nl = '\0';
538 			if (fileline[0] == '#') continue;
539 			if (fileline[0] == '\0') continue;
540 
541 			esp_print_decode_onesecret(ndo, fileline, filename, subfile_lineno);
542 		}
543 		fclose(secretfile);
544 
545 		return;
546 	}
547 
548 	if (spikey && ascii_strcasecmp(spikey, "ikev2") == 0) {
549 		esp_print_decode_ikeline(ndo, line, file, lineno);
550 		return;
551 	}
552 
553 	if (spikey) {
554 
555 		char *spistr, *foo;
556 		uint32_t spino;
557 
558 		spistr = strsep(&spikey, "@");
559 
560 		spino = strtoul(spistr, &foo, 0);
561 		if (spistr == foo || !spikey) {
562 			(*ndo->ndo_warning)(ndo, "print_esp: failed to decode spi# %s\n", foo);
563 			return;
564 		}
565 
566 		sa1.spi = spino;
567 
568 		if (strtoaddr6(spikey, &sa1.daddr.in6) == 1) {
569 			sa1.daddr_version = 6;
570 		} else if (strtoaddr(spikey, &sa1.daddr.in4) == 1) {
571 			sa1.daddr_version = 4;
572 		} else {
573 			(*ndo->ndo_warning)(ndo, "print_esp: can not decode IP# %s\n", spikey);
574 			return;
575 		}
576 	}
577 
578 	if (decode) {
579 		/* skip any blank spaces */
580 		while (isspace((unsigned char)*decode))
581 			decode++;
582 
583 		if(!espprint_decode_encalgo(ndo, decode, &sa1)) {
584 			return;
585 		}
586 	}
587 
588 	esp_print_addsa(ndo, &sa1, sa_def);
589 }
590 
591 USES_APPLE_DEPRECATED_API
592 static void esp_init(netdissect_options *ndo _U_)
593 {
594 	/*
595 	 * 0.9.6 doesn't appear to define OPENSSL_API_COMPAT, so
596 	 * we check whether it's undefined or it's less than the
597 	 * value for 1.1.0.
598 	 */
599 #if !defined(OPENSSL_API_COMPAT) || OPENSSL_API_COMPAT < 0x10100000L
600 	OpenSSL_add_all_algorithms();
601 #endif
602 	EVP_add_cipher_alias(SN_des_ede3_cbc, "3des");
603 }
604 USES_APPLE_RST
605 
606 void esp_print_decodesecret(netdissect_options *ndo)
607 {
608 	char *line;
609 	char *p;
610 	static int initialized = 0;
611 
612 	if (!initialized) {
613 		esp_init(ndo);
614 		initialized = 1;
615 	}
616 
617 	p = ndo->ndo_espsecret;
618 
619 	while (p && p[0] != '\0') {
620 		/* pick out the first line or first thing until a comma */
621 		if ((line = strsep(&p, "\n,")) == NULL) {
622 			line = p;
623 			p = NULL;
624 		}
625 
626 		esp_print_decode_onesecret(ndo, line, "cmdline", 0);
627 	}
628 
629 	ndo->ndo_espsecret = NULL;
630 }
631 
632 #endif
633 
634 #ifdef HAVE_LIBCRYPTO
635 USES_APPLE_DEPRECATED_API
636 #endif
637 int
638 esp_print(netdissect_options *ndo,
639 	  const u_char *bp, const int length, const u_char *bp2
640 #ifndef HAVE_LIBCRYPTO
641 	_U_
642 #endif
643 	,
644 	int *nhdr
645 #ifndef HAVE_LIBCRYPTO
646 	_U_
647 #endif
648 	,
649 	int *padlen
650 #ifndef HAVE_LIBCRYPTO
651 	_U_
652 #endif
653 	)
654 {
655 	register const struct newesp *esp;
656 	register const u_char *ep;
657 #ifdef HAVE_LIBCRYPTO
658 	const struct ip *ip;
659 	struct sa_list *sa = NULL;
660 	const struct ip6_hdr *ip6 = NULL;
661 	int advance;
662 	int len;
663 	u_char *secret;
664 	int ivlen = 0;
665 	const u_char *ivoff;
666 	const u_char *p;
667 	EVP_CIPHER_CTX *ctx;
668 	unsigned int block_size, output_buffer_size;
669 	u_char *output_buffer;
670 #endif
671 
672 	esp = (const struct newesp *)bp;
673 
674 #ifdef HAVE_LIBCRYPTO
675 	secret = NULL;
676 	advance = 0;
677 #endif
678 
679 #if 0
680 	/* keep secret out of a register */
681 	p = (u_char *)&secret;
682 #endif
683 
684 	/* 'ep' points to the end of available data. */
685 	ep = ndo->ndo_snapend;
686 
687 	if ((const u_char *)(esp + 1) >= ep) {
688 		ND_PRINT((ndo, "[|ESP]"));
689 		goto fail;
690 	}
691 	ND_PRINT((ndo, "ESP(spi=0x%08x", EXTRACT_32BITS(&esp->esp_spi)));
692 	ND_PRINT((ndo, ",seq=0x%x)", EXTRACT_32BITS(&esp->esp_seq)));
693 	ND_PRINT((ndo, ", length %u", length));
694 
695 #ifndef HAVE_LIBCRYPTO
696 	goto fail;
697 #else
698 	/* initiailize SAs */
699 	if (ndo->ndo_sa_list_head == NULL) {
700 		if (!ndo->ndo_espsecret)
701 			goto fail;
702 
703 		esp_print_decodesecret(ndo);
704 	}
705 
706 	if (ndo->ndo_sa_list_head == NULL)
707 		goto fail;
708 
709 	ip = (const struct ip *)bp2;
710 	switch (IP_V(ip)) {
711 	case 6:
712 		ip6 = (const struct ip6_hdr *)bp2;
713 		/* we do not attempt to decrypt jumbograms */
714 		if (!EXTRACT_16BITS(&ip6->ip6_plen))
715 			goto fail;
716 		/* if we can't get nexthdr, we do not need to decrypt it */
717 		len = sizeof(struct ip6_hdr) + EXTRACT_16BITS(&ip6->ip6_plen);
718 
719 		/* see if we can find the SA, and if so, decode it */
720 		for (sa = ndo->ndo_sa_list_head; sa != NULL; sa = sa->next) {
721 			if (sa->spi == EXTRACT_32BITS(&esp->esp_spi) &&
722 			    sa->daddr_version == 6 &&
723 			    UNALIGNED_MEMCMP(&sa->daddr.in6, &ip6->ip6_dst,
724 				   sizeof(struct in6_addr)) == 0) {
725 				break;
726 			}
727 		}
728 		break;
729 	case 4:
730 		/* nexthdr & padding are in the last fragment */
731 		if (EXTRACT_16BITS(&ip->ip_off) & IP_MF)
732 			goto fail;
733 		len = EXTRACT_16BITS(&ip->ip_len);
734 
735 		/* see if we can find the SA, and if so, decode it */
736 		for (sa = ndo->ndo_sa_list_head; sa != NULL; sa = sa->next) {
737 			if (sa->spi == EXTRACT_32BITS(&esp->esp_spi) &&
738 			    sa->daddr_version == 4 &&
739 			    UNALIGNED_MEMCMP(&sa->daddr.in4, &ip->ip_dst,
740 				   sizeof(struct in_addr)) == 0) {
741 				break;
742 			}
743 		}
744 		break;
745 	default:
746 		goto fail;
747 	}
748 
749 	/* if we didn't find the specific one, then look for
750 	 * an unspecified one.
751 	 */
752 	if (sa == NULL)
753 		sa = ndo->ndo_sa_default;
754 
755 	/* if not found fail */
756 	if (sa == NULL)
757 		goto fail;
758 
759 	/* if we can't get nexthdr, we do not need to decrypt it */
760 	if (ep - bp2 < len)
761 		goto fail;
762 	if (ep - bp2 > len) {
763 		/* FCS included at end of frame (NetBSD 1.6 or later) */
764 		ep = bp2 + len;
765 	}
766 
767 	/* pointer to the IV, if there is one */
768 	ivoff = (const u_char *)(esp + 1) + 0;
769 	/* length of the IV, if there is one; 0, if there isn't */
770 	ivlen = sa->ivlen;
771 	secret = sa->secret;
772 	ep = ep - sa->authlen;
773 
774 	if (sa->evp) {
775 		ctx = EVP_CIPHER_CTX_new();
776 		if (ctx != NULL) {
777 			if (set_cipher_parameters(ctx, sa->evp, secret, NULL, 0) < 0)
778 				(*ndo->ndo_warning)(ndo, "espkey init failed");
779 
780 			p = ivoff;
781 			set_cipher_parameters(ctx, NULL, NULL, p, 0);
782 			len = ep - (p + ivlen);
783 
784 			/*
785 			 * Allocate a buffer for the decrypted data.
786 			 * The output buffer must be separate from the
787 			 * input buffer, and its size must be a multiple
788 			 * of the cipher block size.
789 			 */
790 			block_size = (unsigned int)EVP_CIPHER_CTX_block_size(ctx);
791 			output_buffer_size = len + (block_size - len % block_size);
792 			output_buffer = (u_char *)malloc(output_buffer_size);
793 			if (output_buffer == NULL) {
794 				(*ndo->ndo_warning)(ndo, "can't allocate memory for decryption buffer");
795 				EVP_CIPHER_CTX_free(ctx);
796 				return -1;
797 			}
798 
799 			EVP_Cipher(ctx, output_buffer, p + ivlen, len);
800 			EVP_CIPHER_CTX_free(ctx);
801 			/*
802 			 * XXX - of course this is wrong, because buf is a
803 			 * const buffer, but changing this would require a
804 			 * more complicated fix.
805 			 */
806 			memcpy(__UNCONST(p + ivlen), output_buffer, len);
807 			free(output_buffer);
808 			advance = ivoff - (const u_char *)esp + ivlen;
809 		} else
810 			advance = sizeof(struct newesp);
811 	} else
812 		advance = sizeof(struct newesp);
813 
814 	/* sanity check for pad length */
815 	if (ep - bp < *(ep - 2))
816 		goto fail;
817 
818 	if (padlen)
819 		*padlen = *(ep - 2) + 2;
820 
821 	if (nhdr)
822 		*nhdr = *(ep - 1);
823 
824 	ND_PRINT((ndo, ": "));
825 	return advance;
826 #endif
827 
828 fail:
829 	return -1;
830 }
831 #ifdef HAVE_LIBCRYPTO
832 USES_APPLE_RST
833 #endif
834 
835 /*
836  * Local Variables:
837  * c-style: whitesmith
838  * c-basic-offset: 8
839  * End:
840  */
841