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
148327234Semaste#ifdef HAVE_EVP_CIPHERINIT_EX
149313537Sglebius/*
150327234Semaste * Initialize the cipher by calling EVP_CipherInit_ex(), because
151327234Semaste * calling EVP_CipherInit() will reset the cipher context, clearing
152327234Semaste * the cipher, so calling it twice, with the second call having a
153327234Semaste * null cipher, will clear the already-set cipher.  EVP_CipherInit_ex(),
154327234Semaste * however, won't reset the cipher context, so you can use it to specify
155327234Semaste * the IV oin a second call after a first call to EVP_CipherInit_ex()
156327234Semaste * to set the cipher and the key.
157327234Semaste *
158327234Semaste * XXX - is there some reason why we need to make two calls?
159327234Semaste */
160327234Semastestatic int
161327234Semasteset_cipher_parameters(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
162327234Semaste		      const unsigned char *key,
163327234Semaste		      const unsigned char *iv, int enc)
164327234Semaste{
165327234Semaste	return EVP_CipherInit_ex(ctx, cipher, NULL, key, iv, enc);
166327234Semaste}
167327234Semaste#else
168327234Semaste/*
169327234Semaste * Initialize the cipher by calling EVP_CipherInit(), because we don't
170327234Semaste * have EVP_CipherInit_ex(); we rely on it not trashing the context.
171327234Semaste */
172327234Semastestatic int
173327234Semasteset_cipher_parameters(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
174327234Semaste		      const unsigned char *key,
175327234Semaste		      const unsigned char *iv, int enc)
176327234Semaste{
177327234Semaste	return EVP_CipherInit(ctx, cipher, key, iv, enc);
178327234Semaste}
179327234Semaste#endif
180327234Semaste
181327234Semaste/*
182214478Srpaulo * this will adjust ndo_packetp and ndo_snapend to new buffer!
183214478Srpaulo */
184276788SdelphijUSES_APPLE_DEPRECATED_API
185214478Srpauloint esp_print_decrypt_buffer_by_ikev2(netdissect_options *ndo,
186214478Srpaulo				      int initiator,
187214478Srpaulo				      u_char spii[8], u_char spir[8],
188313537Sglebius				      const u_char *buf, const u_char *end)
189214478Srpaulo{
190214478Srpaulo	struct sa_list *sa;
191313537Sglebius	const u_char *iv;
192327234Semaste	unsigned int len;
193313537Sglebius	EVP_CIPHER_CTX *ctx;
194356341Scy	unsigned int block_size, buffer_size;
195356341Scy	u_char *input_buffer, *output_buffer;
196214478Srpaulo
197214478Srpaulo	/* initiator arg is any non-zero value */
198214478Srpaulo	if(initiator) initiator=1;
199276788Sdelphij
200214478Srpaulo	/* see if we can find the SA, and if so, decode it */
201214478Srpaulo	for (sa = ndo->ndo_sa_list_head; sa != NULL; sa = sa->next) {
202214478Srpaulo		if (sa->spi == 0
203214478Srpaulo		    && initiator == sa->initiator
204214478Srpaulo		    && memcmp(spii, sa->spii, 8) == 0
205214478Srpaulo		    && memcmp(spir, sa->spir, 8) == 0)
206214478Srpaulo			break;
207214478Srpaulo	}
208214478Srpaulo
209214478Srpaulo	if(sa == NULL) return 0;
210214478Srpaulo	if(sa->evp == NULL) return 0;
211214478Srpaulo
212214478Srpaulo	/*
213214478Srpaulo	 * remove authenticator, and see if we still have something to
214214478Srpaulo	 * work with
215214478Srpaulo	 */
216214478Srpaulo	end = end - sa->authlen;
217214478Srpaulo	iv  = buf;
218214478Srpaulo	buf = buf + sa->ivlen;
219214478Srpaulo	len = end-buf;
220214478Srpaulo
221214478Srpaulo	if(end <= buf) return 0;
222214478Srpaulo
223313537Sglebius	ctx = EVP_CIPHER_CTX_new();
224313537Sglebius	if (ctx == NULL)
225313537Sglebius		return 0;
226327234Semaste	if (set_cipher_parameters(ctx, sa->evp, sa->secret, NULL, 0) < 0)
227214478Srpaulo		(*ndo->ndo_warning)(ndo, "espkey init failed");
228327234Semaste	set_cipher_parameters(ctx, NULL, NULL, iv, 0);
229327234Semaste	/*
230356341Scy	 * Allocate buffers for the encrypted and decrypted data.
231356341Scy	 * Both buffers' sizes must be a multiple of the cipher block
232356341Scy	 * size, and the output buffer must be separate from the input
233356341Scy	 * buffer.
234327234Semaste	 */
235327234Semaste	block_size = (unsigned int)EVP_CIPHER_CTX_block_size(ctx);
236356341Scy	buffer_size = len + (block_size - len % block_size);
237356341Scy
238356341Scy	/*
239356341Scy	 * Attempt to allocate the input buffer.
240356341Scy	 */
241356341Scy	input_buffer = (u_char *)malloc(buffer_size);
242356341Scy	if (input_buffer == NULL) {
243356341Scy		EVP_CIPHER_CTX_free(ctx);
244356341Scy		(*ndo->ndo_error)(ndo, "can't allocate memory for encrypted data buffer");
245356341Scy	}
246356341Scy	/*
247356341Scy	 * Copy the input data to the encrypted data buffer, and pad it
248356341Scy	 * with zeroes.
249356341Scy	 */
250356341Scy	memcpy(input_buffer, buf, len);
251356341Scy	memset(input_buffer + len, 0, buffer_size - len);
252356341Scy
253356341Scy	/*
254356341Scy	 * Attempt to allocate the output buffer.
255356341Scy	 */
256356341Scy	output_buffer = (u_char *)malloc(buffer_size);
257327234Semaste	if (output_buffer == NULL) {
258356341Scy		free(input_buffer);
259327234Semaste		EVP_CIPHER_CTX_free(ctx);
260356341Scy		(*ndo->ndo_error)(ndo, "can't allocate memory for decryption buffer");
261327234Semaste	}
262356341Scy	EVP_Cipher(ctx, output_buffer, input_buffer, len);
263313537Sglebius	EVP_CIPHER_CTX_free(ctx);
264214478Srpaulo
265327234Semaste	/*
266327234Semaste	 * XXX - of course this is wrong, because buf is a const buffer,
267327234Semaste	 * but changing this would require a more complicated fix.
268327234Semaste	 */
269327234Semaste	memcpy(__DECONST(u_char *, buf), output_buffer, len);
270356341Scy	free(input_buffer);
271327234Semaste	free(output_buffer);
272327234Semaste
273214478Srpaulo	ndo->ndo_packetp = buf;
274214478Srpaulo	ndo->ndo_snapend = end;
275214478Srpaulo
276214478Srpaulo	return 1;
277214478Srpaulo}
278276788SdelphijUSES_APPLE_RST
279214478Srpaulo
280146773Ssamstatic void esp_print_addsa(netdissect_options *ndo,
281146773Ssam			    struct sa_list *sa, int sa_def)
282127668Sbms{
283127668Sbms	/* copy the "sa" */
28498524Sfenner
285127668Sbms	struct sa_list *nsa;
28698524Sfenner
287127668Sbms	nsa = (struct sa_list *)malloc(sizeof(struct sa_list));
288127668Sbms	if (nsa == NULL)
289146773Ssam		(*ndo->ndo_error)(ndo, "ran out of memory to allocate sa structure");
29098524Sfenner
291127668Sbms	*nsa = *sa;
29298524Sfenner
293127668Sbms	if (sa_def)
294146773Ssam		ndo->ndo_sa_default = nsa;
295127668Sbms
296146773Ssam	nsa->next = ndo->ndo_sa_list_head;
297146773Ssam	ndo->ndo_sa_list_head = nsa;
298127668Sbms}
299127668Sbms
300127668Sbms
301147899Ssamstatic u_int hexdigit(netdissect_options *ndo, char hex)
30298524Sfenner{
303127668Sbms	if (hex >= '0' && hex <= '9')
30498524Sfenner		return (hex - '0');
305127668Sbms	else if (hex >= 'A' && hex <= 'F')
30698524Sfenner		return (hex - 'A' + 10);
307127668Sbms	else if (hex >= 'a' && hex <= 'f')
30898524Sfenner		return (hex - 'a' + 10);
309127668Sbms	else {
310146773Ssam		(*ndo->ndo_error)(ndo, "invalid hex digit %c in espsecret\n", hex);
31198524Sfenner	}
31298524Sfenner}
31398524Sfenner
314147899Ssamstatic u_int hex2byte(netdissect_options *ndo, char *hexstring)
31598524Sfenner{
316147899Ssam	u_int byte;
31798524Sfenner
318146773Ssam	byte = (hexdigit(ndo, hexstring[0]) << 4) + hexdigit(ndo, hexstring[1]);
31998524Sfenner	return byte;
32098524Sfenner}
32198524Sfenner
322127668Sbms/*
323214478Srpaulo * returns size of binary, 0 on failure.
324214478Srpaulo */
325214478Srpaulostatic
326214478Srpauloint espprint_decode_hex(netdissect_options *ndo,
327214478Srpaulo			u_char *binbuf, unsigned int binbuf_len,
328214478Srpaulo			char *hex)
329214478Srpaulo{
330214478Srpaulo	unsigned int len;
331214478Srpaulo	int i;
332214478Srpaulo
333214478Srpaulo	len = strlen(hex) / 2;
334276788Sdelphij
335214478Srpaulo	if (len > binbuf_len) {
336214478Srpaulo		(*ndo->ndo_warning)(ndo, "secret is too big: %d\n", len);
337214478Srpaulo		return 0;
338214478Srpaulo	}
339276788Sdelphij
340214478Srpaulo	i = 0;
341214478Srpaulo	while (hex[0] != '\0' && hex[1]!='\0') {
342214478Srpaulo		binbuf[i] = hex2byte(ndo, hex);
343214478Srpaulo		hex += 2;
344214478Srpaulo		i++;
345214478Srpaulo	}
346214478Srpaulo
347214478Srpaulo	return i;
348214478Srpaulo}
349214478Srpaulo
350214478Srpaulo/*
351127668Sbms * decode the form:    SPINUM@IP <tab> ALGONAME:0xsecret
352214478Srpaulo */
353214478Srpaulo
354276788SdelphijUSES_APPLE_DEPRECATED_API
355214478Srpaulostatic int
356214478Srpauloespprint_decode_encalgo(netdissect_options *ndo,
357214478Srpaulo			char *decode, struct sa_list *sa)
358214478Srpaulo{
359214478Srpaulo	size_t i;
360214478Srpaulo	const EVP_CIPHER *evp;
361214478Srpaulo	int authlen = 0;
362214478Srpaulo	char *colon, *p;
363276788Sdelphij
364214478Srpaulo	colon = strchr(decode, ':');
365214478Srpaulo	if (colon == NULL) {
366214478Srpaulo		(*ndo->ndo_warning)(ndo, "failed to decode espsecret: %s\n", decode);
367214478Srpaulo		return 0;
368214478Srpaulo	}
369214478Srpaulo	*colon = '\0';
370276788Sdelphij
371214478Srpaulo	if (strlen(decode) > strlen("-hmac96") &&
372214478Srpaulo	    !strcmp(decode + strlen(decode) - strlen("-hmac96"),
373214478Srpaulo		    "-hmac96")) {
374214478Srpaulo		p = strstr(decode, "-hmac96");
375214478Srpaulo		*p = '\0';
376214478Srpaulo		authlen = 12;
377214478Srpaulo	}
378214478Srpaulo	if (strlen(decode) > strlen("-cbc") &&
379214478Srpaulo	    !strcmp(decode + strlen(decode) - strlen("-cbc"), "-cbc")) {
380214478Srpaulo		p = strstr(decode, "-cbc");
381214478Srpaulo		*p = '\0';
382214478Srpaulo	}
383214478Srpaulo	evp = EVP_get_cipherbyname(decode);
384214478Srpaulo
385214478Srpaulo	if (!evp) {
386214478Srpaulo		(*ndo->ndo_warning)(ndo, "failed to find cipher algo %s\n", decode);
387214478Srpaulo		sa->evp = NULL;
388214478Srpaulo		sa->authlen = 0;
389214478Srpaulo		sa->ivlen = 0;
390214478Srpaulo		return 0;
391214478Srpaulo	}
392276788Sdelphij
393214478Srpaulo	sa->evp = evp;
394214478Srpaulo	sa->authlen = authlen;
395214478Srpaulo	sa->ivlen = EVP_CIPHER_iv_length(evp);
396276788Sdelphij
397214478Srpaulo	colon++;
398214478Srpaulo	if (colon[0] == '0' && colon[1] == 'x') {
399214478Srpaulo		/* decode some hex! */
400214478Srpaulo
401214478Srpaulo		colon += 2;
402214478Srpaulo		sa->secretlen = espprint_decode_hex(ndo, sa->secret, sizeof(sa->secret), colon);
403214478Srpaulo		if(sa->secretlen == 0) return 0;
404214478Srpaulo	} else {
405214478Srpaulo		i = strlen(colon);
406276788Sdelphij
407214478Srpaulo		if (i < sizeof(sa->secret)) {
408214478Srpaulo			memcpy(sa->secret, colon, i);
409214478Srpaulo			sa->secretlen = i;
410214478Srpaulo		} else {
411214478Srpaulo			memcpy(sa->secret, colon, sizeof(sa->secret));
412214478Srpaulo			sa->secretlen = sizeof(sa->secret);
413214478Srpaulo		}
414214478Srpaulo	}
415214478Srpaulo
416214478Srpaulo	return 1;
417214478Srpaulo}
418276788SdelphijUSES_APPLE_RST
419214478Srpaulo
420214478Srpaulo/*
421356341Scy * for the moment, ignore the auth algorithm, just hard code the authenticator
422214478Srpaulo * length. Need to research how openssl looks up HMAC stuff.
423214478Srpaulo */
424214478Srpaulostatic int
425214478Srpauloespprint_decode_authalgo(netdissect_options *ndo,
426214478Srpaulo			 char *decode, struct sa_list *sa)
427214478Srpaulo{
428214478Srpaulo	char *colon;
429214478Srpaulo
430214478Srpaulo	colon = strchr(decode, ':');
431214478Srpaulo	if (colon == NULL) {
432214478Srpaulo		(*ndo->ndo_warning)(ndo, "failed to decode espsecret: %s\n", decode);
433214478Srpaulo		return 0;
434214478Srpaulo	}
435214478Srpaulo	*colon = '\0';
436276788Sdelphij
437313537Sglebius	if(ascii_strcasecmp(colon,"sha1") == 0 ||
438313537Sglebius	   ascii_strcasecmp(colon,"md5") == 0) {
439214478Srpaulo		sa->authlen = 12;
440214478Srpaulo	}
441214478Srpaulo	return 1;
442214478Srpaulo}
443214478Srpaulo
444214478Srpaulostatic void esp_print_decode_ikeline(netdissect_options *ndo, char *line,
445214478Srpaulo				     const char *file, int lineno)
446214478Srpaulo{
447214478Srpaulo	/* it's an IKEv2 secret, store it instead */
448214478Srpaulo	struct sa_list sa1;
449214478Srpaulo
450214478Srpaulo	char *init;
451214478Srpaulo	char *icookie, *rcookie;
452214478Srpaulo	int   ilen, rlen;
453214478Srpaulo	char *authkey;
454214478Srpaulo	char *enckey;
455276788Sdelphij
456214478Srpaulo	init = strsep(&line, " \t");
457214478Srpaulo	icookie = strsep(&line, " \t");
458214478Srpaulo	rcookie = strsep(&line, " \t");
459214478Srpaulo	authkey = strsep(&line, " \t");
460214478Srpaulo	enckey  = strsep(&line, " \t");
461276788Sdelphij
462214478Srpaulo	/* if any fields are missing */
463214478Srpaulo	if(!init || !icookie || !rcookie || !authkey || !enckey) {
464214478Srpaulo		(*ndo->ndo_warning)(ndo, "print_esp: failed to find all fields for ikev2 at %s:%u",
465214478Srpaulo				    file, lineno);
466276788Sdelphij
467214478Srpaulo		return;
468214478Srpaulo	}
469276788Sdelphij
470214478Srpaulo	ilen = strlen(icookie);
471214478Srpaulo	rlen = strlen(rcookie);
472214478Srpaulo
473214478Srpaulo	if((init[0]!='I' && init[0]!='R')
474214478Srpaulo	   || icookie[0]!='0' || icookie[1]!='x'
475214478Srpaulo	   || rcookie[0]!='0' || rcookie[1]!='x'
476214478Srpaulo	   || ilen!=18
477214478Srpaulo	   || rlen!=18) {
478214478Srpaulo		(*ndo->ndo_warning)(ndo, "print_esp: line %s:%u improperly formatted.",
479214478Srpaulo				    file, lineno);
480214478Srpaulo
481214478Srpaulo		(*ndo->ndo_warning)(ndo, "init=%s icookie=%s(%u) rcookie=%s(%u)",
482214478Srpaulo				    init, icookie, ilen, rcookie, rlen);
483276788Sdelphij
484214478Srpaulo		return;
485214478Srpaulo	}
486214478Srpaulo
487214478Srpaulo	sa1.spi = 0;
488214478Srpaulo	sa1.initiator = (init[0] == 'I');
489214478Srpaulo	if(espprint_decode_hex(ndo, sa1.spii, sizeof(sa1.spii), icookie+2)!=8)
490214478Srpaulo		return;
491214478Srpaulo
492214478Srpaulo	if(espprint_decode_hex(ndo, sa1.spir, sizeof(sa1.spir), rcookie+2)!=8)
493214478Srpaulo		return;
494214478Srpaulo
495214478Srpaulo	if(!espprint_decode_encalgo(ndo, enckey, &sa1)) return;
496214478Srpaulo
497214478Srpaulo	if(!espprint_decode_authalgo(ndo, authkey, &sa1)) return;
498276788Sdelphij
499214478Srpaulo	esp_print_addsa(ndo, &sa1, FALSE);
500214478Srpaulo}
501214478Srpaulo
502214478Srpaulo/*
503127668Sbms *
504127668Sbms * special form: file /name
505127668Sbms * causes us to go read from this file instead.
506127668Sbms *
507127668Sbms */
508214478Srpaulostatic void esp_print_decode_onesecret(netdissect_options *ndo, char *line,
509214478Srpaulo				       const char *file, int lineno)
51098524Sfenner{
511127668Sbms	struct sa_list sa1;
512127668Sbms	int sa_def;
51398524Sfenner
514127668Sbms	char *spikey;
515127668Sbms	char *decode;
51698524Sfenner
517127668Sbms	spikey = strsep(&line, " \t");
518127668Sbms	sa_def = 0;
519127668Sbms	memset(&sa1, 0, sizeof(struct sa_list));
520127668Sbms
521127668Sbms	/* if there is only one token, then it is an algo:key token */
522127668Sbms	if (line == NULL) {
523127668Sbms		decode = spikey;
524127668Sbms		spikey = NULL;
525276788Sdelphij		/* sa1.daddr.version = 0; */
526127668Sbms		/* memset(&sa1.daddr, 0, sizeof(sa1.daddr)); */
527127668Sbms		/* sa1.spi = 0; */
528127668Sbms		sa_def    = 1;
529127668Sbms	} else
530127668Sbms		decode = line;
531127668Sbms
532313537Sglebius	if (spikey && ascii_strcasecmp(spikey, "file") == 0) {
533127668Sbms		/* open file and read it */
534127668Sbms		FILE *secretfile;
535127668Sbms		char  fileline[1024];
536313537Sglebius		int   subfile_lineno=0;
537127668Sbms		char  *nl;
538214478Srpaulo		char *filename = line;
539127668Sbms
540214478Srpaulo		secretfile = fopen(filename, FOPEN_READ_TXT);
541127668Sbms		if (secretfile == NULL) {
542313537Sglebius			(*ndo->ndo_error)(ndo, "print_esp: can't open %s: %s\n",
543313537Sglebius			    filename, strerror(errno));
544127668Sbms		}
545127668Sbms
546127668Sbms		while (fgets(fileline, sizeof(fileline)-1, secretfile) != NULL) {
547313537Sglebius			subfile_lineno++;
548127668Sbms			/* remove newline from the line */
549127668Sbms			nl = strchr(fileline, '\n');
550127668Sbms			if (nl)
551127668Sbms				*nl = '\0';
552127668Sbms			if (fileline[0] == '#') continue;
553127668Sbms			if (fileline[0] == '\0') continue;
554127668Sbms
555313537Sglebius			esp_print_decode_onesecret(ndo, fileline, filename, subfile_lineno);
556127668Sbms		}
557127668Sbms		fclose(secretfile);
558127668Sbms
55998524Sfenner		return;
56098524Sfenner	}
56198524Sfenner
562313537Sglebius	if (spikey && ascii_strcasecmp(spikey, "ikev2") == 0) {
563214478Srpaulo		esp_print_decode_ikeline(ndo, line, file, lineno);
564214478Srpaulo		return;
565276788Sdelphij	}
566214478Srpaulo
567127668Sbms	if (spikey) {
568276788Sdelphij
569127668Sbms		char *spistr, *foo;
570276788Sdelphij		uint32_t spino;
571276788Sdelphij
572127668Sbms		spistr = strsep(&spikey, "@");
573356341Scy		if (spistr == NULL) {
574356341Scy			(*ndo->ndo_warning)(ndo, "print_esp: failed to find the @ token");
575356341Scy			return;
576356341Scy		}
577276788Sdelphij
578127668Sbms		spino = strtoul(spistr, &foo, 0);
579127668Sbms		if (spistr == foo || !spikey) {
580146773Ssam			(*ndo->ndo_warning)(ndo, "print_esp: failed to decode spi# %s\n", foo);
581127668Sbms			return;
582127668Sbms		}
583276788Sdelphij
584127668Sbms		sa1.spi = spino;
585276788Sdelphij
586313537Sglebius		if (strtoaddr6(spikey, &sa1.daddr.in6) == 1) {
587276788Sdelphij			sa1.daddr_version = 6;
588313537Sglebius		} else if (strtoaddr(spikey, &sa1.daddr.in4) == 1) {
589313537Sglebius			sa1.daddr_version = 4;
590313537Sglebius		} else {
591313537Sglebius			(*ndo->ndo_warning)(ndo, "print_esp: can not decode IP# %s\n", spikey);
592313537Sglebius			return;
593313537Sglebius		}
59498524Sfenner	}
59598524Sfenner
596127668Sbms	if (decode) {
597127668Sbms		/* skip any blank spaces */
598127668Sbms		while (isspace((unsigned char)*decode))
599127668Sbms			decode++;
600276788Sdelphij
601214478Srpaulo		if(!espprint_decode_encalgo(ndo, decode, &sa1)) {
602127668Sbms			return;
60398524Sfenner		}
60498524Sfenner	}
605127668Sbms
606146773Ssam	esp_print_addsa(ndo, &sa1, sa_def);
60798524Sfenner}
60898524Sfenner
609276788SdelphijUSES_APPLE_DEPRECATED_API
610214478Srpaulostatic void esp_init(netdissect_options *ndo _U_)
611127668Sbms{
612313537Sglebius	/*
613313537Sglebius	 * 0.9.6 doesn't appear to define OPENSSL_API_COMPAT, so
614313537Sglebius	 * we check whether it's undefined or it's less than the
615313537Sglebius	 * value for 1.1.0.
616313537Sglebius	 */
617313537Sglebius#if !defined(OPENSSL_API_COMPAT) || OPENSSL_API_COMPAT < 0x10100000L
618214478Srpaulo	OpenSSL_add_all_algorithms();
619313537Sglebius#endif
620214478Srpaulo	EVP_add_cipher_alias(SN_des_ede3_cbc, "3des");
621214478Srpaulo}
622276788SdelphijUSES_APPLE_RST
623214478Srpaulo
624214478Srpaulovoid esp_print_decodesecret(netdissect_options *ndo)
625214478Srpaulo{
626127668Sbms	char *line;
627127668Sbms	char *p;
628214478Srpaulo	static int initialized = 0;
629127668Sbms
630214478Srpaulo	if (!initialized) {
631214478Srpaulo		esp_init(ndo);
632214478Srpaulo		initialized = 1;
633214478Srpaulo	}
634214478Srpaulo
635146773Ssam	p = ndo->ndo_espsecret;
636127668Sbms
637214478Srpaulo	while (p && p[0] != '\0') {
638127668Sbms		/* pick out the first line or first thing until a comma */
639214478Srpaulo		if ((line = strsep(&p, "\n,")) == NULL) {
640214478Srpaulo			line = p;
641214478Srpaulo			p = NULL;
642127668Sbms		}
643127668Sbms
644214478Srpaulo		esp_print_decode_onesecret(ndo, line, "cmdline", 0);
645127668Sbms	}
646214478Srpaulo
647214478Srpaulo	ndo->ndo_espsecret = NULL;
648127668Sbms}
649127668Sbms
650127668Sbms#endif
651127668Sbms
652276788Sdelphij#ifdef HAVE_LIBCRYPTO
653276788SdelphijUSES_APPLE_DEPRECATED_API
654276788Sdelphij#endif
65556893Sfennerint
656146773Ssamesp_print(netdissect_options *ndo,
657146773Ssam	  const u_char *bp, const int length, const u_char *bp2
658127668Sbms#ifndef HAVE_LIBCRYPTO
659127668Sbms	_U_
660127668Sbms#endif
661127668Sbms	,
662127668Sbms	int *nhdr
663127668Sbms#ifndef HAVE_LIBCRYPTO
664127668Sbms	_U_
665127668Sbms#endif
666127668Sbms	,
667127668Sbms	int *padlen
668127668Sbms#ifndef HAVE_LIBCRYPTO
669127668Sbms	_U_
670127668Sbms#endif
671127668Sbms	)
67256893Sfenner{
673127668Sbms	register const struct newesp *esp;
67456893Sfenner	register const u_char *ep;
675127668Sbms#ifdef HAVE_LIBCRYPTO
676313537Sglebius	const struct ip *ip;
677127668Sbms	struct sa_list *sa = NULL;
678313537Sglebius	const struct ip6_hdr *ip6 = NULL;
67956893Sfenner	int advance;
68056893Sfenner	int len;
681147899Ssam	u_char *secret;
68256893Sfenner	int ivlen = 0;
683313537Sglebius	const u_char *ivoff;
684313537Sglebius	const u_char *p;
685313537Sglebius	EVP_CIPHER_CTX *ctx;
686356341Scy	unsigned int block_size, buffer_size;
687356341Scy	u_char *input_buffer, *output_buffer;
688127668Sbms#endif
689127668Sbms
690313537Sglebius	esp = (const struct newesp *)bp;
691127668Sbms
692127668Sbms#ifdef HAVE_LIBCRYPTO
69398524Sfenner	secret = NULL;
694127668Sbms	advance = 0;
695127668Sbms#endif
696127668Sbms
69798524Sfenner#if 0
69898524Sfenner	/* keep secret out of a register */
69998524Sfenner	p = (u_char *)&secret;
70098524Sfenner#endif
70198524Sfenner
70275115Sfenner	/* 'ep' points to the end of available data. */
703146773Ssam	ep = ndo->ndo_snapend;
70456893Sfenner
705313537Sglebius	if ((const u_char *)(esp + 1) >= ep) {
706276788Sdelphij		ND_PRINT((ndo, "[|ESP]"));
70756893Sfenner		goto fail;
70856893Sfenner	}
709276788Sdelphij	ND_PRINT((ndo, "ESP(spi=0x%08x", EXTRACT_32BITS(&esp->esp_spi)));
710276788Sdelphij	ND_PRINT((ndo, ",seq=0x%x)", EXTRACT_32BITS(&esp->esp_seq)));
711276788Sdelphij	ND_PRINT((ndo, ", length %u", length));
71256893Sfenner
713127668Sbms#ifndef HAVE_LIBCRYPTO
714127668Sbms	goto fail;
715127668Sbms#else
716127668Sbms	/* initiailize SAs */
717146773Ssam	if (ndo->ndo_sa_list_head == NULL) {
718146773Ssam		if (!ndo->ndo_espsecret)
719127668Sbms			goto fail;
72056893Sfenner
721146773Ssam		esp_print_decodesecret(ndo);
72256893Sfenner	}
723127668Sbms
724146773Ssam	if (ndo->ndo_sa_list_head == NULL)
72598524Sfenner		goto fail;
72656893Sfenner
727313537Sglebius	ip = (const struct ip *)bp2;
72875115Sfenner	switch (IP_V(ip)) {
72956893Sfenner	case 6:
730313537Sglebius		ip6 = (const struct ip6_hdr *)bp2;
73156893Sfenner		/* we do not attempt to decrypt jumbograms */
732127668Sbms		if (!EXTRACT_16BITS(&ip6->ip6_plen))
73356893Sfenner			goto fail;
73456893Sfenner		/* if we can't get nexthdr, we do not need to decrypt it */
735127668Sbms		len = sizeof(struct ip6_hdr) + EXTRACT_16BITS(&ip6->ip6_plen);
736127668Sbms
737127668Sbms		/* see if we can find the SA, and if so, decode it */
738146773Ssam		for (sa = ndo->ndo_sa_list_head; sa != NULL; sa = sa->next) {
739214478Srpaulo			if (sa->spi == EXTRACT_32BITS(&esp->esp_spi) &&
740276788Sdelphij			    sa->daddr_version == 6 &&
741276788Sdelphij			    UNALIGNED_MEMCMP(&sa->daddr.in6, &ip6->ip6_dst,
742127668Sbms				   sizeof(struct in6_addr)) == 0) {
743127668Sbms				break;
744127668Sbms			}
745127668Sbms		}
74656893Sfenner		break;
74756893Sfenner	case 4:
74898524Sfenner		/* nexthdr & padding are in the last fragment */
749127668Sbms		if (EXTRACT_16BITS(&ip->ip_off) & IP_MF)
75098524Sfenner			goto fail;
751127668Sbms		len = EXTRACT_16BITS(&ip->ip_len);
752127668Sbms
753127668Sbms		/* see if we can find the SA, and if so, decode it */
754146773Ssam		for (sa = ndo->ndo_sa_list_head; sa != NULL; sa = sa->next) {
755214478Srpaulo			if (sa->spi == EXTRACT_32BITS(&esp->esp_spi) &&
756276788Sdelphij			    sa->daddr_version == 4 &&
757276788Sdelphij			    UNALIGNED_MEMCMP(&sa->daddr.in4, &ip->ip_dst,
758276788Sdelphij				   sizeof(struct in_addr)) == 0) {
759127668Sbms				break;
760127668Sbms			}
761127668Sbms		}
76256893Sfenner		break;
76356893Sfenner	default:
76456893Sfenner		goto fail;
76556893Sfenner	}
76656893Sfenner
767127668Sbms	/* if we didn't find the specific one, then look for
768127668Sbms	 * an unspecified one.
769127668Sbms	 */
770127668Sbms	if (sa == NULL)
771146773Ssam		sa = ndo->ndo_sa_default;
772276788Sdelphij
773127668Sbms	/* if not found fail */
774127668Sbms	if (sa == NULL)
775127668Sbms		goto fail;
776127668Sbms
77756893Sfenner	/* if we can't get nexthdr, we do not need to decrypt it */
77856893Sfenner	if (ep - bp2 < len)
77956893Sfenner		goto fail;
780127668Sbms	if (ep - bp2 > len) {
781127668Sbms		/* FCS included at end of frame (NetBSD 1.6 or later) */
782127668Sbms		ep = bp2 + len;
783127668Sbms	}
78456893Sfenner
785327234Semaste	/* pointer to the IV, if there is one */
786313537Sglebius	ivoff = (const u_char *)(esp + 1) + 0;
787327234Semaste	/* length of the IV, if there is one; 0, if there isn't */
788127668Sbms	ivlen = sa->ivlen;
789127668Sbms	secret = sa->secret;
790146773Ssam	ep = ep - sa->authlen;
79156893Sfenner
792127668Sbms	if (sa->evp) {
793313537Sglebius		ctx = EVP_CIPHER_CTX_new();
794313537Sglebius		if (ctx != NULL) {
795327234Semaste			if (set_cipher_parameters(ctx, sa->evp, secret, NULL, 0) < 0)
796313537Sglebius				(*ndo->ndo_warning)(ndo, "espkey init failed");
79756893Sfenner
798313537Sglebius			p = ivoff;
799327234Semaste			set_cipher_parameters(ctx, NULL, NULL, p, 0);
800327234Semaste			len = ep - (p + ivlen);
801327234Semaste
802327234Semaste			/*
803356341Scy			 * Allocate buffers for the encrypted and decrypted
804356341Scy			 * data.  Both buffers' sizes must be a multiple of
805356341Scy			 * the cipher block size, and the output buffer must
806356341Scy			 * be separate from the input buffer.
807327234Semaste			 */
808327234Semaste			block_size = (unsigned int)EVP_CIPHER_CTX_block_size(ctx);
809356341Scy			buffer_size = len + (block_size - len % block_size);
810356341Scy
811356341Scy			/*
812356341Scy			 * Attempt to allocate the input buffer.
813356341Scy			 */
814356341Scy			input_buffer = (u_char *)malloc(buffer_size);
815356341Scy			if (input_buffer == NULL) {
816356341Scy				EVP_CIPHER_CTX_free(ctx);
817356341Scy				(*ndo->ndo_error)(ndo, "can't allocate memory for encrypted data buffer");
818356341Scy			}
819356341Scy			/*
820356341Scy			 * Copy the input data to the encrypted data buffer,
821356341Scy			 * and pad it with zeroes.
822356341Scy			 */
823356341Scy			memcpy(input_buffer, p + ivlen, len);
824356341Scy			memset(input_buffer + len, 0, buffer_size - len);
825356341Scy
826356341Scy			/*
827356341Scy			 * Attempt to allocate the output buffer.
828356341Scy			 */
829356341Scy			output_buffer = (u_char *)malloc(buffer_size);
830327234Semaste			if (output_buffer == NULL) {
831356341Scy				free(input_buffer);
832327234Semaste				EVP_CIPHER_CTX_free(ctx);
833356341Scy				(*ndo->ndo_error)(ndo, "can't allocate memory for decryption buffer");
834327234Semaste			}
835327234Semaste
836356341Scy			EVP_Cipher(ctx, output_buffer, input_buffer, len);
837356341Scy			free(input_buffer);
838313537Sglebius			EVP_CIPHER_CTX_free(ctx);
839327234Semaste			/*
840327234Semaste			 * XXX - of course this is wrong, because buf is a
841327234Semaste			 * const buffer, but changing this would require a
842327234Semaste			 * more complicated fix.
843327234Semaste			 */
844327234Semaste			memcpy(__DECONST(u_char *, p + ivlen), output_buffer, len);
845327234Semaste			free(output_buffer);
846313537Sglebius			advance = ivoff - (const u_char *)esp + ivlen;
847313537Sglebius		} else
848313537Sglebius			advance = sizeof(struct newesp);
849127668Sbms	} else
850127668Sbms		advance = sizeof(struct newesp);
85156893Sfenner
85256893Sfenner	/* sanity check for pad length */
85356893Sfenner	if (ep - bp < *(ep - 2))
85456893Sfenner		goto fail;
85556893Sfenner
85698524Sfenner	if (padlen)
85798524Sfenner		*padlen = *(ep - 2) + 2;
85898524Sfenner
85956893Sfenner	if (nhdr)
86056893Sfenner		*nhdr = *(ep - 1);
86156893Sfenner
862276788Sdelphij	ND_PRINT((ndo, ": "));
86356893Sfenner	return advance;
864127668Sbms#endif
86556893Sfenner
86656893Sfennerfail:
867127668Sbms	return -1;
86856893Sfenner}
869276788Sdelphij#ifdef HAVE_LIBCRYPTO
870276788SdelphijUSES_APPLE_RST
871276788Sdelphij#endif
872146773Ssam
873146773Ssam/*
874146773Ssam * Local Variables:
875146773Ssam * c-style: whitesmith
876146773Ssam * c-basic-offset: 8
877146773Ssam * End:
878146773Ssam */
879