xref: /freebsd/contrib/tcpdump/print-esp.c (revision daf1cffce2e07931f27c6c6998652e90df6ba87e)
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
25 static const char rcsid[] =
26     "@(#) $Header: /tcpdump/master/tcpdump/print-esp.c,v 1.5 1999/12/15 08:10:18 fenner 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 <net/route.h>
40 #include <net/if.h>
41 
42 #include <netinet/in.h>
43 #include <netinet/if_ether.h>
44 #include <netinet/in_systm.h>
45 #include <netinet/ip.h>
46 #include <netinet/ip_icmp.h>
47 #include <netinet/ip_var.h>
48 #include <netinet/udp.h>
49 #include <netinet/udp_var.h>
50 #include <netinet/tcp.h>
51 
52 #ifdef CRYPTO
53 #include <des.h>
54 #include <blowfish.h>
55 #ifdef HAVE_RC5_H
56 #include <rc5.h>
57 #endif
58 #ifdef HAVE_CAST_H
59 #include <cast.h>
60 #endif
61 #endif
62 
63 #include <stdio.h>
64 
65 #ifdef INET6
66 #include <netinet/ip6.h>
67 #endif
68 
69 /* there's no standard definition so we are on our own */
70 struct esp {
71 	u_int32_t	esp_spi;	/* ESP */
72 	/*variable size, 32bit bound*/	/* Initialization Vector */
73 	/*variable size*/		/* Payload data */
74 	/*variable size*/		/* padding */
75 	/*8bit*/			/* pad size */
76 	/*8bit*/			/* next header */
77 	/*8bit*/			/* next header */
78 	/*variable size, 32bit bound*/	/* Authentication data (new IPsec) */
79 };
80 
81 struct newesp {
82 	u_int32_t	esp_spi;	/* ESP */
83 	u_int32_t	esp_seq;	/* Sequence number */
84 	/*variable size*/		/* (IV and) Payload data */
85 	/*variable size*/		/* padding */
86 	/*8bit*/			/* pad size */
87 	/*8bit*/			/* next header */
88 	/*8bit*/			/* next header */
89 	/*variable size, 32bit bound*/	/* Authentication data */
90 };
91 
92 #include "interface.h"
93 #include "addrtoname.h"
94 
95 int
96 esp_print(register const u_char *bp, register const u_char *bp2, int *nhdr)
97 {
98 	register const struct esp *esp;
99 	register const u_char *ep;
100 	u_int32_t spi;
101 	enum { NONE, DESCBC, BLOWFISH, RC5, CAST128, DES3CBC } algo = NONE;
102 	struct ip *ip = NULL;
103 #ifdef INET6
104 	struct ip6_hdr *ip6 = NULL;
105 #endif
106 	int advance;
107 	int len;
108 	char *secret = NULL;
109 	int ivlen = 0;
110 	u_char *ivoff;
111 
112 	esp = (struct esp *)bp;
113 	spi = (u_int32_t)ntohl(esp->esp_spi);
114 
115 	/* 'ep' points to the end of avaible data. */
116 	ep = snapend;
117 
118 	if ((u_char *)(esp + 1) >= ep - sizeof(struct esp)) {
119 		fputs("[|ESP]", stdout);
120 		goto fail;
121 	}
122 	printf("ESP(spi=%u", spi);
123 	printf(",seq=0x%x", (u_int32_t)ntohl(*(u_int32_t *)(esp + 1)));
124 	printf(")");
125 
126 	/* if we don't have decryption key, we can't decrypt this packet. */
127 	if (!espsecret)
128 		goto fail;
129 
130 	if (strncmp(espsecret, "des-cbc:", 8) == 0
131 	 && strlen(espsecret + 8) == 8) {
132 		algo = DESCBC;
133 		ivlen = 8;
134 		secret = espsecret + 8;
135 	} else if (strncmp(espsecret, "blowfish-cbc:", 13) == 0) {
136 		algo = BLOWFISH;
137 		ivlen = 8;
138 		secret = espsecret + 13;
139 	} else if (strncmp(espsecret, "rc5-cbc:", 8) == 0) {
140 		algo = RC5;
141 		ivlen = 8;
142 		secret = espsecret + 8;
143 	} else if (strncmp(espsecret, "cast128-cbc:", 12) == 0) {
144 		algo = CAST128;
145 		ivlen = 8;
146 		secret = espsecret + 12;
147 	} else if (strncmp(espsecret, "3des-cbc:", 9) == 0
148 		&& strlen(espsecret + 9) == 24) {
149 		algo = DES3CBC;
150 		ivlen = 8;
151 		secret = espsecret + 9;
152 	} else if (strncmp(espsecret, "none:", 5) == 0) {
153 		algo = NONE;
154 		ivlen = 0;
155 		secret = espsecret + 5;
156 	} else if (strlen(espsecret) == 8) {
157 		algo = DESCBC;
158 		ivlen = 8;
159 		secret = espsecret;
160 	} else {
161 		algo = NONE;
162 		ivlen = 0;
163 		secret = espsecret;
164 	}
165 
166 	ip = (struct ip *)bp2;
167 	switch (ip->ip_v) {
168 #ifdef INET6
169 	case 6:
170 		ip6 = (struct ip6_hdr *)bp2;
171 		ip = NULL;
172 		/* we do not attempt to decrypt jumbograms */
173 		if (!ntohs(ip6->ip6_plen))
174 			goto fail;
175 		/* if we can't get nexthdr, we do not need to decrypt it */
176 		len = sizeof(struct ip6_hdr) + ntohs(ip6->ip6_plen);
177 		break;
178 #endif /*INET6*/
179 	case 4:
180 #ifdef INET6
181 		ip6 = NULL;
182 #endif
183 		len = ntohs(ip->ip_len);
184 		break;
185 	default:
186 		goto fail;
187 	}
188 
189 	/* if we can't get nexthdr, we do not need to decrypt it */
190 	if (ep - bp2 < len)
191 		goto fail;
192 
193 	if (Rflag)
194 		ivoff = (u_char *)(esp + 1) + sizeof(u_int32_t);
195 	else
196 		ivoff = (u_char *)(esp + 1);
197 
198 	switch (algo) {
199 	case DESCBC:
200 #ifdef CRYPTO
201 	    {
202 		u_char iv[8];
203 		des_key_schedule schedule;
204 		u_char *p;
205 
206 		switch (ivlen) {
207 		case 4:
208 			memcpy(iv, ivoff, 4);
209 			memcpy(&iv[4], ivoff, 4);
210 			p = &iv[4];
211 			*p++ ^= 0xff;
212 			*p++ ^= 0xff;
213 			*p++ ^= 0xff;
214 			*p++ ^= 0xff;
215 			break;
216 		case 8:
217 			memcpy(iv, ivoff, 8);
218 			break;
219 		default:
220 			goto fail;
221 		}
222 
223 		des_check_key = 0;
224 		des_set_key((void *)secret, schedule);
225 
226 		p = ivoff + ivlen;
227 		des_cbc_encrypt((void *)p, (void *)p,
228 			(long)(ep - p), schedule, (void *)iv,
229 			DES_DECRYPT);
230 		advance = ivoff - (u_char *)esp + ivlen;
231 		break;
232 	    }
233 #else
234 		goto fail;
235 #endif /*CRYPTO*/
236 
237 	case BLOWFISH:
238 #ifdef CRYPTO
239 	    {
240 		BF_KEY schedule;
241 		u_char *p;
242 
243 		BF_set_key(&schedule, strlen(secret), secret);
244 
245 		p = ivoff + ivlen;
246 		BF_cbc_encrypt(p, p, (long)(ep - p), &schedule, ivoff,
247 			BF_DECRYPT);
248 		advance = ivoff - (u_char *)esp + ivlen;
249 		break;
250 	    }
251 #else
252 		goto fail;
253 #endif /*CRYPTO*/
254 
255 	case RC5:
256 #if defined(CRYPTO) && defined(HAVE_RC5_H)
257 	    {
258 		RC5_32_KEY schedule;
259 		u_char *p;
260 
261 		RC5_32_set_key(&schedule, strlen(secret), secret,
262 			RC5_16_ROUNDS);
263 
264 		p = ivoff + ivlen;
265 		RC5_32_cbc_encrypt(p, p, (long)(ep - p), &schedule, ivoff,
266 			RC5_DECRYPT);
267 		advance = ivoff - (u_char *)esp + ivlen;
268 		break;
269 	    }
270 #else
271 		goto fail;
272 #endif /*CRYPTO*/
273 
274 	case CAST128:
275 #if defined(CRYPTO) && defined(HAVE_CAST_H) && !defined(HAVE_BUGGY_CAST128)
276 	    {
277 		CAST_KEY schedule;
278 		u_char *p;
279 
280 		CAST_set_key(&schedule, strlen(secret), secret);
281 
282 		p = ivoff + ivlen;
283 		CAST_cbc_encrypt(p, p, (long)(ep - p), &schedule, ivoff,
284 			CAST_DECRYPT);
285 		advance = ivoff - (u_char *)esp + ivlen;
286 		break;
287 	    }
288 #else
289 		goto fail;
290 #endif /*CRYPTO*/
291 
292 	case DES3CBC:
293 #if defined(CRYPTO)
294 	    {
295 		des_key_schedule s1, s2, s3;
296 		u_char *p;
297 
298 		des_check_key = 0;
299 		des_set_key((void *)secret, s1);
300 		des_set_key((void *)(secret + 8), s2);
301 		des_set_key((void *)(secret + 16), s3);
302 
303 		p = ivoff + ivlen;
304 		des_ede3_cbc_encrypt((void *)p, (void *)p,
305 			(long)(ep - p), s1, s2, s3, (void *)ivoff, DES_DECRYPT);
306 		advance = ivoff - (u_char *)esp + ivlen;
307 		break;
308 	    }
309 #else
310 		goto fail;
311 #endif /*CRYPTO*/
312 
313 	case NONE:
314 	default:
315 		if (Rflag)
316 			advance = sizeof(struct esp) + sizeof(u_int32_t);
317 		else
318 			advance = sizeof(struct esp);
319 		break;
320 	}
321 
322 	/* sanity check for pad length */
323 	if (ep - bp < *(ep - 2))
324 		goto fail;
325 
326 	if (nhdr)
327 		*nhdr = *(ep - 1);
328 
329 	printf(": ");
330 	return advance;
331 
332 fail:
333 	if (nhdr)
334 		*nhdr = -1;
335 	return 65536;
336 }
337