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