xref: /freebsd/contrib/tcpdump/print-esp.c (revision f4d0c64a1ddc84cf60d453e0f1ea0a70bea248e3)
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_ =
26f4d0c64aSSam Leffler     "@(#) $Header: /tcpdump/master/tcpdump/print-esp.c,v 1.55.2.1 2005/04/21 06:44:57 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 
531de50e9fSSam Leffler #include "netdissect.h"
54b0453382SBill Fenner #include "addrtoname.h"
555b0fe478SBruce M Simpson #include "extract.h"
56b0453382SBill Fenner 
575b0fe478SBruce M Simpson #ifndef HAVE_SOCKADDR_STORAGE
585b0fe478SBruce M Simpson #ifdef INET6
595b0fe478SBruce M Simpson struct sockaddr_storage {
605b0fe478SBruce M Simpson 	union {
615b0fe478SBruce M Simpson 		struct sockaddr_in sin;
625b0fe478SBruce M Simpson 		struct sockaddr_in6 sin6;
635b0fe478SBruce M Simpson 	} un;
645b0fe478SBruce M Simpson };
655b0fe478SBruce M Simpson #else
665b0fe478SBruce M Simpson #define sockaddr_storage sockaddr
675b0fe478SBruce M Simpson #endif
685b0fe478SBruce M Simpson #endif /* HAVE_SOCKADDR_STORAGE */
69a90e161bSBill Fenner 
705b0fe478SBruce M Simpson #ifdef HAVE_LIBCRYPTO
715b0fe478SBruce M Simpson struct sa_list {
725b0fe478SBruce M Simpson 	struct sa_list	*next;
735b0fe478SBruce M Simpson 	struct sockaddr_storage daddr;
745b0fe478SBruce M Simpson 	u_int32_t	spi;
755b0fe478SBruce M Simpson 	const EVP_CIPHER *evp;
76a90e161bSBill Fenner 	int		ivlen;
77a90e161bSBill Fenner 	int		authlen;
78f4d0c64aSSam Leffler 	u_char		secret[256];  /* is that big enough for all secrets? */
795b0fe478SBruce M Simpson 	int		secretlen;
80a90e161bSBill Fenner };
81a90e161bSBill Fenner 
821de50e9fSSam Leffler static void esp_print_addsa(netdissect_options *ndo,
831de50e9fSSam Leffler 			    struct sa_list *sa, int sa_def)
845b0fe478SBruce M Simpson {
855b0fe478SBruce M Simpson 	/* copy the "sa" */
865b0fe478SBruce M Simpson 
875b0fe478SBruce M Simpson 	struct sa_list *nsa;
885b0fe478SBruce M Simpson 
895b0fe478SBruce M Simpson 	nsa = (struct sa_list *)malloc(sizeof(struct sa_list));
905b0fe478SBruce M Simpson 	if (nsa == NULL)
911de50e9fSSam Leffler 		(*ndo->ndo_error)(ndo, "ran out of memory to allocate sa structure");
925b0fe478SBruce M Simpson 
935b0fe478SBruce M Simpson 	*nsa = *sa;
945b0fe478SBruce M Simpson 
955b0fe478SBruce M Simpson 	if (sa_def)
961de50e9fSSam Leffler 		ndo->ndo_sa_default = nsa;
975b0fe478SBruce M Simpson 
981de50e9fSSam Leffler 	nsa->next = ndo->ndo_sa_list_head;
991de50e9fSSam Leffler 	ndo->ndo_sa_list_head = nsa;
1005b0fe478SBruce M Simpson }
1015b0fe478SBruce M Simpson 
102a90e161bSBill Fenner 
103f4d0c64aSSam Leffler static u_int hexdigit(netdissect_options *ndo, char hex)
104a90e161bSBill Fenner {
1055b0fe478SBruce M Simpson 	if (hex >= '0' && hex <= '9')
106a90e161bSBill Fenner 		return (hex - '0');
1075b0fe478SBruce M Simpson 	else if (hex >= 'A' && hex <= 'F')
108a90e161bSBill Fenner 		return (hex - 'A' + 10);
1095b0fe478SBruce M Simpson 	else if (hex >= 'a' && hex <= 'f')
110a90e161bSBill Fenner 		return (hex - 'a' + 10);
1115b0fe478SBruce M Simpson 	else {
1121de50e9fSSam Leffler 		(*ndo->ndo_error)(ndo, "invalid hex digit %c in espsecret\n", hex);
113a90e161bSBill Fenner 		return 0;
114a90e161bSBill Fenner 	}
115a90e161bSBill Fenner }
116a90e161bSBill Fenner 
117f4d0c64aSSam Leffler static u_int hex2byte(netdissect_options *ndo, char *hexstring)
118a90e161bSBill Fenner {
119f4d0c64aSSam Leffler 	u_int byte;
120a90e161bSBill Fenner 
1211de50e9fSSam Leffler 	byte = (hexdigit(ndo, hexstring[0]) << 4) + hexdigit(ndo, hexstring[1]);
122a90e161bSBill Fenner 	return byte;
123a90e161bSBill Fenner }
124a90e161bSBill Fenner 
1255b0fe478SBruce M Simpson /*
1265b0fe478SBruce M Simpson  * decode the form:    SPINUM@IP <tab> ALGONAME:0xsecret
1275b0fe478SBruce M Simpson  *
1285b0fe478SBruce M Simpson  * special form: file /name
1295b0fe478SBruce M Simpson  * causes us to go read from this file instead.
1305b0fe478SBruce M Simpson  *
1315b0fe478SBruce M Simpson  */
1321de50e9fSSam Leffler static void esp_print_decode_onesecret(netdissect_options *ndo, char *line)
133a90e161bSBill Fenner {
1345b0fe478SBruce M Simpson 	struct sa_list sa1;
1355b0fe478SBruce M Simpson 	int sa_def;
136a90e161bSBill Fenner 
1375b0fe478SBruce M Simpson 	char *spikey;
1385b0fe478SBruce M Simpson 	char *decode;
1395b0fe478SBruce M Simpson 
1405b0fe478SBruce M Simpson 	spikey = strsep(&line, " \t");
1415b0fe478SBruce M Simpson 	sa_def = 0;
1425b0fe478SBruce M Simpson 	memset(&sa1, 0, sizeof(struct sa_list));
1435b0fe478SBruce M Simpson 
1445b0fe478SBruce M Simpson 	/* if there is only one token, then it is an algo:key token */
1455b0fe478SBruce M Simpson 	if (line == NULL) {
1465b0fe478SBruce M Simpson 		decode = spikey;
1475b0fe478SBruce M Simpson 		spikey = NULL;
1485b0fe478SBruce M Simpson 		/* memset(&sa1.daddr, 0, sizeof(sa1.daddr)); */
1495b0fe478SBruce M Simpson 		/* sa1.spi = 0; */
1505b0fe478SBruce M Simpson 		sa_def    = 1;
1515b0fe478SBruce M Simpson 	} else
1525b0fe478SBruce M Simpson 		decode = line;
1535b0fe478SBruce M Simpson 
1545b0fe478SBruce M Simpson 	if (spikey && strcasecmp(spikey, "file") == 0) {
1555b0fe478SBruce M Simpson 		/* open file and read it */
1565b0fe478SBruce M Simpson 		FILE *secretfile;
1575b0fe478SBruce M Simpson 		char  fileline[1024];
1585b0fe478SBruce M Simpson 		char  *nl;
1595b0fe478SBruce M Simpson 
1605b0fe478SBruce M Simpson 		secretfile = fopen(line, FOPEN_READ_TXT);
1615b0fe478SBruce M Simpson 		if (secretfile == NULL) {
1625b0fe478SBruce M Simpson 			perror(line);
1635b0fe478SBruce M Simpson 			exit(3);
1645b0fe478SBruce M Simpson 		}
1655b0fe478SBruce M Simpson 
1665b0fe478SBruce M Simpson 		while (fgets(fileline, sizeof(fileline)-1, secretfile) != NULL) {
1675b0fe478SBruce M Simpson 			/* remove newline from the line */
1685b0fe478SBruce M Simpson 			nl = strchr(fileline, '\n');
1695b0fe478SBruce M Simpson 			if (nl)
1705b0fe478SBruce M Simpson 				*nl = '\0';
1715b0fe478SBruce M Simpson 			if (fileline[0] == '#') continue;
1725b0fe478SBruce M Simpson 			if (fileline[0] == '\0') continue;
1735b0fe478SBruce M Simpson 
1741de50e9fSSam Leffler 			esp_print_decode_onesecret(ndo, fileline);
1755b0fe478SBruce M Simpson 		}
1765b0fe478SBruce M Simpson 		fclose(secretfile);
1775b0fe478SBruce M Simpson 
178a90e161bSBill Fenner 		return;
179a90e161bSBill Fenner 	}
180a90e161bSBill Fenner 
1815b0fe478SBruce M Simpson 	if (spikey) {
1825b0fe478SBruce M Simpson 		char *spistr, *foo;
1835b0fe478SBruce M Simpson 		u_int32_t spino;
1845b0fe478SBruce M Simpson 		struct sockaddr_in *sin;
1855b0fe478SBruce M Simpson #ifdef INET6
1865b0fe478SBruce M Simpson 		struct sockaddr_in6 *sin6;
1875b0fe478SBruce M Simpson #endif
1885b0fe478SBruce M Simpson 
1895b0fe478SBruce M Simpson 		spistr = strsep(&spikey, "@");
1905b0fe478SBruce M Simpson 
1915b0fe478SBruce M Simpson 		spino = strtoul(spistr, &foo, 0);
1925b0fe478SBruce M Simpson 		if (spistr == foo || !spikey) {
1931de50e9fSSam Leffler 			(*ndo->ndo_warning)(ndo, "print_esp: failed to decode spi# %s\n", foo);
194a90e161bSBill Fenner 			return;
195a90e161bSBill Fenner 		}
196a90e161bSBill Fenner 
1975b0fe478SBruce M Simpson 		sa1.spi = spino;
1985b0fe478SBruce M Simpson 
1995b0fe478SBruce M Simpson 		sin = (struct sockaddr_in *)&sa1.daddr;
2005b0fe478SBruce M Simpson #ifdef INET6
2015b0fe478SBruce M Simpson 		sin6 = (struct sockaddr_in6 *)&sa1.daddr;
2025b0fe478SBruce M Simpson 		if (inet_pton(AF_INET6, spikey, &sin6->sin6_addr) == 1) {
2035b0fe478SBruce M Simpson #ifdef HAVE_SOCKADDR_SA_LEN
2045b0fe478SBruce M Simpson 			sin6->sin6_len = sizeof(struct sockaddr_in6);
2055b0fe478SBruce M Simpson #endif
2065b0fe478SBruce M Simpson 			sin6->sin6_family = AF_INET6;
2075b0fe478SBruce M Simpson 		} else
2085b0fe478SBruce M Simpson #endif
2095b0fe478SBruce M Simpson 		if (inet_pton(AF_INET, spikey, &sin->sin_addr) == 1) {
2105b0fe478SBruce M Simpson #ifdef HAVE_SOCKADDR_SA_LEN
2115b0fe478SBruce M Simpson 			sin->sin_len = sizeof(struct sockaddr_in);
2125b0fe478SBruce M Simpson #endif
2135b0fe478SBruce M Simpson 			sin->sin_family = AF_INET;
2145b0fe478SBruce M Simpson 		} else {
2151de50e9fSSam Leffler 			(*ndo->ndo_warning)(ndo, "print_esp: can not decode IP# %s\n", spikey);
2165b0fe478SBruce M Simpson 			return;
2175b0fe478SBruce M Simpson 		}
2185b0fe478SBruce M Simpson 	}
2195b0fe478SBruce M Simpson 
2205b0fe478SBruce M Simpson 	if (decode) {
2215b0fe478SBruce M Simpson 		char *colon, *p;
222f4d0c64aSSam Leffler 		u_char espsecret_key[256];
2235b0fe478SBruce M Simpson 		int len;
2245b0fe478SBruce M Simpson 		size_t i;
2255b0fe478SBruce M Simpson 		const EVP_CIPHER *evp;
2265b0fe478SBruce M Simpson 		int authlen = 0;
2275b0fe478SBruce M Simpson 
2285b0fe478SBruce M Simpson 		/* skip any blank spaces */
2295b0fe478SBruce M Simpson 		while (isspace((unsigned char)*decode))
2305b0fe478SBruce M Simpson 			decode++;
2315b0fe478SBruce M Simpson 
2325b0fe478SBruce M Simpson 		colon = strchr(decode, ':');
233a90e161bSBill Fenner 		if (colon == NULL) {
2341de50e9fSSam Leffler 			(*ndo->ndo_warning)(ndo, "failed to decode espsecret: %s\n", decode);
235a90e161bSBill Fenner 			return;
236a90e161bSBill Fenner 		}
2375b0fe478SBruce M Simpson 		*colon = '\0';
2385b0fe478SBruce M Simpson 
2395b0fe478SBruce M Simpson 		len = colon - decode;
2405b0fe478SBruce M Simpson 		if (strlen(decode) > strlen("-hmac96") &&
2415b0fe478SBruce M Simpson 		    !strcmp(decode + strlen(decode) - strlen("-hmac96"),
2425b0fe478SBruce M Simpson 		    "-hmac96")) {
2435b0fe478SBruce M Simpson 			p = strstr(decode, "-hmac96");
2445b0fe478SBruce M Simpson 			*p = '\0';
2455b0fe478SBruce M Simpson 			authlen = 12;
2465b0fe478SBruce M Simpson 		}
2475b0fe478SBruce M Simpson 		if (strlen(decode) > strlen("-cbc") &&
2485b0fe478SBruce M Simpson 		    !strcmp(decode + strlen(decode) - strlen("-cbc"), "-cbc")) {
2495b0fe478SBruce M Simpson 			p = strstr(decode, "-cbc");
2505b0fe478SBruce M Simpson 			*p = '\0';
2515b0fe478SBruce M Simpson 		}
2525b0fe478SBruce M Simpson 		evp = EVP_get_cipherbyname(decode);
2535b0fe478SBruce M Simpson 		if (!evp) {
2541de50e9fSSam Leffler 			(*ndo->ndo_warning)(ndo, "failed to find cipher algo %s\n", decode);
2555b0fe478SBruce M Simpson 			sa1.evp = NULL;
2565b0fe478SBruce M Simpson 			sa1.authlen = 0;
2575b0fe478SBruce M Simpson 			sa1.ivlen = 0;
2585b0fe478SBruce M Simpson 			return;
2595b0fe478SBruce M Simpson 		}
2605b0fe478SBruce M Simpson 
2615b0fe478SBruce M Simpson 		sa1.evp = evp;
2625b0fe478SBruce M Simpson 		sa1.authlen = authlen;
2631de50e9fSSam Leffler 		sa1.ivlen = EVP_CIPHER_iv_length(evp);
264a90e161bSBill Fenner 
265a90e161bSBill Fenner 		colon++;
266a90e161bSBill Fenner 		if (colon[0] == '0' && colon[1] == 'x') {
267a90e161bSBill Fenner 			/* decode some hex! */
268a90e161bSBill Fenner 			colon += 2;
269a90e161bSBill Fenner 			len = strlen(colon) / 2;
2705b0fe478SBruce M Simpson 
2715b0fe478SBruce M Simpson 			if (len > 256) {
2721de50e9fSSam Leffler 				(*ndo->ndo_warning)(ndo, "secret is too big: %d\n", len);
2735b0fe478SBruce M Simpson 				return;
274a90e161bSBill Fenner 			}
2755b0fe478SBruce M Simpson 
276a90e161bSBill Fenner 			i = 0;
277a90e161bSBill Fenner 			while (colon[0] != '\0' && colon[1]!='\0') {
2781de50e9fSSam Leffler 				espsecret_key[i] = hex2byte(ndo, colon);
279a90e161bSBill Fenner 				colon += 2;
280a90e161bSBill Fenner 				i++;
281a90e161bSBill Fenner 			}
2825b0fe478SBruce M Simpson 
2835b0fe478SBruce M Simpson 			memcpy(sa1.secret, espsecret_key, i);
2845b0fe478SBruce M Simpson 			sa1.secretlen = i;
285a90e161bSBill Fenner 		} else {
2865b0fe478SBruce M Simpson 			i = strlen(colon);
2875b0fe478SBruce M Simpson 
2885b0fe478SBruce M Simpson 			if (i < sizeof(sa1.secret)) {
2895b0fe478SBruce M Simpson 				memcpy(sa1.secret, colon, i);
2905b0fe478SBruce M Simpson 				sa1.secretlen = i;
2915b0fe478SBruce M Simpson 			} else {
2925b0fe478SBruce M Simpson 				memcpy(sa1.secret, colon, sizeof(sa1.secret));
2935b0fe478SBruce M Simpson 				sa1.secretlen = sizeof(sa1.secret);
2945b0fe478SBruce M Simpson 			}
295a90e161bSBill Fenner 		}
296a90e161bSBill Fenner 	}
297a90e161bSBill Fenner 
2981de50e9fSSam Leffler 	esp_print_addsa(ndo, &sa1, sa_def);
2995b0fe478SBruce M Simpson }
3005b0fe478SBruce M Simpson 
3011de50e9fSSam Leffler static void esp_print_decodesecret(netdissect_options *ndo)
302b0453382SBill Fenner {
3035b0fe478SBruce M Simpson 	char *line;
3045b0fe478SBruce M Simpson 	char *p;
3055b0fe478SBruce M Simpson 
3061de50e9fSSam Leffler 	p = ndo->ndo_espsecret;
3075b0fe478SBruce M Simpson 
3081de50e9fSSam Leffler 	while (ndo->ndo_espsecret && ndo->ndo_espsecret[0] != '\0') {
3095b0fe478SBruce M Simpson 		/* pick out the first line or first thing until a comma */
3101de50e9fSSam Leffler 		if ((line = strsep(&ndo->ndo_espsecret, "\n,")) == NULL) {
3111de50e9fSSam Leffler 			line = ndo->ndo_espsecret;
3121de50e9fSSam Leffler 			ndo->ndo_espsecret = NULL;
3135b0fe478SBruce M Simpson 		}
3145b0fe478SBruce M Simpson 
3151de50e9fSSam Leffler 		esp_print_decode_onesecret(ndo, line);
3165b0fe478SBruce M Simpson 	}
3175b0fe478SBruce M Simpson }
3185b0fe478SBruce M Simpson 
3191de50e9fSSam Leffler static void esp_init(netdissect_options *ndo _U_)
3205b0fe478SBruce M Simpson {
3215b0fe478SBruce M Simpson 
3225b0fe478SBruce M Simpson 	OpenSSL_add_all_algorithms();
3235b0fe478SBruce M Simpson 	EVP_add_cipher_alias(SN_des_ede3_cbc, "3des");
3245b0fe478SBruce M Simpson }
3255b0fe478SBruce M Simpson #endif
3265b0fe478SBruce M Simpson 
3275b0fe478SBruce M Simpson int
3281de50e9fSSam Leffler esp_print(netdissect_options *ndo,
3291de50e9fSSam Leffler 	  const u_char *bp, const int length, const u_char *bp2
3305b0fe478SBruce M Simpson #ifndef HAVE_LIBCRYPTO
3315b0fe478SBruce M Simpson 	_U_
3325b0fe478SBruce M Simpson #endif
3335b0fe478SBruce M Simpson 	,
3345b0fe478SBruce M Simpson 	int *nhdr
3355b0fe478SBruce M Simpson #ifndef HAVE_LIBCRYPTO
3365b0fe478SBruce M Simpson 	_U_
3375b0fe478SBruce M Simpson #endif
3385b0fe478SBruce M Simpson 	,
3395b0fe478SBruce M Simpson 	int *padlen
3405b0fe478SBruce M Simpson #ifndef HAVE_LIBCRYPTO
3415b0fe478SBruce M Simpson 	_U_
3425b0fe478SBruce M Simpson #endif
3435b0fe478SBruce M Simpson 	)
3445b0fe478SBruce M Simpson {
3455b0fe478SBruce M Simpson 	register const struct newesp *esp;
346b0453382SBill Fenner 	register const u_char *ep;
3475b0fe478SBruce M Simpson #ifdef HAVE_LIBCRYPTO
3485b0fe478SBruce M Simpson 	struct ip *ip;
3495b0fe478SBruce M Simpson 	struct sa_list *sa = NULL;
3505b0fe478SBruce M Simpson 	int espsecret_keylen;
351b0453382SBill Fenner #ifdef INET6
352b0453382SBill Fenner 	struct ip6_hdr *ip6 = NULL;
353b0453382SBill Fenner #endif
354b0453382SBill Fenner 	int advance;
355b0453382SBill Fenner 	int len;
356f4d0c64aSSam Leffler 	u_char *secret;
357b0453382SBill Fenner 	int ivlen = 0;
358b0453382SBill Fenner 	u_char *ivoff;
3591de50e9fSSam Leffler 	u_char *p;
3605b0fe478SBruce M Simpson 	EVP_CIPHER_CTX ctx;
3615b0fe478SBruce M Simpson 	int blocksz;
3625b0fe478SBruce M Simpson 	static int initialized = 0;
3635b0fe478SBruce M Simpson #endif
364b0453382SBill Fenner 
3655b0fe478SBruce M Simpson 	esp = (struct newesp *)bp;
3665b0fe478SBruce M Simpson 
3675b0fe478SBruce M Simpson #ifdef HAVE_LIBCRYPTO
368a90e161bSBill Fenner 	secret = NULL;
3695b0fe478SBruce M Simpson 	advance = 0;
3705b0fe478SBruce M Simpson 
3715b0fe478SBruce M Simpson 	if (!initialized) {
3721de50e9fSSam Leffler 		esp_init(ndo);
3735b0fe478SBruce M Simpson 		initialized = 1;
3745b0fe478SBruce M Simpson 	}
3755b0fe478SBruce M Simpson #endif
376a90e161bSBill Fenner 
377a90e161bSBill Fenner #if 0
378a90e161bSBill Fenner 	/* keep secret out of a register */
379a90e161bSBill Fenner 	p = (u_char *)&secret;
380a90e161bSBill Fenner #endif
381b0453382SBill Fenner 
382685295f4SBill Fenner 	/* 'ep' points to the end of available data. */
3831de50e9fSSam Leffler 	ep = ndo->ndo_snapend;
384b0453382SBill Fenner 
3855b0fe478SBruce M Simpson 	if ((u_char *)(esp + 1) >= ep) {
386b0453382SBill Fenner 		fputs("[|ESP]", stdout);
387b0453382SBill Fenner 		goto fail;
388b0453382SBill Fenner 	}
3891de50e9fSSam Leffler 	(*ndo->ndo_printf)(ndo, "ESP(spi=0x%08x", EXTRACT_32BITS(&esp->esp_spi));
3901de50e9fSSam Leffler 	(*ndo->ndo_printf)(ndo, ",seq=0x%x)", EXTRACT_32BITS(&esp->esp_seq));
3911de50e9fSSam Leffler         (*ndo->ndo_printf)(ndo, ", length %u", length);
392b0453382SBill Fenner 
3935b0fe478SBruce M Simpson #ifndef HAVE_LIBCRYPTO
3945b0fe478SBruce M Simpson 	goto fail;
3955b0fe478SBruce M Simpson #else
3965b0fe478SBruce M Simpson 	/* initiailize SAs */
3971de50e9fSSam Leffler 	if (ndo->ndo_sa_list_head == NULL) {
3981de50e9fSSam Leffler 		if (!ndo->ndo_espsecret)
399b0453382SBill Fenner 			goto fail;
400b0453382SBill Fenner 
4011de50e9fSSam Leffler 		esp_print_decodesecret(ndo);
402a90e161bSBill Fenner 	}
4035b0fe478SBruce M Simpson 
4041de50e9fSSam Leffler 	if (ndo->ndo_sa_list_head == NULL)
405a90e161bSBill Fenner 		goto fail;
406b0453382SBill Fenner 
407b0453382SBill Fenner 	ip = (struct ip *)bp2;
408685295f4SBill Fenner 	switch (IP_V(ip)) {
409b0453382SBill Fenner #ifdef INET6
410b0453382SBill Fenner 	case 6:
411b0453382SBill Fenner 		ip6 = (struct ip6_hdr *)bp2;
412b0453382SBill Fenner 		/* we do not attempt to decrypt jumbograms */
4135b0fe478SBruce M Simpson 		if (!EXTRACT_16BITS(&ip6->ip6_plen))
414b0453382SBill Fenner 			goto fail;
415b0453382SBill Fenner 		/* if we can't get nexthdr, we do not need to decrypt it */
4165b0fe478SBruce M Simpson 		len = sizeof(struct ip6_hdr) + EXTRACT_16BITS(&ip6->ip6_plen);
4175b0fe478SBruce M Simpson 
4185b0fe478SBruce M Simpson 		/* see if we can find the SA, and if so, decode it */
4191de50e9fSSam Leffler 		for (sa = ndo->ndo_sa_list_head; sa != NULL; sa = sa->next) {
4205b0fe478SBruce M Simpson 			struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&sa->daddr;
4215b0fe478SBruce M Simpson 			if (sa->spi == ntohl(esp->esp_spi) &&
4225b0fe478SBruce M Simpson 			    sin6->sin6_family == AF_INET6 &&
4235b0fe478SBruce M Simpson 			    memcmp(&sin6->sin6_addr, &ip6->ip6_dst,
4245b0fe478SBruce M Simpson 				   sizeof(struct in6_addr)) == 0) {
4255b0fe478SBruce M Simpson 				break;
4265b0fe478SBruce M Simpson 			}
4275b0fe478SBruce M Simpson 		}
428b0453382SBill Fenner 		break;
429b0453382SBill Fenner #endif /*INET6*/
430b0453382SBill Fenner 	case 4:
431a90e161bSBill Fenner 		/* nexthdr & padding are in the last fragment */
4325b0fe478SBruce M Simpson 		if (EXTRACT_16BITS(&ip->ip_off) & IP_MF)
433a90e161bSBill Fenner 			goto fail;
4345b0fe478SBruce M Simpson 		len = EXTRACT_16BITS(&ip->ip_len);
4355b0fe478SBruce M Simpson 
4365b0fe478SBruce M Simpson 		/* see if we can find the SA, and if so, decode it */
4371de50e9fSSam Leffler 		for (sa = ndo->ndo_sa_list_head; sa != NULL; sa = sa->next) {
4385b0fe478SBruce M Simpson 			struct sockaddr_in *sin = (struct sockaddr_in *)&sa->daddr;
4395b0fe478SBruce M Simpson 			if (sa->spi == ntohl(esp->esp_spi) &&
4405b0fe478SBruce M Simpson 			    sin->sin_family == AF_INET &&
4415b0fe478SBruce M Simpson 			    sin->sin_addr.s_addr == ip->ip_dst.s_addr) {
4425b0fe478SBruce M Simpson 				break;
4435b0fe478SBruce M Simpson 			}
4445b0fe478SBruce M Simpson 		}
445b0453382SBill Fenner 		break;
446b0453382SBill Fenner 	default:
447b0453382SBill Fenner 		goto fail;
448b0453382SBill Fenner 	}
449b0453382SBill Fenner 
4505b0fe478SBruce M Simpson 	/* if we didn't find the specific one, then look for
4515b0fe478SBruce M Simpson 	 * an unspecified one.
4525b0fe478SBruce M Simpson 	 */
4535b0fe478SBruce M Simpson 	if (sa == NULL)
4541de50e9fSSam Leffler 		sa = ndo->ndo_sa_default;
4555b0fe478SBruce M Simpson 
4565b0fe478SBruce M Simpson 	/* if not found fail */
4575b0fe478SBruce M Simpson 	if (sa == NULL)
4585b0fe478SBruce M Simpson 		goto fail;
4595b0fe478SBruce M Simpson 
460b0453382SBill Fenner 	/* if we can't get nexthdr, we do not need to decrypt it */
461b0453382SBill Fenner 	if (ep - bp2 < len)
462b0453382SBill Fenner 		goto fail;
4635b0fe478SBruce M Simpson 	if (ep - bp2 > len) {
4645b0fe478SBruce M Simpson 		/* FCS included at end of frame (NetBSD 1.6 or later) */
4655b0fe478SBruce M Simpson 		ep = bp2 + len;
466b0453382SBill Fenner 	}
467b0453382SBill Fenner 
4685b0fe478SBruce M Simpson 	ivoff = (u_char *)(esp + 1) + 0;
4695b0fe478SBruce M Simpson 	ivlen = sa->ivlen;
4705b0fe478SBruce M Simpson 	secret = sa->secret;
4715b0fe478SBruce M Simpson 	espsecret_keylen = sa->secretlen;
4721de50e9fSSam Leffler 	ep = ep - sa->authlen;
473b0453382SBill Fenner 
4745b0fe478SBruce M Simpson 	if (sa->evp) {
4755b0fe478SBruce M Simpson 		memset(&ctx, 0, sizeof(ctx));
4765b0fe478SBruce M Simpson 		if (EVP_CipherInit(&ctx, sa->evp, secret, NULL, 0) < 0)
4771de50e9fSSam Leffler 			(*ndo->ndo_warning)(ndo, "espkey init failed");
4785b0fe478SBruce M Simpson 
4795b0fe478SBruce M Simpson 		blocksz = EVP_CIPHER_CTX_block_size(&ctx);
4805b0fe478SBruce M Simpson 
4815b0fe478SBruce M Simpson 		p = ivoff;
4825b0fe478SBruce M Simpson 		EVP_CipherInit(&ctx, NULL, NULL, p, 0);
4835b0fe478SBruce M Simpson 		EVP_Cipher(&ctx, p + ivlen, p + ivlen, ep - (p + ivlen));
484b0453382SBill Fenner 		advance = ivoff - (u_char *)esp + ivlen;
4855b0fe478SBruce M Simpson 	} else
4865b0fe478SBruce M Simpson 		advance = sizeof(struct newesp);
487b0453382SBill Fenner 
488b0453382SBill Fenner 	/* sanity check for pad length */
489b0453382SBill Fenner 	if (ep - bp < *(ep - 2))
490b0453382SBill Fenner 		goto fail;
491b0453382SBill Fenner 
492a90e161bSBill Fenner 	if (padlen)
493a90e161bSBill Fenner 		*padlen = *(ep - 2) + 2;
494a90e161bSBill Fenner 
495b0453382SBill Fenner 	if (nhdr)
496b0453382SBill Fenner 		*nhdr = *(ep - 1);
497b0453382SBill Fenner 
4981de50e9fSSam Leffler 	(ndo->ndo_printf)(ndo, ": ");
499b0453382SBill Fenner 	return advance;
5005b0fe478SBruce M Simpson #endif
501b0453382SBill Fenner 
502b0453382SBill Fenner fail:
5035b0fe478SBruce M Simpson 	return -1;
504b0453382SBill Fenner }
5051de50e9fSSam Leffler 
5061de50e9fSSam Leffler /*
5071de50e9fSSam Leffler  * Local Variables:
5081de50e9fSSam Leffler  * c-style: whitesmith
5091de50e9fSSam Leffler  * c-basic-offset: 8
5101de50e9fSSam Leffler  * End:
5111de50e9fSSam Leffler  */
512