xref: /freebsd/contrib/tcpdump/print-esp.c (revision 5b0fe47811aa43b75fc69dbf7338cace232a4d48)
1b0453382SBill Fenner /*	$NetBSD: print-ah.c,v 1.4 1996/05/20 00:41:16 fvdl Exp $	*/
2b0453382SBill Fenner 
3b0453382SBill Fenner /*
4b0453382SBill Fenner  * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994
5b0453382SBill Fenner  *	The Regents of the University of California.  All rights reserved.
6b0453382SBill Fenner  *
7b0453382SBill Fenner  * Redistribution and use in source and binary forms, with or without
8b0453382SBill Fenner  * modification, are permitted provided that: (1) source code distributions
9b0453382SBill Fenner  * retain the above copyright notice and this paragraph in its entirety, (2)
10b0453382SBill Fenner  * distributions including binary code include the above copyright notice and
11b0453382SBill Fenner  * this paragraph in its entirety in the documentation or other materials
12b0453382SBill Fenner  * provided with the distribution, and (3) all advertising materials mentioning
13b0453382SBill Fenner  * features or use of this software display the following acknowledgement:
14b0453382SBill Fenner  * ``This product includes software developed by the University of California,
15b0453382SBill Fenner  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
16b0453382SBill Fenner  * the University nor the names of its contributors may be used to endorse
17b0453382SBill Fenner  * or promote products derived from this software without specific prior
18b0453382SBill Fenner  * written permission.
19b0453382SBill Fenner  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
20b0453382SBill Fenner  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
21b0453382SBill Fenner  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
22b0453382SBill Fenner  */
23b0453382SBill Fenner 
24b0453382SBill Fenner #ifndef lint
255b0fe478SBruce M Simpson static const char rcsid[] _U_ =
265b0fe478SBruce M Simpson     "@(#) $Header: /tcpdump/master/tcpdump/print-esp.c,v 1.44.2.4 2003/11/19 05:36:40 guy Exp $ (LBL)";
27b0453382SBill Fenner #endif
28b0453382SBill Fenner 
29b0453382SBill Fenner #ifdef HAVE_CONFIG_H
30b0453382SBill Fenner #include "config.h"
31b0453382SBill Fenner #endif
32b0453382SBill Fenner 
33b0453382SBill Fenner #include <string.h>
345b0fe478SBruce M Simpson 
355b0fe478SBruce M Simpson #include <tcpdump-stdinc.h>
365b0fe478SBruce M Simpson 
379afd0c29SBill Fenner #include <stdlib.h>
38b0453382SBill Fenner 
39685295f4SBill Fenner #ifdef HAVE_LIBCRYPTO
405b0fe478SBruce M Simpson #ifdef HAVE_OPENSSL_EVP_H
415b0fe478SBruce M Simpson #include <openssl/evp.h>
42b0453382SBill Fenner #endif
43b0453382SBill Fenner #endif
44b0453382SBill Fenner 
45b0453382SBill Fenner #include <stdio.h>
46b0453382SBill Fenner 
47685295f4SBill Fenner #include "ip.h"
48685295f4SBill Fenner #include "esp.h"
49b0453382SBill Fenner #ifdef INET6
50685295f4SBill Fenner #include "ip6.h"
51b0453382SBill Fenner #endif
52b0453382SBill Fenner 
535b0fe478SBruce M Simpson #if defined(__MINGW32__) || defined(__WATCOMC__)
545b0fe478SBruce M Simpson extern char *strsep(char **stringp, const char *delim); /* Missing/strsep.c */
555b0fe478SBruce M Simpson #endif
565b0fe478SBruce M Simpson 
57b0453382SBill Fenner #include "interface.h"
58b0453382SBill Fenner #include "addrtoname.h"
595b0fe478SBruce M Simpson #include "extract.h"
60b0453382SBill Fenner 
615b0fe478SBruce M Simpson #ifndef HAVE_SOCKADDR_STORAGE
625b0fe478SBruce M Simpson #ifdef INET6
635b0fe478SBruce M Simpson struct sockaddr_storage {
645b0fe478SBruce M Simpson 	union {
655b0fe478SBruce M Simpson 		struct sockaddr_in sin;
665b0fe478SBruce M Simpson 		struct sockaddr_in6 sin6;
675b0fe478SBruce M Simpson 	} un;
685b0fe478SBruce M Simpson };
695b0fe478SBruce M Simpson #else
705b0fe478SBruce M Simpson #define sockaddr_storage sockaddr
715b0fe478SBruce M Simpson #endif
725b0fe478SBruce M Simpson #endif /* HAVE_SOCKADDR_STORAGE */
73a90e161bSBill Fenner 
745b0fe478SBruce M Simpson #ifdef HAVE_LIBCRYPTO
755b0fe478SBruce M Simpson struct sa_list {
765b0fe478SBruce M Simpson 	struct sa_list	*next;
775b0fe478SBruce M Simpson 	struct sockaddr_storage daddr;
785b0fe478SBruce M Simpson 	u_int32_t	spi;
795b0fe478SBruce M Simpson 	const EVP_CIPHER *evp;
80a90e161bSBill Fenner 	int		ivlen;
81a90e161bSBill Fenner 	int		authlen;
825b0fe478SBruce M Simpson 	char		secret[256];  /* is that big enough for all secrets? */
835b0fe478SBruce M Simpson 	int		secretlen;
84a90e161bSBill Fenner };
85a90e161bSBill Fenner 
865b0fe478SBruce M Simpson static struct sa_list *sa_list_head = NULL;
875b0fe478SBruce M Simpson static struct sa_list *sa_default = NULL;
885b0fe478SBruce M Simpson 
895b0fe478SBruce M Simpson static void esp_print_addsa(struct sa_list *sa, int sa_def)
905b0fe478SBruce M Simpson {
915b0fe478SBruce M Simpson 	/* copy the "sa" */
925b0fe478SBruce M Simpson 
935b0fe478SBruce M Simpson 	struct sa_list *nsa;
945b0fe478SBruce M Simpson 
955b0fe478SBruce M Simpson 	nsa = (struct sa_list *)malloc(sizeof(struct sa_list));
965b0fe478SBruce M Simpson 	if (nsa == NULL)
975b0fe478SBruce M Simpson 		error("ran out of memory to allocate sa structure");
985b0fe478SBruce M Simpson 
995b0fe478SBruce M Simpson 	*nsa = *sa;
1005b0fe478SBruce M Simpson 
1015b0fe478SBruce M Simpson 	if (sa_def)
1025b0fe478SBruce M Simpson 		sa_default = nsa;
1035b0fe478SBruce M Simpson 
1045b0fe478SBruce M Simpson 	nsa->next = sa_list_head;
1055b0fe478SBruce M Simpson 	sa_list_head = nsa;
1065b0fe478SBruce M Simpson }
1075b0fe478SBruce M Simpson 
108a90e161bSBill Fenner 
109a90e161bSBill Fenner static int hexdigit(char hex)
110a90e161bSBill Fenner {
1115b0fe478SBruce M Simpson 	if (hex >= '0' && hex <= '9')
112a90e161bSBill Fenner 		return (hex - '0');
1135b0fe478SBruce M Simpson 	else if (hex >= 'A' && hex <= 'F')
114a90e161bSBill Fenner 		return (hex - 'A' + 10);
1155b0fe478SBruce M Simpson 	else if (hex >= 'a' && hex <= 'f')
116a90e161bSBill Fenner 		return (hex - 'a' + 10);
1175b0fe478SBruce M Simpson 	else {
118a90e161bSBill Fenner 		printf("invalid hex digit %c in espsecret\n", hex);
119a90e161bSBill Fenner 		return 0;
120a90e161bSBill Fenner 	}
121a90e161bSBill Fenner }
122a90e161bSBill Fenner 
123a90e161bSBill Fenner static int hex2byte(char *hexstring)
124a90e161bSBill Fenner {
125a90e161bSBill Fenner 	int byte;
126a90e161bSBill Fenner 
1275b0fe478SBruce M Simpson 	byte = (hexdigit(hexstring[0]) << 4) + hexdigit(hexstring[1]);
128a90e161bSBill Fenner 	return byte;
129a90e161bSBill Fenner }
130a90e161bSBill Fenner 
1315b0fe478SBruce M Simpson /*
1325b0fe478SBruce M Simpson  * decode the form:    SPINUM@IP <tab> ALGONAME:0xsecret
1335b0fe478SBruce M Simpson  *
1345b0fe478SBruce M Simpson  * special form: file /name
1355b0fe478SBruce M Simpson  * causes us to go read from this file instead.
1365b0fe478SBruce M Simpson  *
1375b0fe478SBruce M Simpson  */
1385b0fe478SBruce M Simpson static void esp_print_decode_onesecret(char *line)
139a90e161bSBill Fenner {
1405b0fe478SBruce M Simpson 	struct sa_list sa1;
1415b0fe478SBruce M Simpson 	int sa_def;
142a90e161bSBill Fenner 
1435b0fe478SBruce M Simpson 	char *spikey;
1445b0fe478SBruce M Simpson 	char *decode;
1455b0fe478SBruce M Simpson 
1465b0fe478SBruce M Simpson 	spikey = strsep(&line, " \t");
1475b0fe478SBruce M Simpson 	sa_def = 0;
1485b0fe478SBruce M Simpson 	memset(&sa1, 0, sizeof(struct sa_list));
1495b0fe478SBruce M Simpson 
1505b0fe478SBruce M Simpson 	/* if there is only one token, then it is an algo:key token */
1515b0fe478SBruce M Simpson 	if (line == NULL) {
1525b0fe478SBruce M Simpson 		decode = spikey;
1535b0fe478SBruce M Simpson 		spikey = NULL;
1545b0fe478SBruce M Simpson 		/* memset(&sa1.daddr, 0, sizeof(sa1.daddr)); */
1555b0fe478SBruce M Simpson 		/* sa1.spi = 0; */
1565b0fe478SBruce M Simpson 		sa_def    = 1;
1575b0fe478SBruce M Simpson 	} else
1585b0fe478SBruce M Simpson 		decode = line;
1595b0fe478SBruce M Simpson 
1605b0fe478SBruce M Simpson 	if (spikey && strcasecmp(spikey, "file") == 0) {
1615b0fe478SBruce M Simpson 		/* open file and read it */
1625b0fe478SBruce M Simpson 		FILE *secretfile;
1635b0fe478SBruce M Simpson 		char  fileline[1024];
1645b0fe478SBruce M Simpson 		char  *nl;
1655b0fe478SBruce M Simpson 
1665b0fe478SBruce M Simpson 		secretfile = fopen(line, FOPEN_READ_TXT);
1675b0fe478SBruce M Simpson 		if (secretfile == NULL) {
1685b0fe478SBruce M Simpson 			perror(line);
1695b0fe478SBruce M Simpson 			exit(3);
1705b0fe478SBruce M Simpson 		}
1715b0fe478SBruce M Simpson 
1725b0fe478SBruce M Simpson 		while (fgets(fileline, sizeof(fileline)-1, secretfile) != NULL) {
1735b0fe478SBruce M Simpson 			/* remove newline from the line */
1745b0fe478SBruce M Simpson 			nl = strchr(fileline, '\n');
1755b0fe478SBruce M Simpson 			if (nl)
1765b0fe478SBruce M Simpson 				*nl = '\0';
1775b0fe478SBruce M Simpson 			if (fileline[0] == '#') continue;
1785b0fe478SBruce M Simpson 			if (fileline[0] == '\0') continue;
1795b0fe478SBruce M Simpson 
1805b0fe478SBruce M Simpson 			esp_print_decode_onesecret(fileline);
1815b0fe478SBruce M Simpson 		}
1825b0fe478SBruce M Simpson 		fclose(secretfile);
1835b0fe478SBruce M Simpson 
184a90e161bSBill Fenner 		return;
185a90e161bSBill Fenner 	}
186a90e161bSBill Fenner 
1875b0fe478SBruce M Simpson 	if (spikey) {
1885b0fe478SBruce M Simpson 		char *spistr, *foo;
1895b0fe478SBruce M Simpson 		u_int32_t spino;
1905b0fe478SBruce M Simpson 		struct sockaddr_in *sin;
1915b0fe478SBruce M Simpson #ifdef INET6
1925b0fe478SBruce M Simpson 		struct sockaddr_in6 *sin6;
1935b0fe478SBruce M Simpson #endif
1945b0fe478SBruce M Simpson 
1955b0fe478SBruce M Simpson 		spistr = strsep(&spikey, "@");
1965b0fe478SBruce M Simpson 
1975b0fe478SBruce M Simpson 		spino = strtoul(spistr, &foo, 0);
1985b0fe478SBruce M Simpson 		if (spistr == foo || !spikey) {
1995b0fe478SBruce M Simpson 			printf("print_esp: failed to decode spi# %s\n", foo);
200a90e161bSBill Fenner 			return;
201a90e161bSBill Fenner 		}
202a90e161bSBill Fenner 
2035b0fe478SBruce M Simpson 		sa1.spi = spino;
2045b0fe478SBruce M Simpson 
2055b0fe478SBruce M Simpson 		sin = (struct sockaddr_in *)&sa1.daddr;
2065b0fe478SBruce M Simpson #ifdef INET6
2075b0fe478SBruce M Simpson 		sin6 = (struct sockaddr_in6 *)&sa1.daddr;
2085b0fe478SBruce M Simpson 		if (inet_pton(AF_INET6, spikey, &sin6->sin6_addr) == 1) {
2095b0fe478SBruce M Simpson #ifdef HAVE_SOCKADDR_SA_LEN
2105b0fe478SBruce M Simpson 			sin6->sin6_len = sizeof(struct sockaddr_in6);
2115b0fe478SBruce M Simpson #endif
2125b0fe478SBruce M Simpson 			sin6->sin6_family = AF_INET6;
2135b0fe478SBruce M Simpson 		} else
2145b0fe478SBruce M Simpson #endif
2155b0fe478SBruce M Simpson 		if (inet_pton(AF_INET, spikey, &sin->sin_addr) == 1) {
2165b0fe478SBruce M Simpson #ifdef HAVE_SOCKADDR_SA_LEN
2175b0fe478SBruce M Simpson 			sin->sin_len = sizeof(struct sockaddr_in);
2185b0fe478SBruce M Simpson #endif
2195b0fe478SBruce M Simpson 			sin->sin_family = AF_INET;
2205b0fe478SBruce M Simpson 		} else {
2215b0fe478SBruce M Simpson 			printf("print_esp: can not decode IP# %s\n", spikey);
2225b0fe478SBruce M Simpson 			return;
2235b0fe478SBruce M Simpson 		}
2245b0fe478SBruce M Simpson 	}
2255b0fe478SBruce M Simpson 
2265b0fe478SBruce M Simpson 	if (decode) {
2275b0fe478SBruce M Simpson 		char *colon, *p;
2285b0fe478SBruce M Simpson 		char  espsecret_key[256];
2295b0fe478SBruce M Simpson 		int len;
2305b0fe478SBruce M Simpson 		size_t i;
2315b0fe478SBruce M Simpson 		const EVP_CIPHER *evp;
2325b0fe478SBruce M Simpson 		int ivlen = 8;
2335b0fe478SBruce M Simpson 		int authlen = 0;
2345b0fe478SBruce M Simpson 
2355b0fe478SBruce M Simpson 		/* skip any blank spaces */
2365b0fe478SBruce M Simpson 		while (isspace((unsigned char)*decode))
2375b0fe478SBruce M Simpson 			decode++;
2385b0fe478SBruce M Simpson 
2395b0fe478SBruce M Simpson 		colon = strchr(decode, ':');
240a90e161bSBill Fenner 		if (colon == NULL) {
2415b0fe478SBruce M Simpson 			printf("failed to decode espsecret: %s\n", decode);
242a90e161bSBill Fenner 			return;
243a90e161bSBill Fenner 		}
2445b0fe478SBruce M Simpson 		*colon = '\0';
2455b0fe478SBruce M Simpson 
2465b0fe478SBruce M Simpson 		len = colon - decode;
2475b0fe478SBruce M Simpson 		if (strlen(decode) > strlen("-hmac96") &&
2485b0fe478SBruce M Simpson 		    !strcmp(decode + strlen(decode) - strlen("-hmac96"),
2495b0fe478SBruce M Simpson 		    "-hmac96")) {
2505b0fe478SBruce M Simpson 			p = strstr(decode, "-hmac96");
2515b0fe478SBruce M Simpson 			*p = '\0';
2525b0fe478SBruce M Simpson 			authlen = 12;
2535b0fe478SBruce M Simpson 		}
2545b0fe478SBruce M Simpson 		if (strlen(decode) > strlen("-cbc") &&
2555b0fe478SBruce M Simpson 		    !strcmp(decode + strlen(decode) - strlen("-cbc"), "-cbc")) {
2565b0fe478SBruce M Simpson 			p = strstr(decode, "-cbc");
2575b0fe478SBruce M Simpson 			*p = '\0';
2585b0fe478SBruce M Simpson 		}
2595b0fe478SBruce M Simpson 		evp = EVP_get_cipherbyname(decode);
2605b0fe478SBruce M Simpson 		if (!evp) {
2615b0fe478SBruce M Simpson 			printf("failed to find cipher algo %s\n", decode);
2625b0fe478SBruce M Simpson 			sa1.evp = NULL;
2635b0fe478SBruce M Simpson 			sa1.authlen = 0;
2645b0fe478SBruce M Simpson 			sa1.ivlen = 0;
2655b0fe478SBruce M Simpson 			return;
2665b0fe478SBruce M Simpson 		}
2675b0fe478SBruce M Simpson 
2685b0fe478SBruce M Simpson 		sa1.evp = evp;
2695b0fe478SBruce M Simpson 		sa1.authlen = authlen;
2705b0fe478SBruce M Simpson 		sa1.ivlen = ivlen;
271a90e161bSBill Fenner 
272a90e161bSBill Fenner 		colon++;
273a90e161bSBill Fenner 		if (colon[0] == '0' && colon[1] == 'x') {
274a90e161bSBill Fenner 			/* decode some hex! */
275a90e161bSBill Fenner 			colon += 2;
276a90e161bSBill Fenner 			len = strlen(colon) / 2;
2775b0fe478SBruce M Simpson 
2785b0fe478SBruce M Simpson 			if (len > 256) {
2795b0fe478SBruce M Simpson 				printf("secret is too big: %d\n", len);
2805b0fe478SBruce M Simpson 				return;
281a90e161bSBill Fenner 			}
2825b0fe478SBruce M Simpson 
283a90e161bSBill Fenner 			i = 0;
284a90e161bSBill Fenner 			while (colon[0] != '\0' && colon[1]!='\0') {
285a90e161bSBill Fenner 				espsecret_key[i] = hex2byte(colon);
286a90e161bSBill Fenner 				colon += 2;
287a90e161bSBill Fenner 				i++;
288a90e161bSBill Fenner 			}
2895b0fe478SBruce M Simpson 
2905b0fe478SBruce M Simpson 			memcpy(sa1.secret, espsecret_key, i);
2915b0fe478SBruce M Simpson 			sa1.secretlen = i;
292a90e161bSBill Fenner 		} else {
2935b0fe478SBruce M Simpson 			i = strlen(colon);
2945b0fe478SBruce M Simpson 
2955b0fe478SBruce M Simpson 			if (i < sizeof(sa1.secret)) {
2965b0fe478SBruce M Simpson 				memcpy(sa1.secret, colon, i);
2975b0fe478SBruce M Simpson 				sa1.secretlen = i;
2985b0fe478SBruce M Simpson 			} else {
2995b0fe478SBruce M Simpson 				memcpy(sa1.secret, colon, sizeof(sa1.secret));
3005b0fe478SBruce M Simpson 				sa1.secretlen = sizeof(sa1.secret);
3015b0fe478SBruce M Simpson 			}
302a90e161bSBill Fenner 		}
303a90e161bSBill Fenner 	}
304a90e161bSBill Fenner 
3055b0fe478SBruce M Simpson 	esp_print_addsa(&sa1, sa_def);
3065b0fe478SBruce M Simpson }
3075b0fe478SBruce M Simpson 
3085b0fe478SBruce M Simpson static void esp_print_decodesecret(void)
309b0453382SBill Fenner {
3105b0fe478SBruce M Simpson 	char *line;
3115b0fe478SBruce M Simpson 	char *p;
3125b0fe478SBruce M Simpson 
3135b0fe478SBruce M Simpson 	p = espsecret;
3145b0fe478SBruce M Simpson 
3155b0fe478SBruce M Simpson 	while (espsecret && espsecret[0] != '\0') {
3165b0fe478SBruce M Simpson 		/* pick out the first line or first thing until a comma */
3175b0fe478SBruce M Simpson 		if ((line = strsep(&espsecret, "\n,")) == NULL) {
3185b0fe478SBruce M Simpson 			line = espsecret;
3195b0fe478SBruce M Simpson 			espsecret = NULL;
3205b0fe478SBruce M Simpson 		}
3215b0fe478SBruce M Simpson 
3225b0fe478SBruce M Simpson 		esp_print_decode_onesecret(line);
3235b0fe478SBruce M Simpson 	}
3245b0fe478SBruce M Simpson }
3255b0fe478SBruce M Simpson 
3265b0fe478SBruce M Simpson static void esp_init(void)
3275b0fe478SBruce M Simpson {
3285b0fe478SBruce M Simpson 
3295b0fe478SBruce M Simpson 	OpenSSL_add_all_algorithms();
3305b0fe478SBruce M Simpson 	EVP_add_cipher_alias(SN_des_ede3_cbc, "3des");
3315b0fe478SBruce M Simpson }
3325b0fe478SBruce M Simpson #endif
3335b0fe478SBruce M Simpson 
3345b0fe478SBruce M Simpson int
3355b0fe478SBruce M Simpson esp_print(const u_char *bp, const u_char *bp2
3365b0fe478SBruce M Simpson #ifndef HAVE_LIBCRYPTO
3375b0fe478SBruce M Simpson 	_U_
3385b0fe478SBruce M Simpson #endif
3395b0fe478SBruce M Simpson 	,
3405b0fe478SBruce M Simpson 	int *nhdr
3415b0fe478SBruce M Simpson #ifndef HAVE_LIBCRYPTO
3425b0fe478SBruce M Simpson 	_U_
3435b0fe478SBruce M Simpson #endif
3445b0fe478SBruce M Simpson 	,
3455b0fe478SBruce M Simpson 	int *padlen
3465b0fe478SBruce M Simpson #ifndef HAVE_LIBCRYPTO
3475b0fe478SBruce M Simpson 	_U_
3485b0fe478SBruce M Simpson #endif
3495b0fe478SBruce M Simpson 	)
3505b0fe478SBruce M Simpson {
3515b0fe478SBruce M Simpson 	register const struct newesp *esp;
352b0453382SBill Fenner 	register const u_char *ep;
3535b0fe478SBruce M Simpson #ifdef HAVE_LIBCRYPTO
3545b0fe478SBruce M Simpson 	struct ip *ip;
3555b0fe478SBruce M Simpson 	struct sa_list *sa = NULL;
3565b0fe478SBruce M Simpson 	int espsecret_keylen;
357b0453382SBill Fenner #ifdef INET6
358b0453382SBill Fenner 	struct ip6_hdr *ip6 = NULL;
359b0453382SBill Fenner #endif
360b0453382SBill Fenner 	int advance;
361b0453382SBill Fenner 	int len;
362a90e161bSBill Fenner 	char *secret;
363b0453382SBill Fenner 	int ivlen = 0;
364b0453382SBill Fenner 	u_char *ivoff;
3655b0fe478SBruce M Simpson 	const u_char *p;
3665b0fe478SBruce M Simpson 	EVP_CIPHER_CTX ctx;
3675b0fe478SBruce M Simpson 	int blocksz;
3685b0fe478SBruce M Simpson 	static int initialized = 0;
3695b0fe478SBruce M Simpson #endif
370b0453382SBill Fenner 
3715b0fe478SBruce M Simpson 	esp = (struct newesp *)bp;
3725b0fe478SBruce M Simpson 
3735b0fe478SBruce M Simpson #ifdef HAVE_LIBCRYPTO
374a90e161bSBill Fenner 	secret = NULL;
3755b0fe478SBruce M Simpson 	advance = 0;
3765b0fe478SBruce M Simpson 
3775b0fe478SBruce M Simpson 	if (!initialized) {
3785b0fe478SBruce M Simpson 		esp_init();
3795b0fe478SBruce M Simpson 		initialized = 1;
3805b0fe478SBruce M Simpson 	}
3815b0fe478SBruce M Simpson #endif
382a90e161bSBill Fenner 
383a90e161bSBill Fenner #if 0
384a90e161bSBill Fenner 	/* keep secret out of a register */
385a90e161bSBill Fenner 	p = (u_char *)&secret;
386a90e161bSBill Fenner #endif
387b0453382SBill Fenner 
388685295f4SBill Fenner 	/* 'ep' points to the end of available data. */
389b0453382SBill Fenner 	ep = snapend;
390b0453382SBill Fenner 
3915b0fe478SBruce M Simpson 	if ((u_char *)(esp + 1) >= ep) {
392b0453382SBill Fenner 		fputs("[|ESP]", stdout);
393b0453382SBill Fenner 		goto fail;
394b0453382SBill Fenner 	}
3955b0fe478SBruce M Simpson 	printf("ESP(spi=0x%08x", EXTRACT_32BITS(&esp->esp_spi));
3965b0fe478SBruce M Simpson 	printf(",seq=0x%x", EXTRACT_32BITS(&esp->esp_seq));
397b0453382SBill Fenner 	printf(")");
398b0453382SBill Fenner 
3995b0fe478SBruce M Simpson #ifndef HAVE_LIBCRYPTO
4005b0fe478SBruce M Simpson 	goto fail;
4015b0fe478SBruce M Simpson #else
4025b0fe478SBruce M Simpson 	/* initiailize SAs */
4035b0fe478SBruce M Simpson 	if (sa_list_head == NULL) {
404b0453382SBill Fenner 		if (!espsecret)
405b0453382SBill Fenner 			goto fail;
406b0453382SBill Fenner 
407a90e161bSBill Fenner 		esp_print_decodesecret();
408a90e161bSBill Fenner 	}
4095b0fe478SBruce M Simpson 
4105b0fe478SBruce M Simpson 	if (sa_list_head == NULL)
411a90e161bSBill Fenner 		goto fail;
412b0453382SBill Fenner 
413b0453382SBill Fenner 	ip = (struct ip *)bp2;
414685295f4SBill Fenner 	switch (IP_V(ip)) {
415b0453382SBill Fenner #ifdef INET6
416b0453382SBill Fenner 	case 6:
417b0453382SBill Fenner 		ip6 = (struct ip6_hdr *)bp2;
418b0453382SBill Fenner 		/* we do not attempt to decrypt jumbograms */
4195b0fe478SBruce M Simpson 		if (!EXTRACT_16BITS(&ip6->ip6_plen))
420b0453382SBill Fenner 			goto fail;
421b0453382SBill Fenner 		/* if we can't get nexthdr, we do not need to decrypt it */
4225b0fe478SBruce M Simpson 		len = sizeof(struct ip6_hdr) + EXTRACT_16BITS(&ip6->ip6_plen);
4235b0fe478SBruce M Simpson 
4245b0fe478SBruce M Simpson 		/* see if we can find the SA, and if so, decode it */
4255b0fe478SBruce M Simpson 		for (sa = sa_list_head; sa != NULL; sa = sa->next) {
4265b0fe478SBruce M Simpson 			struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&sa->daddr;
4275b0fe478SBruce M Simpson 			if (sa->spi == ntohl(esp->esp_spi) &&
4285b0fe478SBruce M Simpson 			    sin6->sin6_family == AF_INET6 &&
4295b0fe478SBruce M Simpson 			    memcmp(&sin6->sin6_addr, &ip6->ip6_dst,
4305b0fe478SBruce M Simpson 				   sizeof(struct in6_addr)) == 0) {
4315b0fe478SBruce M Simpson 				break;
4325b0fe478SBruce M Simpson 			}
4335b0fe478SBruce M Simpson 		}
434b0453382SBill Fenner 		break;
435b0453382SBill Fenner #endif /*INET6*/
436b0453382SBill Fenner 	case 4:
437a90e161bSBill Fenner 		/* nexthdr & padding are in the last fragment */
4385b0fe478SBruce M Simpson 		if (EXTRACT_16BITS(&ip->ip_off) & IP_MF)
439a90e161bSBill Fenner 			goto fail;
4405b0fe478SBruce M Simpson 		len = EXTRACT_16BITS(&ip->ip_len);
4415b0fe478SBruce M Simpson 
4425b0fe478SBruce M Simpson 		/* see if we can find the SA, and if so, decode it */
4435b0fe478SBruce M Simpson 		for (sa = sa_list_head; sa != NULL; sa = sa->next) {
4445b0fe478SBruce M Simpson 			struct sockaddr_in *sin = (struct sockaddr_in *)&sa->daddr;
4455b0fe478SBruce M Simpson 			if (sa->spi == ntohl(esp->esp_spi) &&
4465b0fe478SBruce M Simpson 			    sin->sin_family == AF_INET &&
4475b0fe478SBruce M Simpson 			    sin->sin_addr.s_addr == ip->ip_dst.s_addr) {
4485b0fe478SBruce M Simpson 				break;
4495b0fe478SBruce M Simpson 			}
4505b0fe478SBruce M Simpson 		}
451b0453382SBill Fenner 		break;
452b0453382SBill Fenner 	default:
453b0453382SBill Fenner 		goto fail;
454b0453382SBill Fenner 	}
455b0453382SBill Fenner 
4565b0fe478SBruce M Simpson 	/* if we didn't find the specific one, then look for
4575b0fe478SBruce M Simpson 	 * an unspecified one.
4585b0fe478SBruce M Simpson 	 */
4595b0fe478SBruce M Simpson 	if (sa == NULL)
4605b0fe478SBruce M Simpson 		sa = sa_default;
4615b0fe478SBruce M Simpson 
4625b0fe478SBruce M Simpson 	/* if not found fail */
4635b0fe478SBruce M Simpson 	if (sa == NULL)
4645b0fe478SBruce M Simpson 		goto fail;
4655b0fe478SBruce M Simpson 
466b0453382SBill Fenner 	/* if we can't get nexthdr, we do not need to decrypt it */
467b0453382SBill Fenner 	if (ep - bp2 < len)
468b0453382SBill Fenner 		goto fail;
4695b0fe478SBruce M Simpson 	if (ep - bp2 > len) {
4705b0fe478SBruce M Simpson 		/* FCS included at end of frame (NetBSD 1.6 or later) */
4715b0fe478SBruce M Simpson 		ep = bp2 + len;
472b0453382SBill Fenner 	}
473b0453382SBill Fenner 
4745b0fe478SBruce M Simpson 	ivoff = (u_char *)(esp + 1) + 0;
4755b0fe478SBruce M Simpson 	ivlen = sa->ivlen;
4765b0fe478SBruce M Simpson 	secret = sa->secret;
4775b0fe478SBruce M Simpson 	espsecret_keylen = sa->secretlen;
478b0453382SBill Fenner 
4795b0fe478SBruce M Simpson 	if (sa->evp) {
4805b0fe478SBruce M Simpson 		memset(&ctx, 0, sizeof(ctx));
4815b0fe478SBruce M Simpson 		if (EVP_CipherInit(&ctx, sa->evp, secret, NULL, 0) < 0)
4825b0fe478SBruce M Simpson 			printf("espkey init failed");
4835b0fe478SBruce M Simpson 
4845b0fe478SBruce M Simpson 		blocksz = EVP_CIPHER_CTX_block_size(&ctx);
4855b0fe478SBruce M Simpson 
4865b0fe478SBruce M Simpson 		p = ivoff;
4875b0fe478SBruce M Simpson 		EVP_CipherInit(&ctx, NULL, NULL, p, 0);
4885b0fe478SBruce M Simpson 		EVP_Cipher(&ctx, p + ivlen, p + ivlen, ep - (p + ivlen));
489b0453382SBill Fenner 		advance = ivoff - (u_char *)esp + ivlen;
4905b0fe478SBruce M Simpson 	} else
4915b0fe478SBruce M Simpson 		advance = sizeof(struct newesp);
492b0453382SBill Fenner 
4935b0fe478SBruce M Simpson 	ep = ep - sa->authlen;
494b0453382SBill Fenner 	/* sanity check for pad length */
495b0453382SBill Fenner 	if (ep - bp < *(ep - 2))
496b0453382SBill Fenner 		goto fail;
497b0453382SBill Fenner 
498a90e161bSBill Fenner 	if (padlen)
499a90e161bSBill Fenner 		*padlen = *(ep - 2) + 2;
500a90e161bSBill Fenner 
501b0453382SBill Fenner 	if (nhdr)
502b0453382SBill Fenner 		*nhdr = *(ep - 1);
503b0453382SBill Fenner 
504b0453382SBill Fenner 	printf(": ");
505b0453382SBill Fenner 	return advance;
5065b0fe478SBruce M Simpson #endif
507b0453382SBill Fenner 
508b0453382SBill Fenner fail:
5095b0fe478SBruce M Simpson 	return -1;
510b0453382SBill Fenner }
511