xref: /freebsd/contrib/tcpdump/print-esp.c (revision 2a4a1db342263067035ce69a4017c645da63455d)
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.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 
63 int
64 esp_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 
300 fail:
301 	if (nhdr)
302 		*nhdr = -1;
303 	return 65536;
304 }
305