print-esp.c revision 75115
1/*	$NetBSD: print-ah.c,v 1.4 1996/05/20 00:41:16 fvdl Exp $	*/
2
3/*
4 * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994
5 *	The Regents of the University of California.  All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that: (1) source code distributions
9 * retain the above copyright notice and this paragraph in its entirety, (2)
10 * distributions including binary code include the above copyright notice and
11 * this paragraph in its entirety in the documentation or other materials
12 * provided with the distribution, and (3) all advertising materials mentioning
13 * features or use of this software display the following acknowledgement:
14 * ``This product includes software developed by the University of California,
15 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
16 * the University nor the names of its contributors may be used to endorse
17 * or promote products derived from this software without specific prior
18 * written permission.
19 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
20 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
21 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
22 */
23
24#ifndef lint
25static const char rcsid[] =
26    "@(#) $Header: /tcpdump/master/tcpdump/print-esp.c,v 1.17 2000/12/12 09:58:41 itojun Exp $ (LBL)";
27#endif
28
29#ifdef HAVE_CONFIG_H
30#include "config.h"
31#endif
32
33#include <string.h>
34#include <sys/param.h>
35#include <sys/time.h>
36#include <sys/types.h>
37#include <sys/socket.h>
38
39#include <netinet/in.h>
40
41#ifdef HAVE_LIBCRYPTO
42#include <des.h>
43#include <blowfish.h>
44#ifdef HAVE_RC5_H
45#include <rc5.h>
46#endif
47#ifdef HAVE_CAST_H
48#include <cast.h>
49#endif
50#endif
51
52#include <stdio.h>
53
54#include "ip.h"
55#include "esp.h"
56#ifdef INET6
57#include "ip6.h"
58#endif
59
60#include "interface.h"
61#include "addrtoname.h"
62
63int
64esp_print(register const u_char *bp, register const u_char *bp2, int *nhdr)
65{
66	register const struct esp *esp;
67	register const u_char *ep;
68	u_int32_t spi;
69	enum { NONE, DESCBC, BLOWFISH, RC5, CAST128, DES3CBC } algo = NONE;
70	struct ip *ip = NULL;
71#ifdef INET6
72	struct ip6_hdr *ip6 = NULL;
73#endif
74	int advance;
75	int len;
76	char *secret = NULL;
77	int ivlen = 0;
78	u_char *ivoff;
79
80	esp = (struct esp *)bp;
81	spi = (u_int32_t)ntohl(esp->esp_spi);
82
83	/* 'ep' points to the end of available data. */
84	ep = snapend;
85
86	if ((u_char *)(esp + 1) >= ep - sizeof(struct esp)) {
87		fputs("[|ESP]", stdout);
88		goto fail;
89	}
90	printf("ESP(spi=0x%08x", spi);
91	printf(",seq=0x%x", (u_int32_t)ntohl(*(u_int32_t *)(esp + 1)));
92	printf(")");
93
94	/* if we don't have decryption key, we can't decrypt this packet. */
95	if (!espsecret)
96		goto fail;
97
98	if (strncmp(espsecret, "des-cbc:", 8) == 0
99	 && strlen(espsecret + 8) == 8) {
100		algo = DESCBC;
101		ivlen = 8;
102		secret = espsecret + 8;
103	} else if (strncmp(espsecret, "blowfish-cbc:", 13) == 0) {
104		algo = BLOWFISH;
105		ivlen = 8;
106		secret = espsecret + 13;
107	} else if (strncmp(espsecret, "rc5-cbc:", 8) == 0) {
108		algo = RC5;
109		ivlen = 8;
110		secret = espsecret + 8;
111	} else if (strncmp(espsecret, "cast128-cbc:", 12) == 0) {
112		algo = CAST128;
113		ivlen = 8;
114		secret = espsecret + 12;
115	} else if (strncmp(espsecret, "3des-cbc:", 9) == 0
116		&& strlen(espsecret + 9) == 24) {
117		algo = DES3CBC;
118		ivlen = 8;
119		secret = espsecret + 9;
120	} else if (strncmp(espsecret, "none:", 5) == 0) {
121		algo = NONE;
122		ivlen = 0;
123		secret = espsecret + 5;
124	} else if (strlen(espsecret) == 8) {
125		algo = DESCBC;
126		ivlen = 8;
127		secret = espsecret;
128	} else {
129		algo = NONE;
130		ivlen = 0;
131		secret = espsecret;
132	}
133
134	ip = (struct ip *)bp2;
135	switch (IP_V(ip)) {
136#ifdef INET6
137	case 6:
138		ip6 = (struct ip6_hdr *)bp2;
139		ip = NULL;
140		/* we do not attempt to decrypt jumbograms */
141		if (!ntohs(ip6->ip6_plen))
142			goto fail;
143		/* if we can't get nexthdr, we do not need to decrypt it */
144		len = sizeof(struct ip6_hdr) + ntohs(ip6->ip6_plen);
145		break;
146#endif /*INET6*/
147	case 4:
148#ifdef INET6
149		ip6 = NULL;
150#endif
151		len = ntohs(ip->ip_len);
152		break;
153	default:
154		goto fail;
155	}
156
157	/* if we can't get nexthdr, we do not need to decrypt it */
158	if (ep - bp2 < len)
159		goto fail;
160
161	if (Rflag)
162		ivoff = (u_char *)(esp + 1) + sizeof(u_int32_t);
163	else
164		ivoff = (u_char *)(esp + 1);
165
166	switch (algo) {
167	case DESCBC:
168#ifdef HAVE_LIBCRYPTO
169	    {
170		u_char iv[8];
171		des_key_schedule schedule;
172		u_char *p;
173
174		switch (ivlen) {
175		case 4:
176			memcpy(iv, ivoff, 4);
177			memcpy(&iv[4], ivoff, 4);
178			p = &iv[4];
179			*p++ ^= 0xff;
180			*p++ ^= 0xff;
181			*p++ ^= 0xff;
182			*p++ ^= 0xff;
183			break;
184		case 8:
185			memcpy(iv, ivoff, 8);
186			break;
187		default:
188			goto fail;
189		}
190
191		des_check_key = 0;
192		des_set_key((void *)secret, schedule);
193
194		p = ivoff + ivlen;
195		des_cbc_encrypt((void *)p, (void *)p,
196			(long)(ep - p), schedule, (void *)iv,
197			DES_DECRYPT);
198		advance = ivoff - (u_char *)esp + ivlen;
199		break;
200	    }
201#else
202		goto fail;
203#endif /*HAVE_LIBCRYPTO*/
204
205	case BLOWFISH:
206#ifdef HAVE_LIBCRYPTO
207	    {
208		BF_KEY schedule;
209		u_char *p;
210
211		BF_set_key(&schedule, strlen(secret), secret);
212
213		p = ivoff + ivlen;
214		BF_cbc_encrypt(p, p, (long)(ep - p), &schedule, ivoff,
215			BF_DECRYPT);
216		advance = ivoff - (u_char *)esp + ivlen;
217		break;
218	    }
219#else
220		goto fail;
221#endif /*HAVE_LIBCRYPTO*/
222
223	case RC5:
224#if defined(HAVE_LIBCRYPTO) && defined(HAVE_RC5_H)
225	    {
226		RC5_32_KEY schedule;
227		u_char *p;
228
229		RC5_32_set_key(&schedule, strlen(secret), secret,
230			RC5_16_ROUNDS);
231
232		p = ivoff + ivlen;
233		RC5_32_cbc_encrypt(p, p, (long)(ep - p), &schedule, ivoff,
234			RC5_DECRYPT);
235		advance = ivoff - (u_char *)esp + ivlen;
236		break;
237	    }
238#else
239		goto fail;
240#endif /*HAVE_LIBCRYPTO*/
241
242	case CAST128:
243#if defined(HAVE_LIBCRYPTO) && defined(HAVE_CAST_H) && !defined(HAVE_BUGGY_CAST128)
244	    {
245		CAST_KEY schedule;
246		u_char *p;
247
248		CAST_set_key(&schedule, strlen(secret), secret);
249
250		p = ivoff + ivlen;
251		CAST_cbc_encrypt(p, p, (long)(ep - p), &schedule, ivoff,
252			CAST_DECRYPT);
253		advance = ivoff - (u_char *)esp + ivlen;
254		break;
255	    }
256#else
257		goto fail;
258#endif /*HAVE_LIBCRYPTO*/
259
260	case DES3CBC:
261#if defined(HAVE_LIBCRYPTO)
262	    {
263		des_key_schedule s1, s2, s3;
264		u_char *p;
265
266		des_check_key = 0;
267		des_set_key((void *)secret, s1);
268		des_set_key((void *)(secret + 8), s2);
269		des_set_key((void *)(secret + 16), s3);
270
271		p = ivoff + ivlen;
272		des_ede3_cbc_encrypt((void *)p, (void *)p,
273			(long)(ep - p), s1, s2, s3, (void *)ivoff, DES_DECRYPT);
274		advance = ivoff - (u_char *)esp + ivlen;
275		break;
276	    }
277#else
278		goto fail;
279#endif /*HAVE_LIBCRYPTO*/
280
281	case NONE:
282	default:
283		if (Rflag)
284			advance = sizeof(struct esp) + sizeof(u_int32_t);
285		else
286			advance = sizeof(struct esp);
287		break;
288	}
289
290	/* sanity check for pad length */
291	if (ep - bp < *(ep - 2))
292		goto fail;
293
294	if (nhdr)
295		*nhdr = *(ep - 1);
296
297	printf(": ");
298	return advance;
299
300fail:
301	if (nhdr)
302		*nhdr = -1;
303	return 65536;
304}
305