xref: /freebsd/contrib/tcpdump/print-esp.c (revision 0a7e5f1f02aad2ff5fff1c60f44c6975fd07e1d9)
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 
243340d773SGleb Smirnoff /* \summary: IPSEC Encapsulating Security Payload (ESP) printer */
253340d773SGleb Smirnoff 
26ee67461eSJoseph Mingrone #include <config.h>
27b0453382SBill Fenner 
28ee67461eSJoseph Mingrone #include "netdissect-stdinc.h"
295b0fe478SBruce M Simpson 
303c602fabSXin LI #include <string.h>
319afd0c29SBill Fenner #include <stdlib.h>
32b0453382SBill Fenner 
33685295f4SBill Fenner #ifdef HAVE_LIBCRYPTO
345b0fe478SBruce M Simpson #include <openssl/evp.h>
35b0453382SBill Fenner #endif
36b0453382SBill Fenner 
373340d773SGleb Smirnoff #include "netdissect.h"
385b0fe478SBruce M Simpson #include "extract.h"
39b0453382SBill Fenner 
40ee67461eSJoseph Mingrone #include "diag-control.h"
41ee67461eSJoseph Mingrone 
42ee67461eSJoseph Mingrone #ifdef HAVE_LIBCRYPTO
43ee67461eSJoseph Mingrone #include "strtoaddr.h"
443340d773SGleb Smirnoff #include "ascii_strcasecmp.h"
45ee67461eSJoseph Mingrone #endif
463340d773SGleb Smirnoff 
473340d773SGleb Smirnoff #include "ip.h"
483340d773SGleb Smirnoff #include "ip6.h"
493340d773SGleb Smirnoff 
503c602fabSXin LI /*
513c602fabSXin LI  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
523c602fabSXin LI  * All rights reserved.
533c602fabSXin LI  *
543c602fabSXin LI  * Redistribution and use in source and binary forms, with or without
553c602fabSXin LI  * modification, are permitted provided that the following conditions
563c602fabSXin LI  * are met:
573c602fabSXin LI  * 1. Redistributions of source code must retain the above copyright
583c602fabSXin LI  *    notice, this list of conditions and the following disclaimer.
593c602fabSXin LI  * 2. Redistributions in binary form must reproduce the above copyright
603c602fabSXin LI  *    notice, this list of conditions and the following disclaimer in the
613c602fabSXin LI  *    documentation and/or other materials provided with the distribution.
623c602fabSXin LI  * 3. Neither the name of the project nor the names of its contributors
633c602fabSXin LI  *    may be used to endorse or promote products derived from this software
643c602fabSXin LI  *    without specific prior written permission.
653c602fabSXin LI  *
663c602fabSXin LI  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
673c602fabSXin LI  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
683c602fabSXin LI  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
693c602fabSXin LI  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
703c602fabSXin LI  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
713c602fabSXin LI  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
723c602fabSXin LI  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
733c602fabSXin LI  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
743c602fabSXin LI  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
753c602fabSXin LI  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
763c602fabSXin LI  * SUCH DAMAGE.
773c602fabSXin LI  */
783c602fabSXin LI 
793c602fabSXin LI /*
803c602fabSXin LI  * RFC1827/2406 Encapsulated Security Payload.
813c602fabSXin LI  */
823c602fabSXin LI 
833c602fabSXin LI struct newesp {
84ee67461eSJoseph Mingrone 	nd_uint32_t	esp_spi;	/* ESP */
85ee67461eSJoseph Mingrone 	nd_uint32_t	esp_seq;	/* Sequence number */
863c602fabSXin LI 	/*variable size*/		/* (IV and) Payload data */
873c602fabSXin LI 	/*variable size*/		/* padding */
883c602fabSXin LI 	/*8bit*/			/* pad size */
893c602fabSXin LI 	/*8bit*/			/* next header */
903c602fabSXin LI 	/*8bit*/			/* next header */
913c602fabSXin LI 	/*variable size, 32bit bound*/	/* Authentication data */
925b0fe478SBruce M Simpson };
93a90e161bSBill Fenner 
945b0fe478SBruce M Simpson #ifdef HAVE_LIBCRYPTO
953c602fabSXin LI union inaddr_u {
96ee67461eSJoseph Mingrone 	nd_ipv4 in4;
97ee67461eSJoseph Mingrone 	nd_ipv6 in6;
983c602fabSXin LI };
995b0fe478SBruce M Simpson struct sa_list {
1005b0fe478SBruce M Simpson 	struct sa_list	*next;
1013c602fabSXin LI 	u_int		daddr_version;
1023c602fabSXin LI 	union inaddr_u	daddr;
1033c602fabSXin LI 	uint32_t	spi;          /* if == 0, then IKEv2 */
10427df3f5dSRui Paulo 	int             initiator;
10527df3f5dSRui Paulo 	u_char          spii[8];      /* for IKEv2 */
10627df3f5dSRui Paulo 	u_char          spir[8];
1075b0fe478SBruce M Simpson 	const EVP_CIPHER *evp;
108ee67461eSJoseph Mingrone 	u_int		ivlen;
109a90e161bSBill Fenner 	int		authlen;
11027df3f5dSRui Paulo 	u_char          authsecret[256];
11127df3f5dSRui Paulo 	int             authsecret_len;
112f4d0c64aSSam Leffler 	u_char		secret[256];  /* is that big enough for all secrets? */
1135b0fe478SBruce M Simpson 	int		secretlen;
114a90e161bSBill Fenner };
115a90e161bSBill Fenner 
1163340d773SGleb Smirnoff #ifndef HAVE_EVP_CIPHER_CTX_NEW
1173340d773SGleb Smirnoff /*
1183340d773SGleb Smirnoff  * Allocate an EVP_CIPHER_CTX.
1193340d773SGleb Smirnoff  * Used if we have an older version of OpenSSL that doesn't provide
1203340d773SGleb Smirnoff  * routines to allocate and free them.
1213340d773SGleb Smirnoff  */
1223340d773SGleb Smirnoff static EVP_CIPHER_CTX *
EVP_CIPHER_CTX_new(void)1233340d773SGleb Smirnoff EVP_CIPHER_CTX_new(void)
1243340d773SGleb Smirnoff {
1253340d773SGleb Smirnoff 	EVP_CIPHER_CTX *ctx;
1263340d773SGleb Smirnoff 
1273340d773SGleb Smirnoff 	ctx = malloc(sizeof(*ctx));
1283340d773SGleb Smirnoff 	if (ctx == NULL)
1293340d773SGleb Smirnoff 		return (NULL);
1303340d773SGleb Smirnoff 	memset(ctx, 0, sizeof(*ctx));
1313340d773SGleb Smirnoff 	return (ctx);
1323340d773SGleb Smirnoff }
1333340d773SGleb Smirnoff 
1343340d773SGleb Smirnoff static void
EVP_CIPHER_CTX_free(EVP_CIPHER_CTX * ctx)1353340d773SGleb Smirnoff EVP_CIPHER_CTX_free(EVP_CIPHER_CTX *ctx)
1363340d773SGleb Smirnoff {
1373340d773SGleb Smirnoff 	EVP_CIPHER_CTX_cleanup(ctx);
1383340d773SGleb Smirnoff 	free(ctx);
1393340d773SGleb Smirnoff }
1403340d773SGleb Smirnoff #endif
1413340d773SGleb Smirnoff 
142ee67461eSJoseph Mingrone #ifdef HAVE_EVP_DECRYPTINIT_EX
1430bff6a5aSEd Maste /*
144ee67461eSJoseph Mingrone  * Initialize the cipher by calling EVP_DecryptInit_ex(), because
145ee67461eSJoseph Mingrone  * calling EVP_DecryptInit() will reset the cipher context, clearing
1460bff6a5aSEd Maste  * the cipher, so calling it twice, with the second call having a
147ee67461eSJoseph Mingrone  * null cipher, will clear the already-set cipher.  EVP_DecryptInit_ex(),
1480bff6a5aSEd Maste  * however, won't reset the cipher context, so you can use it to specify
149ee67461eSJoseph Mingrone  * the IV in a second call after a first call to EVP_DecryptInit_ex()
1500bff6a5aSEd Maste  * to set the cipher and the key.
1510bff6a5aSEd Maste  *
1520bff6a5aSEd Maste  * XXX - is there some reason why we need to make two calls?
1530bff6a5aSEd Maste  */
1540bff6a5aSEd Maste static int
set_cipher_parameters(EVP_CIPHER_CTX * ctx,const EVP_CIPHER * cipher,const unsigned char * key,const unsigned char * iv)1550bff6a5aSEd Maste set_cipher_parameters(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
1560bff6a5aSEd Maste 		      const unsigned char *key,
157ee67461eSJoseph Mingrone 		      const unsigned char *iv)
1580bff6a5aSEd Maste {
159ee67461eSJoseph Mingrone 	return EVP_DecryptInit_ex(ctx, cipher, NULL, key, iv);
1600bff6a5aSEd Maste }
1610bff6a5aSEd Maste #else
1620bff6a5aSEd Maste /*
163ee67461eSJoseph Mingrone  * Initialize the cipher by calling EVP_DecryptInit(), because we don't
164ee67461eSJoseph Mingrone  * have EVP_DecryptInit_ex(); we rely on it not trashing the context.
1650bff6a5aSEd Maste  */
1660bff6a5aSEd Maste static int
set_cipher_parameters(EVP_CIPHER_CTX * ctx,const EVP_CIPHER * cipher,const unsigned char * key,const unsigned char * iv)1670bff6a5aSEd Maste set_cipher_parameters(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
1680bff6a5aSEd Maste 		      const unsigned char *key,
169ee67461eSJoseph Mingrone 		      const unsigned char *iv)
1700bff6a5aSEd Maste {
171ee67461eSJoseph Mingrone 	return EVP_DecryptInit(ctx, cipher, key, iv);
1720bff6a5aSEd Maste }
1730bff6a5aSEd Maste #endif
1740bff6a5aSEd Maste 
175ee67461eSJoseph Mingrone static u_char *
do_decrypt(netdissect_options * ndo,const char * caller,struct sa_list * sa,const u_char * iv,const u_char * ct,unsigned int ctlen)176ee67461eSJoseph Mingrone do_decrypt(netdissect_options *ndo, const char *caller, struct sa_list *sa,
177ee67461eSJoseph Mingrone     const u_char *iv, const u_char *ct, unsigned int ctlen)
178ee67461eSJoseph Mingrone {
179ee67461eSJoseph Mingrone 	EVP_CIPHER_CTX *ctx;
180ee67461eSJoseph Mingrone 	unsigned int block_size;
181ee67461eSJoseph Mingrone 	unsigned int ptlen;
182ee67461eSJoseph Mingrone 	u_char *pt;
183ee67461eSJoseph Mingrone 	int len;
184ee67461eSJoseph Mingrone 
185ee67461eSJoseph Mingrone 	ctx = EVP_CIPHER_CTX_new();
186ee67461eSJoseph Mingrone 	if (ctx == NULL) {
18727df3f5dSRui Paulo 		/*
188ee67461eSJoseph Mingrone 		 * Failed to initialize the cipher context.
189ee67461eSJoseph Mingrone 		 * From a look at the OpenSSL code, this appears to
190ee67461eSJoseph Mingrone 		 * mean "couldn't allocate memory for the cipher context";
191ee67461eSJoseph Mingrone 		 * note that we're not passing any parameters, so there's
192ee67461eSJoseph Mingrone 		 * not much else it can mean.
19327df3f5dSRui Paulo 		 */
194ee67461eSJoseph Mingrone 		(*ndo->ndo_error)(ndo, S_ERR_ND_MEM_ALLOC,
195ee67461eSJoseph Mingrone 		    "%s: can't allocate memory for cipher context", caller);
196ee67461eSJoseph Mingrone 		return NULL;
197ee67461eSJoseph Mingrone 	}
198ee67461eSJoseph Mingrone 
199ee67461eSJoseph Mingrone 	if (set_cipher_parameters(ctx, sa->evp, sa->secret, NULL) < 0) {
200ee67461eSJoseph Mingrone 		EVP_CIPHER_CTX_free(ctx);
201ee67461eSJoseph Mingrone 		(*ndo->ndo_warning)(ndo, "%s: espkey init failed", caller);
202ee67461eSJoseph Mingrone 		return NULL;
203ee67461eSJoseph Mingrone 	}
204ee67461eSJoseph Mingrone 	if (set_cipher_parameters(ctx, NULL, NULL, iv) < 0) {
205ee67461eSJoseph Mingrone 		EVP_CIPHER_CTX_free(ctx);
206ee67461eSJoseph Mingrone 		(*ndo->ndo_warning)(ndo, "%s: IV init failed", caller);
207ee67461eSJoseph Mingrone 		return NULL;
208ee67461eSJoseph Mingrone 	}
209ee67461eSJoseph Mingrone 
210ee67461eSJoseph Mingrone 	/*
211ee67461eSJoseph Mingrone 	 * At least as I read RFC 5996 section 3.14 and RFC 4303 section 2.4,
212ee67461eSJoseph Mingrone 	 * if the cipher has a block size of which the ciphertext's size must
213ee67461eSJoseph Mingrone 	 * be a multiple, the payload must be padded to make that happen, so
214ee67461eSJoseph Mingrone 	 * the ciphertext length must be a multiple of the block size.  Fail
215ee67461eSJoseph Mingrone 	 * if that's not the case.
216ee67461eSJoseph Mingrone 	 */
217ee67461eSJoseph Mingrone 	block_size = (unsigned int)EVP_CIPHER_CTX_block_size(ctx);
218ee67461eSJoseph Mingrone 	if ((ctlen % block_size) != 0) {
219ee67461eSJoseph Mingrone 		EVP_CIPHER_CTX_free(ctx);
220ee67461eSJoseph Mingrone 		(*ndo->ndo_warning)(ndo,
221ee67461eSJoseph Mingrone 		    "%s: ciphertext size %u is not a multiple of the cipher block size %u",
222ee67461eSJoseph Mingrone 		    caller, ctlen, block_size);
223ee67461eSJoseph Mingrone 		return NULL;
224ee67461eSJoseph Mingrone 	}
225ee67461eSJoseph Mingrone 
226ee67461eSJoseph Mingrone 	/*
227ee67461eSJoseph Mingrone 	 * Attempt to allocate a buffer for the decrypted data, because
228ee67461eSJoseph Mingrone 	 * we can't decrypt on top of the input buffer.
229ee67461eSJoseph Mingrone 	 */
230ee67461eSJoseph Mingrone 	ptlen = ctlen;
231ee67461eSJoseph Mingrone 	pt = (u_char *)calloc(1, ptlen);
232ee67461eSJoseph Mingrone 	if (pt == NULL) {
233ee67461eSJoseph Mingrone 		EVP_CIPHER_CTX_free(ctx);
234ee67461eSJoseph Mingrone 		(*ndo->ndo_error)(ndo, S_ERR_ND_MEM_ALLOC,
235ee67461eSJoseph Mingrone 		    "%s: can't allocate memory for decryption buffer", caller);
236ee67461eSJoseph Mingrone 		return NULL;
237ee67461eSJoseph Mingrone 	}
238ee67461eSJoseph Mingrone 
239ee67461eSJoseph Mingrone 	/*
240ee67461eSJoseph Mingrone 	 * The size of the ciphertext handed to us is a multiple of the
241ee67461eSJoseph Mingrone 	 * cipher block size, so we don't need to worry about padding.
242ee67461eSJoseph Mingrone 	 */
243ee67461eSJoseph Mingrone 	if (!EVP_CIPHER_CTX_set_padding(ctx, 0)) {
244ee67461eSJoseph Mingrone 		free(pt);
245ee67461eSJoseph Mingrone 		EVP_CIPHER_CTX_free(ctx);
246ee67461eSJoseph Mingrone 		(*ndo->ndo_warning)(ndo,
247ee67461eSJoseph Mingrone 		    "%s: EVP_CIPHER_CTX_set_padding failed", caller);
248ee67461eSJoseph Mingrone 		return NULL;
249ee67461eSJoseph Mingrone 	}
250ee67461eSJoseph Mingrone 	if (!EVP_DecryptUpdate(ctx, pt, &len, ct, ctlen)) {
251ee67461eSJoseph Mingrone 		free(pt);
252ee67461eSJoseph Mingrone 		EVP_CIPHER_CTX_free(ctx);
253ee67461eSJoseph Mingrone 		(*ndo->ndo_warning)(ndo, "%s: EVP_DecryptUpdate failed",
254ee67461eSJoseph Mingrone 		    caller);
255ee67461eSJoseph Mingrone 		return NULL;
256ee67461eSJoseph Mingrone 	}
257ee67461eSJoseph Mingrone 	EVP_CIPHER_CTX_free(ctx);
258ee67461eSJoseph Mingrone 	return pt;
259ee67461eSJoseph Mingrone }
260ee67461eSJoseph Mingrone 
261ee67461eSJoseph Mingrone /*
262ee67461eSJoseph Mingrone  * This will allocate a new buffer containing the decrypted data.
263ee67461eSJoseph Mingrone  * It returns 1 on success and 0 on failure.
264ee67461eSJoseph Mingrone  *
265ee67461eSJoseph Mingrone  * It will push the new buffer and the values of ndo->ndo_packetp and
266ee67461eSJoseph Mingrone  * ndo->ndo_snapend onto the buffer stack, and change ndo->ndo_packetp
267ee67461eSJoseph Mingrone  * and ndo->ndo_snapend to refer to the new buffer.
268ee67461eSJoseph Mingrone  *
269ee67461eSJoseph Mingrone  * Our caller must pop the buffer off the stack when it's finished
270ee67461eSJoseph Mingrone  * dissecting anything in it and before it does any dissection of
271ee67461eSJoseph Mingrone  * anything in the old buffer.  That will free the new buffer.
272ee67461eSJoseph Mingrone  */
273ee67461eSJoseph Mingrone DIAG_OFF_DEPRECATION
esp_decrypt_buffer_by_ikev2_print(netdissect_options * ndo,int initiator,const u_char spii[8],const u_char spir[8],const u_char * buf,const u_char * end)274ee67461eSJoseph Mingrone int esp_decrypt_buffer_by_ikev2_print(netdissect_options *ndo,
27527df3f5dSRui Paulo 				      int initiator,
276ee67461eSJoseph Mingrone 				      const u_char spii[8],
277ee67461eSJoseph Mingrone 				      const u_char spir[8],
2783340d773SGleb Smirnoff 				      const u_char *buf, const u_char *end)
27927df3f5dSRui Paulo {
28027df3f5dSRui Paulo 	struct sa_list *sa;
2813340d773SGleb Smirnoff 	const u_char *iv;
282ee67461eSJoseph Mingrone 	const u_char *ct;
283ee67461eSJoseph Mingrone 	unsigned int ctlen;
284ee67461eSJoseph Mingrone 	u_char *pt;
28527df3f5dSRui Paulo 
28627df3f5dSRui Paulo 	/* initiator arg is any non-zero value */
28727df3f5dSRui Paulo 	if(initiator) initiator=1;
28827df3f5dSRui Paulo 
28927df3f5dSRui Paulo 	/* see if we can find the SA, and if so, decode it */
29027df3f5dSRui Paulo 	for (sa = ndo->ndo_sa_list_head; sa != NULL; sa = sa->next) {
29127df3f5dSRui Paulo 		if (sa->spi == 0
29227df3f5dSRui Paulo 		    && initiator == sa->initiator
29327df3f5dSRui Paulo 		    && memcmp(spii, sa->spii, 8) == 0
29427df3f5dSRui Paulo 		    && memcmp(spir, sa->spir, 8) == 0)
29527df3f5dSRui Paulo 			break;
29627df3f5dSRui Paulo 	}
29727df3f5dSRui Paulo 
29827df3f5dSRui Paulo 	if(sa == NULL) return 0;
29927df3f5dSRui Paulo 	if(sa->evp == NULL) return 0;
30027df3f5dSRui Paulo 
30127df3f5dSRui Paulo 	/*
30227df3f5dSRui Paulo 	 * remove authenticator, and see if we still have something to
30327df3f5dSRui Paulo 	 * work with
30427df3f5dSRui Paulo 	 */
30527df3f5dSRui Paulo 	end = end - sa->authlen;
30627df3f5dSRui Paulo 	iv  = buf;
307ee67461eSJoseph Mingrone 	ct = iv + sa->ivlen;
308ee67461eSJoseph Mingrone 	ctlen = end-ct;
30927df3f5dSRui Paulo 
310ee67461eSJoseph Mingrone 	if(end <= ct) return 0;
31127df3f5dSRui Paulo 
312ee67461eSJoseph Mingrone 	pt = do_decrypt(ndo, __func__, sa, iv,
313ee67461eSJoseph Mingrone 	    ct, ctlen);
314ee67461eSJoseph Mingrone 	if (pt == NULL)
3153340d773SGleb Smirnoff 		return 0;
31639e421e8SCy Schubert 
31739e421e8SCy Schubert 	/*
318ee67461eSJoseph Mingrone 	 * Switch to the output buffer for dissection, and save it
319ee67461eSJoseph Mingrone 	 * on the buffer stack so it can be freed; our caller must
320ee67461eSJoseph Mingrone 	 * pop it when done.
32139e421e8SCy Schubert 	 */
322ee67461eSJoseph Mingrone 	if (!nd_push_buffer(ndo, pt, pt, ctlen)) {
323ee67461eSJoseph Mingrone 		free(pt);
324ee67461eSJoseph Mingrone 		(*ndo->ndo_error)(ndo, S_ERR_ND_MEM_ALLOC,
325ee67461eSJoseph Mingrone 			"%s: can't push buffer on buffer stack", __func__);
3260bff6a5aSEd Maste 	}
32727df3f5dSRui Paulo 
32827df3f5dSRui Paulo 	return 1;
32927df3f5dSRui Paulo }
330ee67461eSJoseph Mingrone DIAG_ON_DEPRECATION
33127df3f5dSRui Paulo 
esp_print_addsa(netdissect_options * ndo,const struct sa_list * sa,int sa_def)3321de50e9fSSam Leffler static void esp_print_addsa(netdissect_options *ndo,
333ee67461eSJoseph Mingrone 			    const struct sa_list *sa, int sa_def)
3345b0fe478SBruce M Simpson {
3355b0fe478SBruce M Simpson 	/* copy the "sa" */
3365b0fe478SBruce M Simpson 
3375b0fe478SBruce M Simpson 	struct sa_list *nsa;
3385b0fe478SBruce M Simpson 
339ee67461eSJoseph Mingrone 	/* malloc() return used in a 'struct sa_list': do not free() */
3405b0fe478SBruce M Simpson 	nsa = (struct sa_list *)malloc(sizeof(struct sa_list));
3415b0fe478SBruce M Simpson 	if (nsa == NULL)
342ee67461eSJoseph Mingrone 		(*ndo->ndo_error)(ndo, S_ERR_ND_MEM_ALLOC,
343ee67461eSJoseph Mingrone 				  "%s: malloc", __func__);
3445b0fe478SBruce M Simpson 
3455b0fe478SBruce M Simpson 	*nsa = *sa;
3465b0fe478SBruce M Simpson 
3475b0fe478SBruce M Simpson 	if (sa_def)
3481de50e9fSSam Leffler 		ndo->ndo_sa_default = nsa;
3495b0fe478SBruce M Simpson 
3501de50e9fSSam Leffler 	nsa->next = ndo->ndo_sa_list_head;
3511de50e9fSSam Leffler 	ndo->ndo_sa_list_head = nsa;
3525b0fe478SBruce M Simpson }
3535b0fe478SBruce M Simpson 
354a90e161bSBill Fenner 
hexdigit(netdissect_options * ndo,char hex)355f4d0c64aSSam Leffler static u_int hexdigit(netdissect_options *ndo, char hex)
356a90e161bSBill Fenner {
3575b0fe478SBruce M Simpson 	if (hex >= '0' && hex <= '9')
358a90e161bSBill Fenner 		return (hex - '0');
3595b0fe478SBruce M Simpson 	else if (hex >= 'A' && hex <= 'F')
360a90e161bSBill Fenner 		return (hex - 'A' + 10);
3615b0fe478SBruce M Simpson 	else if (hex >= 'a' && hex <= 'f')
362a90e161bSBill Fenner 		return (hex - 'a' + 10);
3635b0fe478SBruce M Simpson 	else {
364ee67461eSJoseph Mingrone 		(*ndo->ndo_error)(ndo, S_ERR_ND_ESP_SECRET,
365ee67461eSJoseph Mingrone 				  "invalid hex digit %c in espsecret\n", hex);
366a90e161bSBill Fenner 	}
367a90e161bSBill Fenner }
368a90e161bSBill Fenner 
hex2byte(netdissect_options * ndo,char * hexstring)369f4d0c64aSSam Leffler static u_int hex2byte(netdissect_options *ndo, char *hexstring)
370a90e161bSBill Fenner {
371f4d0c64aSSam Leffler 	u_int byte;
372a90e161bSBill Fenner 
3731de50e9fSSam Leffler 	byte = (hexdigit(ndo, hexstring[0]) << 4) + hexdigit(ndo, hexstring[1]);
374a90e161bSBill Fenner 	return byte;
375a90e161bSBill Fenner }
376a90e161bSBill Fenner 
3775b0fe478SBruce M Simpson /*
37827df3f5dSRui Paulo  * returns size of binary, 0 on failure.
37927df3f5dSRui Paulo  */
380ee67461eSJoseph Mingrone static int
espprint_decode_hex(netdissect_options * ndo,u_char * binbuf,unsigned int binbuf_len,char * hex)381ee67461eSJoseph Mingrone espprint_decode_hex(netdissect_options *ndo,
382ee67461eSJoseph Mingrone 		    u_char *binbuf, unsigned int binbuf_len, char *hex)
38327df3f5dSRui Paulo {
38427df3f5dSRui Paulo 	unsigned int len;
38527df3f5dSRui Paulo 	int i;
38627df3f5dSRui Paulo 
38727df3f5dSRui Paulo 	len = strlen(hex) / 2;
38827df3f5dSRui Paulo 
38927df3f5dSRui Paulo 	if (len > binbuf_len) {
390ee67461eSJoseph Mingrone 		(*ndo->ndo_warning)(ndo, "secret is too big: %u\n", len);
39127df3f5dSRui Paulo 		return 0;
39227df3f5dSRui Paulo 	}
39327df3f5dSRui Paulo 
39427df3f5dSRui Paulo 	i = 0;
39527df3f5dSRui Paulo 	while (hex[0] != '\0' && hex[1]!='\0') {
39627df3f5dSRui Paulo 		binbuf[i] = hex2byte(ndo, hex);
39727df3f5dSRui Paulo 		hex += 2;
39827df3f5dSRui Paulo 		i++;
39927df3f5dSRui Paulo 	}
40027df3f5dSRui Paulo 
40127df3f5dSRui Paulo 	return i;
40227df3f5dSRui Paulo }
40327df3f5dSRui Paulo 
40427df3f5dSRui Paulo /*
4055b0fe478SBruce M Simpson  * decode the form:    SPINUM@IP <tab> ALGONAME:0xsecret
40627df3f5dSRui Paulo  */
40727df3f5dSRui Paulo 
408ee67461eSJoseph Mingrone DIAG_OFF_DEPRECATION
40927df3f5dSRui Paulo static int
espprint_decode_encalgo(netdissect_options * ndo,char * decode,struct sa_list * sa)41027df3f5dSRui Paulo espprint_decode_encalgo(netdissect_options *ndo,
41127df3f5dSRui Paulo 			char *decode, struct sa_list *sa)
41227df3f5dSRui Paulo {
41327df3f5dSRui Paulo 	size_t i;
41427df3f5dSRui Paulo 	const EVP_CIPHER *evp;
41527df3f5dSRui Paulo 	int authlen = 0;
41627df3f5dSRui Paulo 	char *colon, *p;
417*0a7e5f1fSJoseph Mingrone 	const char *real_decode;
41827df3f5dSRui Paulo 
41927df3f5dSRui Paulo 	colon = strchr(decode, ':');
42027df3f5dSRui Paulo 	if (colon == NULL) {
42127df3f5dSRui Paulo 		(*ndo->ndo_warning)(ndo, "failed to decode espsecret: %s\n", decode);
42227df3f5dSRui Paulo 		return 0;
42327df3f5dSRui Paulo 	}
42427df3f5dSRui Paulo 	*colon = '\0';
42527df3f5dSRui Paulo 
42627df3f5dSRui Paulo 	if (strlen(decode) > strlen("-hmac96") &&
42727df3f5dSRui Paulo 	    !strcmp(decode + strlen(decode) - strlen("-hmac96"),
42827df3f5dSRui Paulo 		    "-hmac96")) {
42927df3f5dSRui Paulo 		p = strstr(decode, "-hmac96");
43027df3f5dSRui Paulo 		*p = '\0';
43127df3f5dSRui Paulo 		authlen = 12;
43227df3f5dSRui Paulo 	}
43327df3f5dSRui Paulo 	if (strlen(decode) > strlen("-cbc") &&
43427df3f5dSRui Paulo 	    !strcmp(decode + strlen(decode) - strlen("-cbc"), "-cbc")) {
43527df3f5dSRui Paulo 		p = strstr(decode, "-cbc");
43627df3f5dSRui Paulo 		*p = '\0';
43727df3f5dSRui Paulo 	}
438*0a7e5f1fSJoseph Mingrone 	/*
439*0a7e5f1fSJoseph Mingrone 	 * Not all versions of libcrypto support calls to add aliases
440*0a7e5f1fSJoseph Mingrone 	 * to ciphers - newer versions of libressl don't - so, instead
441*0a7e5f1fSJoseph Mingrone 	 * of making "3des" an alias for "des_ede3_cbc", if attempting
442*0a7e5f1fSJoseph Mingrone 	 * to get the cipher fails and the name is "3des", we try
443*0a7e5f1fSJoseph Mingrone 	 * "des_ede3_cbc".
444*0a7e5f1fSJoseph Mingrone 	 */
445*0a7e5f1fSJoseph Mingrone 	real_decode = decode;
446*0a7e5f1fSJoseph Mingrone 	if (strcmp(real_decode, "3des") == 0)
447*0a7e5f1fSJoseph Mingrone 		real_decode = "des-ede3-cbc";
448*0a7e5f1fSJoseph Mingrone 	evp = EVP_get_cipherbyname(real_decode);
44927df3f5dSRui Paulo 
45027df3f5dSRui Paulo 	if (!evp) {
451*0a7e5f1fSJoseph Mingrone 		if (decode != real_decode)
452*0a7e5f1fSJoseph Mingrone 			(*ndo->ndo_warning)(ndo, "failed to find cipher algo %s (%s)\n", real_decode, decode);
453*0a7e5f1fSJoseph Mingrone 		else
45427df3f5dSRui Paulo 			(*ndo->ndo_warning)(ndo, "failed to find cipher algo %s\n", decode);
45527df3f5dSRui Paulo 		sa->evp = NULL;
45627df3f5dSRui Paulo 		sa->authlen = 0;
45727df3f5dSRui Paulo 		sa->ivlen = 0;
45827df3f5dSRui Paulo 		return 0;
45927df3f5dSRui Paulo 	}
46027df3f5dSRui Paulo 
46127df3f5dSRui Paulo 	sa->evp = evp;
46227df3f5dSRui Paulo 	sa->authlen = authlen;
463ee67461eSJoseph Mingrone 	/* This returns an int, but it should never be negative */
46427df3f5dSRui Paulo 	sa->ivlen = EVP_CIPHER_iv_length(evp);
46527df3f5dSRui Paulo 
46627df3f5dSRui Paulo 	colon++;
46727df3f5dSRui Paulo 	if (colon[0] == '0' && colon[1] == 'x') {
46827df3f5dSRui Paulo 		/* decode some hex! */
46927df3f5dSRui Paulo 
47027df3f5dSRui Paulo 		colon += 2;
47127df3f5dSRui Paulo 		sa->secretlen = espprint_decode_hex(ndo, sa->secret, sizeof(sa->secret), colon);
47227df3f5dSRui Paulo 		if(sa->secretlen == 0) return 0;
47327df3f5dSRui Paulo 	} else {
47427df3f5dSRui Paulo 		i = strlen(colon);
47527df3f5dSRui Paulo 
47627df3f5dSRui Paulo 		if (i < sizeof(sa->secret)) {
47727df3f5dSRui Paulo 			memcpy(sa->secret, colon, i);
47827df3f5dSRui Paulo 			sa->secretlen = i;
47927df3f5dSRui Paulo 		} else {
48027df3f5dSRui Paulo 			memcpy(sa->secret, colon, sizeof(sa->secret));
48127df3f5dSRui Paulo 			sa->secretlen = sizeof(sa->secret);
48227df3f5dSRui Paulo 		}
48327df3f5dSRui Paulo 	}
48427df3f5dSRui Paulo 
48527df3f5dSRui Paulo 	return 1;
48627df3f5dSRui Paulo }
487ee67461eSJoseph Mingrone DIAG_ON_DEPRECATION
48827df3f5dSRui Paulo 
48927df3f5dSRui Paulo /*
49039e421e8SCy Schubert  * for the moment, ignore the auth algorithm, just hard code the authenticator
49127df3f5dSRui Paulo  * length. Need to research how openssl looks up HMAC stuff.
49227df3f5dSRui Paulo  */
49327df3f5dSRui Paulo static int
espprint_decode_authalgo(netdissect_options * ndo,char * decode,struct sa_list * sa)49427df3f5dSRui Paulo espprint_decode_authalgo(netdissect_options *ndo,
49527df3f5dSRui Paulo 			 char *decode, struct sa_list *sa)
49627df3f5dSRui Paulo {
49727df3f5dSRui Paulo 	char *colon;
49827df3f5dSRui Paulo 
49927df3f5dSRui Paulo 	colon = strchr(decode, ':');
50027df3f5dSRui Paulo 	if (colon == NULL) {
50127df3f5dSRui Paulo 		(*ndo->ndo_warning)(ndo, "failed to decode espsecret: %s\n", decode);
50227df3f5dSRui Paulo 		return 0;
50327df3f5dSRui Paulo 	}
50427df3f5dSRui Paulo 	*colon = '\0';
50527df3f5dSRui Paulo 
506ee67461eSJoseph Mingrone 	if(ascii_strcasecmp(decode,"sha1") == 0 ||
507ee67461eSJoseph Mingrone 	   ascii_strcasecmp(decode,"md5") == 0) {
50827df3f5dSRui Paulo 		sa->authlen = 12;
50927df3f5dSRui Paulo 	}
51027df3f5dSRui Paulo 	return 1;
51127df3f5dSRui Paulo }
51227df3f5dSRui Paulo 
esp_print_decode_ikeline(netdissect_options * ndo,char * line,const char * file,int lineno)51327df3f5dSRui Paulo static void esp_print_decode_ikeline(netdissect_options *ndo, char *line,
51427df3f5dSRui Paulo 				     const char *file, int lineno)
51527df3f5dSRui Paulo {
51627df3f5dSRui Paulo 	/* it's an IKEv2 secret, store it instead */
51727df3f5dSRui Paulo 	struct sa_list sa1;
51827df3f5dSRui Paulo 
51927df3f5dSRui Paulo 	char *init;
52027df3f5dSRui Paulo 	char *icookie, *rcookie;
52127df3f5dSRui Paulo 	int   ilen, rlen;
52227df3f5dSRui Paulo 	char *authkey;
52327df3f5dSRui Paulo 	char *enckey;
52427df3f5dSRui Paulo 
52527df3f5dSRui Paulo 	init = strsep(&line, " \t");
52627df3f5dSRui Paulo 	icookie = strsep(&line, " \t");
52727df3f5dSRui Paulo 	rcookie = strsep(&line, " \t");
52827df3f5dSRui Paulo 	authkey = strsep(&line, " \t");
52927df3f5dSRui Paulo 	enckey  = strsep(&line, " \t");
53027df3f5dSRui Paulo 
53127df3f5dSRui Paulo 	/* if any fields are missing */
53227df3f5dSRui Paulo 	if(!init || !icookie || !rcookie || !authkey || !enckey) {
53327df3f5dSRui Paulo 		(*ndo->ndo_warning)(ndo, "print_esp: failed to find all fields for ikev2 at %s:%u",
53427df3f5dSRui Paulo 				    file, lineno);
53527df3f5dSRui Paulo 
53627df3f5dSRui Paulo 		return;
53727df3f5dSRui Paulo 	}
53827df3f5dSRui Paulo 
53927df3f5dSRui Paulo 	ilen = strlen(icookie);
54027df3f5dSRui Paulo 	rlen = strlen(rcookie);
54127df3f5dSRui Paulo 
54227df3f5dSRui Paulo 	if((init[0]!='I' && init[0]!='R')
54327df3f5dSRui Paulo 	   || icookie[0]!='0' || icookie[1]!='x'
54427df3f5dSRui Paulo 	   || rcookie[0]!='0' || rcookie[1]!='x'
54527df3f5dSRui Paulo 	   || ilen!=18
54627df3f5dSRui Paulo 	   || rlen!=18) {
54727df3f5dSRui Paulo 		(*ndo->ndo_warning)(ndo, "print_esp: line %s:%u improperly formatted.",
54827df3f5dSRui Paulo 				    file, lineno);
54927df3f5dSRui Paulo 
55027df3f5dSRui Paulo 		(*ndo->ndo_warning)(ndo, "init=%s icookie=%s(%u) rcookie=%s(%u)",
55127df3f5dSRui Paulo 				    init, icookie, ilen, rcookie, rlen);
55227df3f5dSRui Paulo 
55327df3f5dSRui Paulo 		return;
55427df3f5dSRui Paulo 	}
55527df3f5dSRui Paulo 
55627df3f5dSRui Paulo 	sa1.spi = 0;
55727df3f5dSRui Paulo 	sa1.initiator = (init[0] == 'I');
55827df3f5dSRui Paulo 	if(espprint_decode_hex(ndo, sa1.spii, sizeof(sa1.spii), icookie+2)!=8)
55927df3f5dSRui Paulo 		return;
56027df3f5dSRui Paulo 
56127df3f5dSRui Paulo 	if(espprint_decode_hex(ndo, sa1.spir, sizeof(sa1.spir), rcookie+2)!=8)
56227df3f5dSRui Paulo 		return;
56327df3f5dSRui Paulo 
56427df3f5dSRui Paulo 	if(!espprint_decode_encalgo(ndo, enckey, &sa1)) return;
56527df3f5dSRui Paulo 
56627df3f5dSRui Paulo 	if(!espprint_decode_authalgo(ndo, authkey, &sa1)) return;
56727df3f5dSRui Paulo 
56827df3f5dSRui Paulo 	esp_print_addsa(ndo, &sa1, FALSE);
56927df3f5dSRui Paulo }
57027df3f5dSRui Paulo 
57127df3f5dSRui Paulo /*
5725b0fe478SBruce M Simpson  *
5735b0fe478SBruce M Simpson  * special form: file /name
5745b0fe478SBruce M Simpson  * causes us to go read from this file instead.
5755b0fe478SBruce M Simpson  *
5765b0fe478SBruce M Simpson  */
esp_print_decode_onesecret(netdissect_options * ndo,char * line,const char * file,int lineno)57727df3f5dSRui Paulo static void esp_print_decode_onesecret(netdissect_options *ndo, char *line,
57827df3f5dSRui Paulo 				       const char *file, int lineno)
579a90e161bSBill Fenner {
5805b0fe478SBruce M Simpson 	struct sa_list sa1;
5815b0fe478SBruce M Simpson 	int sa_def;
582a90e161bSBill Fenner 
5835b0fe478SBruce M Simpson 	char *spikey;
5845b0fe478SBruce M Simpson 	char *decode;
5855b0fe478SBruce M Simpson 
5865b0fe478SBruce M Simpson 	spikey = strsep(&line, " \t");
5875b0fe478SBruce M Simpson 	sa_def = 0;
5885b0fe478SBruce M Simpson 	memset(&sa1, 0, sizeof(struct sa_list));
5895b0fe478SBruce M Simpson 
5905b0fe478SBruce M Simpson 	/* if there is only one token, then it is an algo:key token */
5915b0fe478SBruce M Simpson 	if (line == NULL) {
5925b0fe478SBruce M Simpson 		decode = spikey;
5935b0fe478SBruce M Simpson 		spikey = NULL;
5943c602fabSXin LI 		/* sa1.daddr.version = 0; */
5955b0fe478SBruce M Simpson 		/* memset(&sa1.daddr, 0, sizeof(sa1.daddr)); */
5965b0fe478SBruce M Simpson 		/* sa1.spi = 0; */
5975b0fe478SBruce M Simpson 		sa_def    = 1;
5985b0fe478SBruce M Simpson 	} else
5995b0fe478SBruce M Simpson 		decode = line;
6005b0fe478SBruce M Simpson 
6013340d773SGleb Smirnoff 	if (spikey && ascii_strcasecmp(spikey, "file") == 0) {
6025b0fe478SBruce M Simpson 		/* open file and read it */
6035b0fe478SBruce M Simpson 		FILE *secretfile;
6045b0fe478SBruce M Simpson 		char  fileline[1024];
6053340d773SGleb Smirnoff 		int   subfile_lineno=0;
6065b0fe478SBruce M Simpson 		char  *nl;
60727df3f5dSRui Paulo 		char *filename = line;
6085b0fe478SBruce M Simpson 
60927df3f5dSRui Paulo 		secretfile = fopen(filename, FOPEN_READ_TXT);
6105b0fe478SBruce M Simpson 		if (secretfile == NULL) {
611ee67461eSJoseph Mingrone 			(*ndo->ndo_error)(ndo, S_ERR_ND_OPEN_FILE,
612ee67461eSJoseph Mingrone 					  "%s: can't open %s: %s\n",
613ee67461eSJoseph Mingrone 					  __func__, filename, strerror(errno));
6145b0fe478SBruce M Simpson 		}
6155b0fe478SBruce M Simpson 
6165b0fe478SBruce M Simpson 		while (fgets(fileline, sizeof(fileline)-1, secretfile) != NULL) {
6173340d773SGleb Smirnoff 			subfile_lineno++;
6185b0fe478SBruce M Simpson 			/* remove newline from the line */
6195b0fe478SBruce M Simpson 			nl = strchr(fileline, '\n');
6205b0fe478SBruce M Simpson 			if (nl)
6215b0fe478SBruce M Simpson 				*nl = '\0';
6225b0fe478SBruce M Simpson 			if (fileline[0] == '#') continue;
6235b0fe478SBruce M Simpson 			if (fileline[0] == '\0') continue;
6245b0fe478SBruce M Simpson 
6253340d773SGleb Smirnoff 			esp_print_decode_onesecret(ndo, fileline, filename, subfile_lineno);
6265b0fe478SBruce M Simpson 		}
6275b0fe478SBruce M Simpson 		fclose(secretfile);
6285b0fe478SBruce M Simpson 
629a90e161bSBill Fenner 		return;
630a90e161bSBill Fenner 	}
631a90e161bSBill Fenner 
6323340d773SGleb Smirnoff 	if (spikey && ascii_strcasecmp(spikey, "ikev2") == 0) {
63327df3f5dSRui Paulo 		esp_print_decode_ikeline(ndo, line, file, lineno);
63427df3f5dSRui Paulo 		return;
63527df3f5dSRui Paulo 	}
63627df3f5dSRui Paulo 
6375b0fe478SBruce M Simpson 	if (spikey) {
63827df3f5dSRui Paulo 
6395b0fe478SBruce M Simpson 		char *spistr, *foo;
6403c602fabSXin LI 		uint32_t spino;
6415b0fe478SBruce M Simpson 
6425b0fe478SBruce M Simpson 		spistr = strsep(&spikey, "@");
64339e421e8SCy Schubert 		if (spistr == NULL) {
64439e421e8SCy Schubert 			(*ndo->ndo_warning)(ndo, "print_esp: failed to find the @ token");
64539e421e8SCy Schubert 			return;
64639e421e8SCy Schubert 		}
6475b0fe478SBruce M Simpson 
6485b0fe478SBruce M Simpson 		spino = strtoul(spistr, &foo, 0);
6495b0fe478SBruce M Simpson 		if (spistr == foo || !spikey) {
6501de50e9fSSam Leffler 			(*ndo->ndo_warning)(ndo, "print_esp: failed to decode spi# %s\n", foo);
651a90e161bSBill Fenner 			return;
652a90e161bSBill Fenner 		}
653a90e161bSBill Fenner 
6545b0fe478SBruce M Simpson 		sa1.spi = spino;
6555b0fe478SBruce M Simpson 
6563340d773SGleb Smirnoff 		if (strtoaddr6(spikey, &sa1.daddr.in6) == 1) {
6573c602fabSXin LI 			sa1.daddr_version = 6;
6583340d773SGleb Smirnoff 		} else if (strtoaddr(spikey, &sa1.daddr.in4) == 1) {
6593c602fabSXin LI 			sa1.daddr_version = 4;
6605b0fe478SBruce M Simpson 		} else {
6611de50e9fSSam Leffler 			(*ndo->ndo_warning)(ndo, "print_esp: can not decode IP# %s\n", spikey);
6625b0fe478SBruce M Simpson 			return;
6635b0fe478SBruce M Simpson 		}
6645b0fe478SBruce M Simpson 	}
6655b0fe478SBruce M Simpson 
6665b0fe478SBruce M Simpson 	if (decode) {
6675b0fe478SBruce M Simpson 		/* skip any blank spaces */
668ee67461eSJoseph Mingrone 		while (*decode == ' ' || *decode == '\t' || *decode == '\r' || *decode == '\n')
6695b0fe478SBruce M Simpson 			decode++;
6705b0fe478SBruce M Simpson 
67127df3f5dSRui Paulo 		if(!espprint_decode_encalgo(ndo, decode, &sa1)) {
672a90e161bSBill Fenner 			return;
673a90e161bSBill Fenner 		}
674a90e161bSBill Fenner 	}
675a90e161bSBill Fenner 
6761de50e9fSSam Leffler 	esp_print_addsa(ndo, &sa1, sa_def);
6775b0fe478SBruce M Simpson }
6785b0fe478SBruce M Simpson 
679ee67461eSJoseph Mingrone DIAG_OFF_DEPRECATION
esp_init(netdissect_options * ndo _U_)6801de50e9fSSam Leffler static void esp_init(netdissect_options *ndo _U_)
6815b0fe478SBruce M Simpson {
6823340d773SGleb Smirnoff 	/*
6833340d773SGleb Smirnoff 	 * 0.9.6 doesn't appear to define OPENSSL_API_COMPAT, so
6843340d773SGleb Smirnoff 	 * we check whether it's undefined or it's less than the
6853340d773SGleb Smirnoff 	 * value for 1.1.0.
6863340d773SGleb Smirnoff 	 */
6873340d773SGleb Smirnoff #if !defined(OPENSSL_API_COMPAT) || OPENSSL_API_COMPAT < 0x10100000L
6885b0fe478SBruce M Simpson 	OpenSSL_add_all_algorithms();
6893340d773SGleb Smirnoff #endif
6905b0fe478SBruce M Simpson }
691ee67461eSJoseph Mingrone DIAG_ON_DEPRECATION
69227df3f5dSRui Paulo 
esp_decodesecret_print(netdissect_options * ndo)693ee67461eSJoseph Mingrone void esp_decodesecret_print(netdissect_options *ndo)
69427df3f5dSRui Paulo {
69527df3f5dSRui Paulo 	char *line;
69627df3f5dSRui Paulo 	char *p;
69727df3f5dSRui Paulo 	static int initialized = 0;
69827df3f5dSRui Paulo 
69927df3f5dSRui Paulo 	if (!initialized) {
70027df3f5dSRui Paulo 		esp_init(ndo);
70127df3f5dSRui Paulo 		initialized = 1;
70227df3f5dSRui Paulo 	}
70327df3f5dSRui Paulo 
70427df3f5dSRui Paulo 	p = ndo->ndo_espsecret;
70527df3f5dSRui Paulo 
70627df3f5dSRui Paulo 	while (p && p[0] != '\0') {
70727df3f5dSRui Paulo 		/* pick out the first line or first thing until a comma */
70827df3f5dSRui Paulo 		if ((line = strsep(&p, "\n,")) == NULL) {
70927df3f5dSRui Paulo 			line = p;
71027df3f5dSRui Paulo 			p = NULL;
71127df3f5dSRui Paulo 		}
71227df3f5dSRui Paulo 
71327df3f5dSRui Paulo 		esp_print_decode_onesecret(ndo, line, "cmdline", 0);
71427df3f5dSRui Paulo 	}
71527df3f5dSRui Paulo 
71627df3f5dSRui Paulo 	ndo->ndo_espsecret = NULL;
71727df3f5dSRui Paulo }
71827df3f5dSRui Paulo 
7195b0fe478SBruce M Simpson #endif
7205b0fe478SBruce M Simpson 
7213c602fabSXin LI #ifdef HAVE_LIBCRYPTO
722ee67461eSJoseph Mingrone #define USED_IF_LIBCRYPTO
723ee67461eSJoseph Mingrone #else
724ee67461eSJoseph Mingrone #define USED_IF_LIBCRYPTO _U_
7253c602fabSXin LI #endif
726ee67461eSJoseph Mingrone 
727ee67461eSJoseph Mingrone #ifdef HAVE_LIBCRYPTO
728ee67461eSJoseph Mingrone DIAG_OFF_DEPRECATION
729ee67461eSJoseph Mingrone #endif
730ee67461eSJoseph Mingrone void
esp_print(netdissect_options * ndo,const u_char * bp,u_int length,const u_char * bp2 USED_IF_LIBCRYPTO,u_int ver USED_IF_LIBCRYPTO,int fragmented USED_IF_LIBCRYPTO,u_int ttl_hl USED_IF_LIBCRYPTO)7311de50e9fSSam Leffler esp_print(netdissect_options *ndo,
732ee67461eSJoseph Mingrone 	  const u_char *bp, u_int length,
733ee67461eSJoseph Mingrone 	  const u_char *bp2 USED_IF_LIBCRYPTO,
734ee67461eSJoseph Mingrone 	  u_int ver USED_IF_LIBCRYPTO,
735ee67461eSJoseph Mingrone 	  int fragmented USED_IF_LIBCRYPTO,
736ee67461eSJoseph Mingrone 	  u_int ttl_hl USED_IF_LIBCRYPTO)
7375b0fe478SBruce M Simpson {
738ee67461eSJoseph Mingrone 	const struct newesp *esp;
739ee67461eSJoseph Mingrone 	const u_char *ep;
7405b0fe478SBruce M Simpson #ifdef HAVE_LIBCRYPTO
7413340d773SGleb Smirnoff 	const struct ip *ip;
7425b0fe478SBruce M Simpson 	struct sa_list *sa = NULL;
7433340d773SGleb Smirnoff 	const struct ip6_hdr *ip6 = NULL;
744ee67461eSJoseph Mingrone 	const u_char *iv;
745ee67461eSJoseph Mingrone 	u_int ivlen;
746ee67461eSJoseph Mingrone 	u_int payloadlen;
747ee67461eSJoseph Mingrone 	const u_char *ct;
748ee67461eSJoseph Mingrone 	u_char *pt;
749ee67461eSJoseph Mingrone 	u_int padlen;
750ee67461eSJoseph Mingrone 	u_int nh;
7515b0fe478SBruce M Simpson #endif
752b0453382SBill Fenner 
753ee67461eSJoseph Mingrone 	ndo->ndo_protocol = "esp";
7543340d773SGleb Smirnoff 	esp = (const struct newesp *)bp;
7555b0fe478SBruce M Simpson 
756685295f4SBill Fenner 	/* 'ep' points to the end of available data. */
7571de50e9fSSam Leffler 	ep = ndo->ndo_snapend;
758b0453382SBill Fenner 
7593340d773SGleb Smirnoff 	if ((const u_char *)(esp + 1) >= ep) {
760ee67461eSJoseph Mingrone 		nd_print_trunc(ndo);
761ee67461eSJoseph Mingrone 		return;
762b0453382SBill Fenner 	}
763ee67461eSJoseph Mingrone 	ND_PRINT("ESP(spi=0x%08x", GET_BE_U_4(esp->esp_spi));
764ee67461eSJoseph Mingrone 	ND_PRINT(",seq=0x%x)", GET_BE_U_4(esp->esp_seq));
765ee67461eSJoseph Mingrone 	ND_PRINT(", length %u", length);
766b0453382SBill Fenner 
767ee67461eSJoseph Mingrone #ifdef HAVE_LIBCRYPTO
768ee67461eSJoseph Mingrone 	/* initialize SAs */
7691de50e9fSSam Leffler 	if (ndo->ndo_sa_list_head == NULL) {
7701de50e9fSSam Leffler 		if (!ndo->ndo_espsecret)
771ee67461eSJoseph Mingrone 			return;
772b0453382SBill Fenner 
773ee67461eSJoseph Mingrone 		esp_decodesecret_print(ndo);
774a90e161bSBill Fenner 	}
7755b0fe478SBruce M Simpson 
7761de50e9fSSam Leffler 	if (ndo->ndo_sa_list_head == NULL)
777ee67461eSJoseph Mingrone 		return;
778b0453382SBill Fenner 
7793340d773SGleb Smirnoff 	ip = (const struct ip *)bp2;
780ee67461eSJoseph Mingrone 	switch (ver) {
781b0453382SBill Fenner 	case 6:
7823340d773SGleb Smirnoff 		ip6 = (const struct ip6_hdr *)bp2;
783b0453382SBill Fenner 		/* we do not attempt to decrypt jumbograms */
784ee67461eSJoseph Mingrone 		if (!GET_BE_U_2(ip6->ip6_plen))
785ee67461eSJoseph Mingrone 			return;
786ee67461eSJoseph Mingrone 		/* XXX - check whether it's fragmented? */
787b0453382SBill Fenner 		/* if we can't get nexthdr, we do not need to decrypt it */
7885b0fe478SBruce M Simpson 
7895b0fe478SBruce M Simpson 		/* see if we can find the SA, and if so, decode it */
7901de50e9fSSam Leffler 		for (sa = ndo->ndo_sa_list_head; sa != NULL; sa = sa->next) {
791ee67461eSJoseph Mingrone 			if (sa->spi == GET_BE_U_4(esp->esp_spi) &&
7923c602fabSXin LI 			    sa->daddr_version == 6 &&
7933c602fabSXin LI 			    UNALIGNED_MEMCMP(&sa->daddr.in6, &ip6->ip6_dst,
794ee67461eSJoseph Mingrone 				   sizeof(nd_ipv6)) == 0) {
7955b0fe478SBruce M Simpson 				break;
7965b0fe478SBruce M Simpson 			}
7975b0fe478SBruce M Simpson 		}
798b0453382SBill Fenner 		break;
799b0453382SBill Fenner 	case 4:
800a90e161bSBill Fenner 		/* nexthdr & padding are in the last fragment */
801ee67461eSJoseph Mingrone 		if (fragmented)
802ee67461eSJoseph Mingrone 			return;
8035b0fe478SBruce M Simpson 
8045b0fe478SBruce M Simpson 		/* see if we can find the SA, and if so, decode it */
8051de50e9fSSam Leffler 		for (sa = ndo->ndo_sa_list_head; sa != NULL; sa = sa->next) {
806ee67461eSJoseph Mingrone 			if (sa->spi == GET_BE_U_4(esp->esp_spi) &&
8073c602fabSXin LI 			    sa->daddr_version == 4 &&
8083c602fabSXin LI 			    UNALIGNED_MEMCMP(&sa->daddr.in4, &ip->ip_dst,
809ee67461eSJoseph Mingrone 				   sizeof(nd_ipv4)) == 0) {
8105b0fe478SBruce M Simpson 				break;
8115b0fe478SBruce M Simpson 			}
8125b0fe478SBruce M Simpson 		}
813b0453382SBill Fenner 		break;
814b0453382SBill Fenner 	default:
815ee67461eSJoseph Mingrone 		return;
816b0453382SBill Fenner 	}
817b0453382SBill Fenner 
8185b0fe478SBruce M Simpson 	/* if we didn't find the specific one, then look for
8195b0fe478SBruce M Simpson 	 * an unspecified one.
8205b0fe478SBruce M Simpson 	 */
8215b0fe478SBruce M Simpson 	if (sa == NULL)
8221de50e9fSSam Leffler 		sa = ndo->ndo_sa_default;
8235b0fe478SBruce M Simpson 
8245b0fe478SBruce M Simpson 	/* if not found fail */
8255b0fe478SBruce M Simpson 	if (sa == NULL)
826ee67461eSJoseph Mingrone 		return;
827b0453382SBill Fenner 
8280bff6a5aSEd Maste 	/* pointer to the IV, if there is one */
829ee67461eSJoseph Mingrone 	iv = (const u_char *)(esp + 1) + 0;
8300bff6a5aSEd Maste 	/* length of the IV, if there is one; 0, if there isn't */
8315b0fe478SBruce M Simpson 	ivlen = sa->ivlen;
832ee67461eSJoseph Mingrone 
833ee67461eSJoseph Mingrone 	/*
834ee67461eSJoseph Mingrone 	 * Get a pointer to the ciphertext.
835ee67461eSJoseph Mingrone 	 *
836ee67461eSJoseph Mingrone 	 * p points to the beginning of the payload, i.e. to the
837ee67461eSJoseph Mingrone 	 * initialization vector, so if we skip past the initialization
838ee67461eSJoseph Mingrone 	 * vector, it points to the beginning of the ciphertext.
839ee67461eSJoseph Mingrone 	 */
840ee67461eSJoseph Mingrone 	ct = iv + ivlen;
841ee67461eSJoseph Mingrone 
842ee67461eSJoseph Mingrone 	/*
843ee67461eSJoseph Mingrone 	 * Make sure the authentication data/integrity check value length
844ee67461eSJoseph Mingrone 	 * isn't bigger than the total amount of data available after
845ee67461eSJoseph Mingrone 	 * the ESP header and initialization vector is removed and,
846ee67461eSJoseph Mingrone 	 * if not, slice the authentication data/ICV off.
847ee67461eSJoseph Mingrone 	 */
848ee67461eSJoseph Mingrone 	if (ep - ct < sa->authlen) {
849ee67461eSJoseph Mingrone 		nd_print_trunc(ndo);
850ee67461eSJoseph Mingrone 		return;
851ee67461eSJoseph Mingrone 	}
8521de50e9fSSam Leffler 	ep = ep - sa->authlen;
853b0453382SBill Fenner 
854ee67461eSJoseph Mingrone 	/*
855ee67461eSJoseph Mingrone 	 * Calculate the length of the ciphertext.  ep points to
856ee67461eSJoseph Mingrone 	 * the beginning of the authentication data/integrity check
857ee67461eSJoseph Mingrone 	 * value, i.e. right past the end of the ciphertext;
858ee67461eSJoseph Mingrone 	 */
859ee67461eSJoseph Mingrone 	payloadlen = ep - ct;
8605b0fe478SBruce M Simpson 
861ee67461eSJoseph Mingrone 	if (sa->evp == NULL)
862ee67461eSJoseph Mingrone 		return;
8630bff6a5aSEd Maste 
8640bff6a5aSEd Maste 	/*
865ee67461eSJoseph Mingrone 	 * If the next header value is past the end of the available
866ee67461eSJoseph Mingrone 	 * data, we won't be able to fetch it once we've decrypted
867ee67461eSJoseph Mingrone 	 * the ciphertext, so there's no point in decrypting the data.
868ee67461eSJoseph Mingrone 	 *
869ee67461eSJoseph Mingrone 	 * Report it as truncation.
8700bff6a5aSEd Maste 	 */
871ee67461eSJoseph Mingrone 	if (!ND_TTEST_1(ep - 1)) {
872ee67461eSJoseph Mingrone 		nd_print_trunc(ndo);
873ee67461eSJoseph Mingrone 		return;
8740bff6a5aSEd Maste 	}
8750bff6a5aSEd Maste 
876ee67461eSJoseph Mingrone 	pt = do_decrypt(ndo, __func__, sa, iv, ct, payloadlen);
877ee67461eSJoseph Mingrone 	if (pt == NULL)
878ee67461eSJoseph Mingrone 		return;
879ee67461eSJoseph Mingrone 
8800bff6a5aSEd Maste 	/*
881ee67461eSJoseph Mingrone 	 * Switch to the output buffer for dissection, and
882ee67461eSJoseph Mingrone 	 * save it on the buffer stack so it can be freed.
8830bff6a5aSEd Maste 	 */
884ee67461eSJoseph Mingrone 	if (!nd_push_buffer(ndo, pt, pt, payloadlen)) {
885ee67461eSJoseph Mingrone 		free(pt);
886ee67461eSJoseph Mingrone 		(*ndo->ndo_error)(ndo, S_ERR_ND_MEM_ALLOC,
887ee67461eSJoseph Mingrone 			"%s: can't push buffer on buffer stack", __func__);
888ee67461eSJoseph Mingrone 	}
889b0453382SBill Fenner 
890ee67461eSJoseph Mingrone 	/*
891ee67461eSJoseph Mingrone 	 * Sanity check for pad length; if it, plus 2 for the pad
892ee67461eSJoseph Mingrone 	 * length and next header fields, is bigger than the ciphertext
893ee67461eSJoseph Mingrone 	 * length (which is also the plaintext length), it's too big.
894ee67461eSJoseph Mingrone 	 *
895ee67461eSJoseph Mingrone 	 * XXX - the check can fail if the packet is corrupt *or* if
896ee67461eSJoseph Mingrone 	 * it was not decrypted with the correct key, so that the
897ee67461eSJoseph Mingrone 	 * "plaintext" is not what was being sent.
898ee67461eSJoseph Mingrone 	 */
899ee67461eSJoseph Mingrone 	padlen = GET_U_1(pt + payloadlen - 2);
900ee67461eSJoseph Mingrone 	if (padlen + 2 > payloadlen) {
901ee67461eSJoseph Mingrone 		nd_print_trunc(ndo);
902ee67461eSJoseph Mingrone 		return;
903ee67461eSJoseph Mingrone 	}
904b0453382SBill Fenner 
905ee67461eSJoseph Mingrone 	/* Get the next header */
906ee67461eSJoseph Mingrone 	nh = GET_U_1(pt + payloadlen - 1);
907a90e161bSBill Fenner 
908ee67461eSJoseph Mingrone 	ND_PRINT(": ");
909b0453382SBill Fenner 
910ee67461eSJoseph Mingrone 	/*
911ee67461eSJoseph Mingrone 	 * Don't put padding + padding length(1 byte) + next header(1 byte)
912ee67461eSJoseph Mingrone 	 * in the buffer because they are not part of the plaintext to decode.
913ee67461eSJoseph Mingrone 	 */
914ee67461eSJoseph Mingrone 	if (!nd_push_snaplen(ndo, pt, payloadlen - (padlen + 2))) {
915ee67461eSJoseph Mingrone 		(*ndo->ndo_error)(ndo, S_ERR_ND_MEM_ALLOC,
916ee67461eSJoseph Mingrone 			"%s: can't push snaplen on buffer stack", __func__);
917ee67461eSJoseph Mingrone 	}
918ee67461eSJoseph Mingrone 
919ee67461eSJoseph Mingrone 	/* Now dissect the plaintext. */
920ee67461eSJoseph Mingrone 	ip_demux_print(ndo, pt, payloadlen - (padlen + 2), ver, fragmented,
921ee67461eSJoseph Mingrone 		       ttl_hl, nh, bp2);
922ee67461eSJoseph Mingrone 
923ee67461eSJoseph Mingrone 	/* Pop the buffer, freeing it. */
924ee67461eSJoseph Mingrone 	nd_pop_packet_info(ndo);
925ee67461eSJoseph Mingrone 	/* Pop the nd_push_snaplen */
926ee67461eSJoseph Mingrone 	nd_pop_packet_info(ndo);
9275b0fe478SBruce M Simpson #endif
928b0453382SBill Fenner }
9293c602fabSXin LI #ifdef HAVE_LIBCRYPTO
930ee67461eSJoseph Mingrone DIAG_ON_DEPRECATION
9313c602fabSXin LI #endif
932