print-esp.c revision 313537
156893Sfenner/*	$NetBSD: print-ah.c,v 1.4 1996/05/20 00:41:16 fvdl Exp $	*/
256893Sfenner
356893Sfenner/*
456893Sfenner * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994
556893Sfenner *	The Regents of the University of California.  All rights reserved.
656893Sfenner *
756893Sfenner * Redistribution and use in source and binary forms, with or without
856893Sfenner * modification, are permitted provided that: (1) source code distributions
956893Sfenner * retain the above copyright notice and this paragraph in its entirety, (2)
1056893Sfenner * distributions including binary code include the above copyright notice and
1156893Sfenner * this paragraph in its entirety in the documentation or other materials
1256893Sfenner * provided with the distribution, and (3) all advertising materials mentioning
1356893Sfenner * features or use of this software display the following acknowledgement:
1456893Sfenner * ``This product includes software developed by the University of California,
1556893Sfenner * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
1656893Sfenner * the University nor the names of its contributors may be used to endorse
1756893Sfenner * or promote products derived from this software without specific prior
1856893Sfenner * written permission.
1956893Sfenner * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
2056893Sfenner * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
2156893Sfenner * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
2256893Sfenner */
2356893Sfenner
24313537Sglebius/* \summary: IPSEC Encapsulating Security Payload (ESP) printer */
25313537Sglebius
2656893Sfenner#ifdef HAVE_CONFIG_H
2756893Sfenner#include "config.h"
2856893Sfenner#endif
2956893Sfenner
30313537Sglebius#include <netdissect-stdinc.h>
31127668Sbms
32276788Sdelphij#include <string.h>
33111726Sfenner#include <stdlib.h>
3456893Sfenner
35276788Sdelphij/* Any code in this file that depends on HAVE_LIBCRYPTO depends on
36276788Sdelphij * HAVE_OPENSSL_EVP_H too. Undefining the former when the latter isn't defined
37276788Sdelphij * is the simplest way of handling the dependency.
38276788Sdelphij */
3975115Sfenner#ifdef HAVE_LIBCRYPTO
40127668Sbms#ifdef HAVE_OPENSSL_EVP_H
41127668Sbms#include <openssl/evp.h>
42276788Sdelphij#else
43276788Sdelphij#undef HAVE_LIBCRYPTO
4456893Sfenner#endif
4556893Sfenner#endif
4656893Sfenner
47313537Sglebius#include "netdissect.h"
48313537Sglebius#include "strtoaddr.h"
49313537Sglebius#include "extract.h"
50313537Sglebius
51313537Sglebius#include "ascii_strcasecmp.h"
52313537Sglebius
5375115Sfenner#include "ip.h"
5475115Sfenner#include "ip6.h"
5556893Sfenner
56276788Sdelphij/*
57276788Sdelphij * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
58276788Sdelphij * All rights reserved.
59276788Sdelphij *
60276788Sdelphij * Redistribution and use in source and binary forms, with or without
61276788Sdelphij * modification, are permitted provided that the following conditions
62276788Sdelphij * are met:
63276788Sdelphij * 1. Redistributions of source code must retain the above copyright
64276788Sdelphij *    notice, this list of conditions and the following disclaimer.
65276788Sdelphij * 2. Redistributions in binary form must reproduce the above copyright
66276788Sdelphij *    notice, this list of conditions and the following disclaimer in the
67276788Sdelphij *    documentation and/or other materials provided with the distribution.
68276788Sdelphij * 3. Neither the name of the project nor the names of its contributors
69276788Sdelphij *    may be used to endorse or promote products derived from this software
70276788Sdelphij *    without specific prior written permission.
71276788Sdelphij *
72276788Sdelphij * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
73276788Sdelphij * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
74276788Sdelphij * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
75276788Sdelphij * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
76276788Sdelphij * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
77276788Sdelphij * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
78276788Sdelphij * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
79276788Sdelphij * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
80276788Sdelphij * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
81276788Sdelphij * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
82276788Sdelphij * SUCH DAMAGE.
83276788Sdelphij */
84276788Sdelphij
85276788Sdelphij/*
86276788Sdelphij * RFC1827/2406 Encapsulated Security Payload.
87276788Sdelphij */
88276788Sdelphij
89276788Sdelphijstruct newesp {
90276788Sdelphij	uint32_t	esp_spi;	/* ESP */
91276788Sdelphij	uint32_t	esp_seq;	/* Sequence number */
92276788Sdelphij	/*variable size*/		/* (IV and) Payload data */
93276788Sdelphij	/*variable size*/		/* padding */
94276788Sdelphij	/*8bit*/			/* pad size */
95276788Sdelphij	/*8bit*/			/* next header */
96276788Sdelphij	/*8bit*/			/* next header */
97276788Sdelphij	/*variable size, 32bit bound*/	/* Authentication data */
98127668Sbms};
9998524Sfenner
100127668Sbms#ifdef HAVE_LIBCRYPTO
101276788Sdelphijunion inaddr_u {
102276788Sdelphij	struct in_addr in4;
103276788Sdelphij	struct in6_addr in6;
104276788Sdelphij};
105127668Sbmsstruct sa_list {
106127668Sbms	struct sa_list	*next;
107276788Sdelphij	u_int		daddr_version;
108276788Sdelphij	union inaddr_u	daddr;
109276788Sdelphij	uint32_t	spi;          /* if == 0, then IKEv2 */
110214478Srpaulo	int             initiator;
111214478Srpaulo	u_char          spii[8];      /* for IKEv2 */
112214478Srpaulo	u_char          spir[8];
113127668Sbms	const EVP_CIPHER *evp;
114127668Sbms	int		ivlen;
115127668Sbms	int		authlen;
116214478Srpaulo	u_char          authsecret[256];
117214478Srpaulo	int             authsecret_len;
118147899Ssam	u_char		secret[256];  /* is that big enough for all secrets? */
119127668Sbms	int		secretlen;
120127668Sbms};
12198524Sfenner
122313537Sglebius#ifndef HAVE_EVP_CIPHER_CTX_NEW
123214478Srpaulo/*
124313537Sglebius * Allocate an EVP_CIPHER_CTX.
125313537Sglebius * Used if we have an older version of OpenSSL that doesn't provide
126313537Sglebius * routines to allocate and free them.
127313537Sglebius */
128313537Sglebiusstatic EVP_CIPHER_CTX *
129313537SglebiusEVP_CIPHER_CTX_new(void)
130313537Sglebius{
131313537Sglebius	EVP_CIPHER_CTX *ctx;
132313537Sglebius
133313537Sglebius	ctx = malloc(sizeof(*ctx));
134313537Sglebius	if (ctx == NULL)
135313537Sglebius		return (NULL);
136313537Sglebius	memset(ctx, 0, sizeof(*ctx));
137313537Sglebius	return (ctx);
138313537Sglebius}
139313537Sglebius
140313537Sglebiusstatic void
141313537SglebiusEVP_CIPHER_CTX_free(EVP_CIPHER_CTX *ctx)
142313537Sglebius{
143313537Sglebius	EVP_CIPHER_CTX_cleanup(ctx);
144313537Sglebius	free(ctx);
145313537Sglebius}
146313537Sglebius#endif
147313537Sglebius
148313537Sglebius/*
149214478Srpaulo * this will adjust ndo_packetp and ndo_snapend to new buffer!
150214478Srpaulo */
151276788SdelphijUSES_APPLE_DEPRECATED_API
152214478Srpauloint esp_print_decrypt_buffer_by_ikev2(netdissect_options *ndo,
153214478Srpaulo				      int initiator,
154214478Srpaulo				      u_char spii[8], u_char spir[8],
155313537Sglebius				      const u_char *buf, const u_char *end)
156214478Srpaulo{
157214478Srpaulo	struct sa_list *sa;
158313537Sglebius	const u_char *iv;
159214478Srpaulo	int len;
160313537Sglebius	EVP_CIPHER_CTX *ctx;
161214478Srpaulo
162214478Srpaulo	/* initiator arg is any non-zero value */
163214478Srpaulo	if(initiator) initiator=1;
164276788Sdelphij
165214478Srpaulo	/* see if we can find the SA, and if so, decode it */
166214478Srpaulo	for (sa = ndo->ndo_sa_list_head; sa != NULL; sa = sa->next) {
167214478Srpaulo		if (sa->spi == 0
168214478Srpaulo		    && initiator == sa->initiator
169214478Srpaulo		    && memcmp(spii, sa->spii, 8) == 0
170214478Srpaulo		    && memcmp(spir, sa->spir, 8) == 0)
171214478Srpaulo			break;
172214478Srpaulo	}
173214478Srpaulo
174214478Srpaulo	if(sa == NULL) return 0;
175214478Srpaulo	if(sa->evp == NULL) return 0;
176214478Srpaulo
177214478Srpaulo	/*
178214478Srpaulo	 * remove authenticator, and see if we still have something to
179214478Srpaulo	 * work with
180214478Srpaulo	 */
181214478Srpaulo	end = end - sa->authlen;
182214478Srpaulo	iv  = buf;
183214478Srpaulo	buf = buf + sa->ivlen;
184214478Srpaulo	len = end-buf;
185214478Srpaulo
186214478Srpaulo	if(end <= buf) return 0;
187214478Srpaulo
188313537Sglebius	ctx = EVP_CIPHER_CTX_new();
189313537Sglebius	if (ctx == NULL)
190313537Sglebius		return 0;
191313537Sglebius	if (EVP_CipherInit(ctx, sa->evp, sa->secret, NULL, 0) < 0)
192214478Srpaulo		(*ndo->ndo_warning)(ndo, "espkey init failed");
193313537Sglebius	EVP_CipherInit(ctx, NULL, NULL, iv, 0);
194313537Sglebius	EVP_Cipher(ctx, __DECONST(u_char *, buf), buf, len);
195313537Sglebius	EVP_CIPHER_CTX_free(ctx);
196214478Srpaulo
197214478Srpaulo	ndo->ndo_packetp = buf;
198214478Srpaulo	ndo->ndo_snapend = end;
199214478Srpaulo
200214478Srpaulo	return 1;
201276788Sdelphij
202214478Srpaulo}
203276788SdelphijUSES_APPLE_RST
204214478Srpaulo
205146773Ssamstatic void esp_print_addsa(netdissect_options *ndo,
206146773Ssam			    struct sa_list *sa, int sa_def)
207127668Sbms{
208127668Sbms	/* copy the "sa" */
20998524Sfenner
210127668Sbms	struct sa_list *nsa;
21198524Sfenner
212127668Sbms	nsa = (struct sa_list *)malloc(sizeof(struct sa_list));
213127668Sbms	if (nsa == NULL)
214146773Ssam		(*ndo->ndo_error)(ndo, "ran out of memory to allocate sa structure");
21598524Sfenner
216127668Sbms	*nsa = *sa;
21798524Sfenner
218127668Sbms	if (sa_def)
219146773Ssam		ndo->ndo_sa_default = nsa;
220127668Sbms
221146773Ssam	nsa->next = ndo->ndo_sa_list_head;
222146773Ssam	ndo->ndo_sa_list_head = nsa;
223127668Sbms}
224127668Sbms
225127668Sbms
226147899Ssamstatic u_int hexdigit(netdissect_options *ndo, char hex)
22798524Sfenner{
228127668Sbms	if (hex >= '0' && hex <= '9')
22998524Sfenner		return (hex - '0');
230127668Sbms	else if (hex >= 'A' && hex <= 'F')
23198524Sfenner		return (hex - 'A' + 10);
232127668Sbms	else if (hex >= 'a' && hex <= 'f')
23398524Sfenner		return (hex - 'a' + 10);
234127668Sbms	else {
235146773Ssam		(*ndo->ndo_error)(ndo, "invalid hex digit %c in espsecret\n", hex);
23698524Sfenner		return 0;
23798524Sfenner	}
23898524Sfenner}
23998524Sfenner
240147899Ssamstatic u_int hex2byte(netdissect_options *ndo, char *hexstring)
24198524Sfenner{
242147899Ssam	u_int byte;
24398524Sfenner
244146773Ssam	byte = (hexdigit(ndo, hexstring[0]) << 4) + hexdigit(ndo, hexstring[1]);
24598524Sfenner	return byte;
24698524Sfenner}
24798524Sfenner
248127668Sbms/*
249214478Srpaulo * returns size of binary, 0 on failure.
250214478Srpaulo */
251214478Srpaulostatic
252214478Srpauloint espprint_decode_hex(netdissect_options *ndo,
253214478Srpaulo			u_char *binbuf, unsigned int binbuf_len,
254214478Srpaulo			char *hex)
255214478Srpaulo{
256214478Srpaulo	unsigned int len;
257214478Srpaulo	int i;
258214478Srpaulo
259214478Srpaulo	len = strlen(hex) / 2;
260276788Sdelphij
261214478Srpaulo	if (len > binbuf_len) {
262214478Srpaulo		(*ndo->ndo_warning)(ndo, "secret is too big: %d\n", len);
263214478Srpaulo		return 0;
264214478Srpaulo	}
265276788Sdelphij
266214478Srpaulo	i = 0;
267214478Srpaulo	while (hex[0] != '\0' && hex[1]!='\0') {
268214478Srpaulo		binbuf[i] = hex2byte(ndo, hex);
269214478Srpaulo		hex += 2;
270214478Srpaulo		i++;
271214478Srpaulo	}
272214478Srpaulo
273214478Srpaulo	return i;
274214478Srpaulo}
275214478Srpaulo
276214478Srpaulo/*
277127668Sbms * decode the form:    SPINUM@IP <tab> ALGONAME:0xsecret
278214478Srpaulo */
279214478Srpaulo
280276788SdelphijUSES_APPLE_DEPRECATED_API
281214478Srpaulostatic int
282214478Srpauloespprint_decode_encalgo(netdissect_options *ndo,
283214478Srpaulo			char *decode, struct sa_list *sa)
284214478Srpaulo{
285214478Srpaulo	size_t i;
286214478Srpaulo	const EVP_CIPHER *evp;
287214478Srpaulo	int authlen = 0;
288214478Srpaulo	char *colon, *p;
289276788Sdelphij
290214478Srpaulo	colon = strchr(decode, ':');
291214478Srpaulo	if (colon == NULL) {
292214478Srpaulo		(*ndo->ndo_warning)(ndo, "failed to decode espsecret: %s\n", decode);
293214478Srpaulo		return 0;
294214478Srpaulo	}
295214478Srpaulo	*colon = '\0';
296276788Sdelphij
297214478Srpaulo	if (strlen(decode) > strlen("-hmac96") &&
298214478Srpaulo	    !strcmp(decode + strlen(decode) - strlen("-hmac96"),
299214478Srpaulo		    "-hmac96")) {
300214478Srpaulo		p = strstr(decode, "-hmac96");
301214478Srpaulo		*p = '\0';
302214478Srpaulo		authlen = 12;
303214478Srpaulo	}
304214478Srpaulo	if (strlen(decode) > strlen("-cbc") &&
305214478Srpaulo	    !strcmp(decode + strlen(decode) - strlen("-cbc"), "-cbc")) {
306214478Srpaulo		p = strstr(decode, "-cbc");
307214478Srpaulo		*p = '\0';
308214478Srpaulo	}
309214478Srpaulo	evp = EVP_get_cipherbyname(decode);
310214478Srpaulo
311214478Srpaulo	if (!evp) {
312214478Srpaulo		(*ndo->ndo_warning)(ndo, "failed to find cipher algo %s\n", decode);
313214478Srpaulo		sa->evp = NULL;
314214478Srpaulo		sa->authlen = 0;
315214478Srpaulo		sa->ivlen = 0;
316214478Srpaulo		return 0;
317214478Srpaulo	}
318276788Sdelphij
319214478Srpaulo	sa->evp = evp;
320214478Srpaulo	sa->authlen = authlen;
321214478Srpaulo	sa->ivlen = EVP_CIPHER_iv_length(evp);
322276788Sdelphij
323214478Srpaulo	colon++;
324214478Srpaulo	if (colon[0] == '0' && colon[1] == 'x') {
325214478Srpaulo		/* decode some hex! */
326214478Srpaulo
327214478Srpaulo		colon += 2;
328214478Srpaulo		sa->secretlen = espprint_decode_hex(ndo, sa->secret, sizeof(sa->secret), colon);
329214478Srpaulo		if(sa->secretlen == 0) return 0;
330214478Srpaulo	} else {
331214478Srpaulo		i = strlen(colon);
332276788Sdelphij
333214478Srpaulo		if (i < sizeof(sa->secret)) {
334214478Srpaulo			memcpy(sa->secret, colon, i);
335214478Srpaulo			sa->secretlen = i;
336214478Srpaulo		} else {
337214478Srpaulo			memcpy(sa->secret, colon, sizeof(sa->secret));
338214478Srpaulo			sa->secretlen = sizeof(sa->secret);
339214478Srpaulo		}
340214478Srpaulo	}
341214478Srpaulo
342214478Srpaulo	return 1;
343214478Srpaulo}
344276788SdelphijUSES_APPLE_RST
345214478Srpaulo
346214478Srpaulo/*
347214478Srpaulo * for the moment, ignore the auth algorith, just hard code the authenticator
348214478Srpaulo * length. Need to research how openssl looks up HMAC stuff.
349214478Srpaulo */
350214478Srpaulostatic int
351214478Srpauloespprint_decode_authalgo(netdissect_options *ndo,
352214478Srpaulo			 char *decode, struct sa_list *sa)
353214478Srpaulo{
354214478Srpaulo	char *colon;
355214478Srpaulo
356214478Srpaulo	colon = strchr(decode, ':');
357214478Srpaulo	if (colon == NULL) {
358214478Srpaulo		(*ndo->ndo_warning)(ndo, "failed to decode espsecret: %s\n", decode);
359214478Srpaulo		return 0;
360214478Srpaulo	}
361214478Srpaulo	*colon = '\0';
362276788Sdelphij
363313537Sglebius	if(ascii_strcasecmp(colon,"sha1") == 0 ||
364313537Sglebius	   ascii_strcasecmp(colon,"md5") == 0) {
365214478Srpaulo		sa->authlen = 12;
366214478Srpaulo	}
367214478Srpaulo	return 1;
368214478Srpaulo}
369214478Srpaulo
370214478Srpaulostatic void esp_print_decode_ikeline(netdissect_options *ndo, char *line,
371214478Srpaulo				     const char *file, int lineno)
372214478Srpaulo{
373214478Srpaulo	/* it's an IKEv2 secret, store it instead */
374214478Srpaulo	struct sa_list sa1;
375214478Srpaulo
376214478Srpaulo	char *init;
377214478Srpaulo	char *icookie, *rcookie;
378214478Srpaulo	int   ilen, rlen;
379214478Srpaulo	char *authkey;
380214478Srpaulo	char *enckey;
381276788Sdelphij
382214478Srpaulo	init = strsep(&line, " \t");
383214478Srpaulo	icookie = strsep(&line, " \t");
384214478Srpaulo	rcookie = strsep(&line, " \t");
385214478Srpaulo	authkey = strsep(&line, " \t");
386214478Srpaulo	enckey  = strsep(&line, " \t");
387276788Sdelphij
388214478Srpaulo	/* if any fields are missing */
389214478Srpaulo	if(!init || !icookie || !rcookie || !authkey || !enckey) {
390214478Srpaulo		(*ndo->ndo_warning)(ndo, "print_esp: failed to find all fields for ikev2 at %s:%u",
391214478Srpaulo				    file, lineno);
392276788Sdelphij
393214478Srpaulo		return;
394214478Srpaulo	}
395276788Sdelphij
396214478Srpaulo	ilen = strlen(icookie);
397214478Srpaulo	rlen = strlen(rcookie);
398214478Srpaulo
399214478Srpaulo	if((init[0]!='I' && init[0]!='R')
400214478Srpaulo	   || icookie[0]!='0' || icookie[1]!='x'
401214478Srpaulo	   || rcookie[0]!='0' || rcookie[1]!='x'
402214478Srpaulo	   || ilen!=18
403214478Srpaulo	   || rlen!=18) {
404214478Srpaulo		(*ndo->ndo_warning)(ndo, "print_esp: line %s:%u improperly formatted.",
405214478Srpaulo				    file, lineno);
406214478Srpaulo
407214478Srpaulo		(*ndo->ndo_warning)(ndo, "init=%s icookie=%s(%u) rcookie=%s(%u)",
408214478Srpaulo				    init, icookie, ilen, rcookie, rlen);
409276788Sdelphij
410214478Srpaulo		return;
411214478Srpaulo	}
412214478Srpaulo
413214478Srpaulo	sa1.spi = 0;
414214478Srpaulo	sa1.initiator = (init[0] == 'I');
415214478Srpaulo	if(espprint_decode_hex(ndo, sa1.spii, sizeof(sa1.spii), icookie+2)!=8)
416214478Srpaulo		return;
417214478Srpaulo
418214478Srpaulo	if(espprint_decode_hex(ndo, sa1.spir, sizeof(sa1.spir), rcookie+2)!=8)
419214478Srpaulo		return;
420214478Srpaulo
421214478Srpaulo	if(!espprint_decode_encalgo(ndo, enckey, &sa1)) return;
422214478Srpaulo
423214478Srpaulo	if(!espprint_decode_authalgo(ndo, authkey, &sa1)) return;
424276788Sdelphij
425214478Srpaulo	esp_print_addsa(ndo, &sa1, FALSE);
426214478Srpaulo}
427214478Srpaulo
428214478Srpaulo/*
429127668Sbms *
430127668Sbms * special form: file /name
431127668Sbms * causes us to go read from this file instead.
432127668Sbms *
433127668Sbms */
434214478Srpaulostatic void esp_print_decode_onesecret(netdissect_options *ndo, char *line,
435214478Srpaulo				       const char *file, int lineno)
43698524Sfenner{
437127668Sbms	struct sa_list sa1;
438127668Sbms	int sa_def;
43998524Sfenner
440127668Sbms	char *spikey;
441127668Sbms	char *decode;
44298524Sfenner
443127668Sbms	spikey = strsep(&line, " \t");
444127668Sbms	sa_def = 0;
445127668Sbms	memset(&sa1, 0, sizeof(struct sa_list));
446127668Sbms
447127668Sbms	/* if there is only one token, then it is an algo:key token */
448127668Sbms	if (line == NULL) {
449127668Sbms		decode = spikey;
450127668Sbms		spikey = NULL;
451276788Sdelphij		/* sa1.daddr.version = 0; */
452127668Sbms		/* memset(&sa1.daddr, 0, sizeof(sa1.daddr)); */
453127668Sbms		/* sa1.spi = 0; */
454127668Sbms		sa_def    = 1;
455127668Sbms	} else
456127668Sbms		decode = line;
457127668Sbms
458313537Sglebius	if (spikey && ascii_strcasecmp(spikey, "file") == 0) {
459127668Sbms		/* open file and read it */
460127668Sbms		FILE *secretfile;
461127668Sbms		char  fileline[1024];
462313537Sglebius		int   subfile_lineno=0;
463127668Sbms		char  *nl;
464214478Srpaulo		char *filename = line;
465127668Sbms
466214478Srpaulo		secretfile = fopen(filename, FOPEN_READ_TXT);
467127668Sbms		if (secretfile == NULL) {
468313537Sglebius			(*ndo->ndo_error)(ndo, "print_esp: can't open %s: %s\n",
469313537Sglebius			    filename, strerror(errno));
470313537Sglebius			return;
471127668Sbms		}
472127668Sbms
473127668Sbms		while (fgets(fileline, sizeof(fileline)-1, secretfile) != NULL) {
474313537Sglebius			subfile_lineno++;
475127668Sbms			/* remove newline from the line */
476127668Sbms			nl = strchr(fileline, '\n');
477127668Sbms			if (nl)
478127668Sbms				*nl = '\0';
479127668Sbms			if (fileline[0] == '#') continue;
480127668Sbms			if (fileline[0] == '\0') continue;
481127668Sbms
482313537Sglebius			esp_print_decode_onesecret(ndo, fileline, filename, subfile_lineno);
483127668Sbms		}
484127668Sbms		fclose(secretfile);
485127668Sbms
48698524Sfenner		return;
48798524Sfenner	}
48898524Sfenner
489313537Sglebius	if (spikey && ascii_strcasecmp(spikey, "ikev2") == 0) {
490214478Srpaulo		esp_print_decode_ikeline(ndo, line, file, lineno);
491214478Srpaulo		return;
492276788Sdelphij	}
493214478Srpaulo
494127668Sbms	if (spikey) {
495276788Sdelphij
496127668Sbms		char *spistr, *foo;
497276788Sdelphij		uint32_t spino;
498276788Sdelphij
499127668Sbms		spistr = strsep(&spikey, "@");
500276788Sdelphij
501127668Sbms		spino = strtoul(spistr, &foo, 0);
502127668Sbms		if (spistr == foo || !spikey) {
503146773Ssam			(*ndo->ndo_warning)(ndo, "print_esp: failed to decode spi# %s\n", foo);
504127668Sbms			return;
505127668Sbms		}
506276788Sdelphij
507127668Sbms		sa1.spi = spino;
508276788Sdelphij
509313537Sglebius		if (strtoaddr6(spikey, &sa1.daddr.in6) == 1) {
510276788Sdelphij			sa1.daddr_version = 6;
511313537Sglebius		} else if (strtoaddr(spikey, &sa1.daddr.in4) == 1) {
512313537Sglebius			sa1.daddr_version = 4;
513313537Sglebius		} else {
514313537Sglebius			(*ndo->ndo_warning)(ndo, "print_esp: can not decode IP# %s\n", spikey);
515313537Sglebius			return;
516313537Sglebius		}
51798524Sfenner	}
51898524Sfenner
519127668Sbms	if (decode) {
520127668Sbms		/* skip any blank spaces */
521127668Sbms		while (isspace((unsigned char)*decode))
522127668Sbms			decode++;
523276788Sdelphij
524214478Srpaulo		if(!espprint_decode_encalgo(ndo, decode, &sa1)) {
525127668Sbms			return;
52698524Sfenner		}
52798524Sfenner	}
528127668Sbms
529146773Ssam	esp_print_addsa(ndo, &sa1, sa_def);
53098524Sfenner}
53198524Sfenner
532276788SdelphijUSES_APPLE_DEPRECATED_API
533214478Srpaulostatic void esp_init(netdissect_options *ndo _U_)
534127668Sbms{
535313537Sglebius	/*
536313537Sglebius	 * 0.9.6 doesn't appear to define OPENSSL_API_COMPAT, so
537313537Sglebius	 * we check whether it's undefined or it's less than the
538313537Sglebius	 * value for 1.1.0.
539313537Sglebius	 */
540313537Sglebius#if !defined(OPENSSL_API_COMPAT) || OPENSSL_API_COMPAT < 0x10100000L
541214478Srpaulo	OpenSSL_add_all_algorithms();
542313537Sglebius#endif
543214478Srpaulo	EVP_add_cipher_alias(SN_des_ede3_cbc, "3des");
544214478Srpaulo}
545276788SdelphijUSES_APPLE_RST
546214478Srpaulo
547214478Srpaulovoid esp_print_decodesecret(netdissect_options *ndo)
548214478Srpaulo{
549127668Sbms	char *line;
550127668Sbms	char *p;
551214478Srpaulo	static int initialized = 0;
552127668Sbms
553214478Srpaulo	if (!initialized) {
554214478Srpaulo		esp_init(ndo);
555214478Srpaulo		initialized = 1;
556214478Srpaulo	}
557214478Srpaulo
558146773Ssam	p = ndo->ndo_espsecret;
559127668Sbms
560214478Srpaulo	while (p && p[0] != '\0') {
561127668Sbms		/* pick out the first line or first thing until a comma */
562214478Srpaulo		if ((line = strsep(&p, "\n,")) == NULL) {
563214478Srpaulo			line = p;
564214478Srpaulo			p = NULL;
565127668Sbms		}
566127668Sbms
567214478Srpaulo		esp_print_decode_onesecret(ndo, line, "cmdline", 0);
568127668Sbms	}
569214478Srpaulo
570214478Srpaulo	ndo->ndo_espsecret = NULL;
571127668Sbms}
572127668Sbms
573127668Sbms#endif
574127668Sbms
575276788Sdelphij#ifdef HAVE_LIBCRYPTO
576276788SdelphijUSES_APPLE_DEPRECATED_API
577276788Sdelphij#endif
57856893Sfennerint
579146773Ssamesp_print(netdissect_options *ndo,
580146773Ssam	  const u_char *bp, const int length, const u_char *bp2
581127668Sbms#ifndef HAVE_LIBCRYPTO
582127668Sbms	_U_
583127668Sbms#endif
584127668Sbms	,
585127668Sbms	int *nhdr
586127668Sbms#ifndef HAVE_LIBCRYPTO
587127668Sbms	_U_
588127668Sbms#endif
589127668Sbms	,
590127668Sbms	int *padlen
591127668Sbms#ifndef HAVE_LIBCRYPTO
592127668Sbms	_U_
593127668Sbms#endif
594127668Sbms	)
59556893Sfenner{
596127668Sbms	register const struct newesp *esp;
59756893Sfenner	register const u_char *ep;
598127668Sbms#ifdef HAVE_LIBCRYPTO
599313537Sglebius	const struct ip *ip;
600127668Sbms	struct sa_list *sa = NULL;
601313537Sglebius	const struct ip6_hdr *ip6 = NULL;
60256893Sfenner	int advance;
60356893Sfenner	int len;
604147899Ssam	u_char *secret;
60556893Sfenner	int ivlen = 0;
606313537Sglebius	const u_char *ivoff;
607313537Sglebius	const u_char *p;
608313537Sglebius	EVP_CIPHER_CTX *ctx;
609127668Sbms#endif
610127668Sbms
611313537Sglebius	esp = (const struct newesp *)bp;
612127668Sbms
613127668Sbms#ifdef HAVE_LIBCRYPTO
61498524Sfenner	secret = NULL;
615127668Sbms	advance = 0;
616127668Sbms#endif
617127668Sbms
61898524Sfenner#if 0
61998524Sfenner	/* keep secret out of a register */
62098524Sfenner	p = (u_char *)&secret;
62198524Sfenner#endif
62298524Sfenner
62375115Sfenner	/* 'ep' points to the end of available data. */
624146773Ssam	ep = ndo->ndo_snapend;
62556893Sfenner
626313537Sglebius	if ((const u_char *)(esp + 1) >= ep) {
627276788Sdelphij		ND_PRINT((ndo, "[|ESP]"));
62856893Sfenner		goto fail;
62956893Sfenner	}
630276788Sdelphij	ND_PRINT((ndo, "ESP(spi=0x%08x", EXTRACT_32BITS(&esp->esp_spi)));
631276788Sdelphij	ND_PRINT((ndo, ",seq=0x%x)", EXTRACT_32BITS(&esp->esp_seq)));
632276788Sdelphij	ND_PRINT((ndo, ", length %u", length));
63356893Sfenner
634127668Sbms#ifndef HAVE_LIBCRYPTO
635127668Sbms	goto fail;
636127668Sbms#else
637127668Sbms	/* initiailize SAs */
638146773Ssam	if (ndo->ndo_sa_list_head == NULL) {
639146773Ssam		if (!ndo->ndo_espsecret)
640127668Sbms			goto fail;
64156893Sfenner
642146773Ssam		esp_print_decodesecret(ndo);
64356893Sfenner	}
644127668Sbms
645146773Ssam	if (ndo->ndo_sa_list_head == NULL)
64698524Sfenner		goto fail;
64756893Sfenner
648313537Sglebius	ip = (const struct ip *)bp2;
64975115Sfenner	switch (IP_V(ip)) {
65056893Sfenner	case 6:
651313537Sglebius		ip6 = (const struct ip6_hdr *)bp2;
65256893Sfenner		/* we do not attempt to decrypt jumbograms */
653127668Sbms		if (!EXTRACT_16BITS(&ip6->ip6_plen))
65456893Sfenner			goto fail;
65556893Sfenner		/* if we can't get nexthdr, we do not need to decrypt it */
656127668Sbms		len = sizeof(struct ip6_hdr) + EXTRACT_16BITS(&ip6->ip6_plen);
657127668Sbms
658127668Sbms		/* see if we can find the SA, and if so, decode it */
659146773Ssam		for (sa = ndo->ndo_sa_list_head; sa != NULL; sa = sa->next) {
660214478Srpaulo			if (sa->spi == EXTRACT_32BITS(&esp->esp_spi) &&
661276788Sdelphij			    sa->daddr_version == 6 &&
662276788Sdelphij			    UNALIGNED_MEMCMP(&sa->daddr.in6, &ip6->ip6_dst,
663127668Sbms				   sizeof(struct in6_addr)) == 0) {
664127668Sbms				break;
665127668Sbms			}
666127668Sbms		}
66756893Sfenner		break;
66856893Sfenner	case 4:
66998524Sfenner		/* nexthdr & padding are in the last fragment */
670127668Sbms		if (EXTRACT_16BITS(&ip->ip_off) & IP_MF)
67198524Sfenner			goto fail;
672127668Sbms		len = EXTRACT_16BITS(&ip->ip_len);
673127668Sbms
674127668Sbms		/* see if we can find the SA, and if so, decode it */
675146773Ssam		for (sa = ndo->ndo_sa_list_head; sa != NULL; sa = sa->next) {
676214478Srpaulo			if (sa->spi == EXTRACT_32BITS(&esp->esp_spi) &&
677276788Sdelphij			    sa->daddr_version == 4 &&
678276788Sdelphij			    UNALIGNED_MEMCMP(&sa->daddr.in4, &ip->ip_dst,
679276788Sdelphij				   sizeof(struct in_addr)) == 0) {
680127668Sbms				break;
681127668Sbms			}
682127668Sbms		}
68356893Sfenner		break;
68456893Sfenner	default:
68556893Sfenner		goto fail;
68656893Sfenner	}
68756893Sfenner
688127668Sbms	/* if we didn't find the specific one, then look for
689127668Sbms	 * an unspecified one.
690127668Sbms	 */
691127668Sbms	if (sa == NULL)
692146773Ssam		sa = ndo->ndo_sa_default;
693276788Sdelphij
694127668Sbms	/* if not found fail */
695127668Sbms	if (sa == NULL)
696127668Sbms		goto fail;
697127668Sbms
69856893Sfenner	/* if we can't get nexthdr, we do not need to decrypt it */
69956893Sfenner	if (ep - bp2 < len)
70056893Sfenner		goto fail;
701127668Sbms	if (ep - bp2 > len) {
702127668Sbms		/* FCS included at end of frame (NetBSD 1.6 or later) */
703127668Sbms		ep = bp2 + len;
704127668Sbms	}
70556893Sfenner
706313537Sglebius	ivoff = (const u_char *)(esp + 1) + 0;
707127668Sbms	ivlen = sa->ivlen;
708127668Sbms	secret = sa->secret;
709146773Ssam	ep = ep - sa->authlen;
71056893Sfenner
711127668Sbms	if (sa->evp) {
712313537Sglebius		ctx = EVP_CIPHER_CTX_new();
713313537Sglebius		if (ctx != NULL) {
714313537Sglebius			if (EVP_CipherInit(ctx, sa->evp, secret, NULL, 0) < 0)
715313537Sglebius				(*ndo->ndo_warning)(ndo, "espkey init failed");
71656893Sfenner
717313537Sglebius			p = ivoff;
718313537Sglebius			EVP_CipherInit(ctx, NULL, NULL, p, 0);
719313537Sglebius			EVP_Cipher(ctx, __DECONST(u_char *, p + ivlen),
720313537Sglebius			    p + ivlen, ep - (p + ivlen));
721313537Sglebius			EVP_CIPHER_CTX_free(ctx);
722313537Sglebius			advance = ivoff - (const u_char *)esp + ivlen;
723313537Sglebius		} else
724313537Sglebius			advance = sizeof(struct newesp);
725127668Sbms	} else
726127668Sbms		advance = sizeof(struct newesp);
72756893Sfenner
72856893Sfenner	/* sanity check for pad length */
72956893Sfenner	if (ep - bp < *(ep - 2))
73056893Sfenner		goto fail;
73156893Sfenner
73298524Sfenner	if (padlen)
73398524Sfenner		*padlen = *(ep - 2) + 2;
73498524Sfenner
73556893Sfenner	if (nhdr)
73656893Sfenner		*nhdr = *(ep - 1);
73756893Sfenner
738276788Sdelphij	ND_PRINT((ndo, ": "));
73956893Sfenner	return advance;
740127668Sbms#endif
74156893Sfenner
74256893Sfennerfail:
743127668Sbms	return -1;
74456893Sfenner}
745276788Sdelphij#ifdef HAVE_LIBCRYPTO
746276788SdelphijUSES_APPLE_RST
747276788Sdelphij#endif
748146773Ssam
749146773Ssam/*
750146773Ssam * Local Variables:
751146773Ssam * c-style: whitesmith
752146773Ssam * c-basic-offset: 8
753146773Ssam * End:
754146773Ssam */
755