]> The Tcpdump Group git mirrors - tcpdump/blob - print-esp.c
6e76f1b26bac795e7daf98c5d72a6494d45365c3
[tcpdump] / print-esp.c
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.20 2002-01-21 11:39:59 mcr 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 <openssl/des.h>
43 #include <openssl/blowfish.h>
44 #ifdef HAVE_RC5_H
45 #include <openssl/rc5.h>
46 #endif
47 #ifdef HAVE_CAST_H
48 #include <openssl/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 #define AVOID_CHURN 1
61 #include "interface.h"
62 #include "addrtoname.h"
63
64 static struct esp_algorithm *espsecret_xform=NULL; /* cache of decoded alg. */
65 static char *espsecret_key=NULL;
66
67
68 enum cipher { NONE,
69 DESCBC,
70 BLOWFISH,
71 RC5,
72 CAST128,
73 DES3CBC};
74
75
76
77 struct esp_algorithm {
78 char *name;
79 enum cipher algo;
80 int ivlen;
81 int authlen;
82 int replaysize;
83 };
84
85 struct esp_algorithm esp_xforms[]={
86 {"none", NONE, 0, 0, 0},
87 {"des-cbc", DESCBC, 8, 0, 0},
88 {"des-cbc-hmac96", DESCBC, 8, 12, 4},
89 {"blowfish-cbc", BLOWFISH,8, 0, 0},
90 {"blowfish-cbc-hmac96", BLOWFISH,8, 12, 4},
91 {"rc5-cbc", RC5, 8, 0, 0},
92 {"rc5-cbc-hmac96", RC5, 8, 12, 4},
93 {"cast128-cbc", CAST128, 8, 0, 0},
94 {"cast128-cbc-hmac96", CAST128, 8, 12, 4},
95 {"3des-cbc-hmac96", DES3CBC, 8, 12, 4},
96 };
97
98 static int hexdigit(char hex)
99 {
100 if(hex >= '0' && hex <= '9') {
101 return (hex - '0');
102 } else if(hex >= 'A' && hex <= 'F') {
103 return (hex - 'A' + 10);
104 } else if(hex >= 'a' && hex <= 'f') {
105 return (hex - 'a' + 10);
106 } else {
107 printf("invalid hex digit %c in espsecret\n", hex);
108 return 0;
109 }
110 }
111
112 static int hex2byte(char *hexstring)
113 {
114 int byte;
115
116 byte = (hexdigit(hexstring[0]) << 4) +
117 hexdigit(hexstring[1]);
118 return byte;
119 }
120
121
122 void esp_print_decodesecret()
123 {
124 char *colon;
125 int len, i;
126 struct esp_algorithm *xf;
127
128 if(espsecret == NULL) {
129 /* set to NONE transform */
130 espsecret_xform = esp_xforms;
131 return;
132 }
133
134 if(espsecret_key != NULL) {
135 return;
136 }
137
138 colon = strchr(espsecret, ':');
139 if(colon == NULL) {
140 printf("failed to decode espsecret: %s\n",
141 espsecret);
142 /* set to NONE transform */
143 espsecret_xform = esp_xforms;
144 }
145
146 len = colon - espsecret;
147 xf = esp_xforms;
148 while(xf->name && strncasecmp(espsecret, xf->name, len)!=0) {
149 xf++;
150 }
151 if(xf->name == NULL) {
152 printf("failed to find cipher algo %s\n",
153 espsecret);
154 espsecret_xform = esp_xforms;
155 return;
156 }
157 espsecret_xform = xf;
158
159 colon++;
160 if(colon[0]=='0' && colon[1]=='x') {
161 /* decode some hex! */
162 colon+=2;
163 len = strlen(colon) / 2;
164 espsecret_key = (char *)malloc(len);
165 if(espsecret_key == NULL) {
166 fprintf(stderr, "%s: ran out of memory (%d) to allocate secret key\n",
167 program_name, len);
168 exit(2);
169 }
170 i = 0;
171 while(colon[0] != '\0' && colon[1]!='\0') {
172 espsecret_key[i]=hex2byte(colon);
173 colon+=2;
174 i++;
175 }
176 } else {
177 espsecret_key = colon;
178 }
179 }
180
181 int
182 esp_print(register const u_char *bp, register const u_char *bp2,
183 int *nhdr, int *padlen)
184 {
185 register const struct esp *esp;
186 register const u_char *ep;
187 u_int32_t spi;
188 struct ip *ip = NULL;
189 #ifdef INET6
190 struct ip6_hdr *ip6 = NULL;
191 #endif
192 int advance;
193 int len;
194 char *secret;
195 int ivlen = 0;
196 u_char *ivoff;
197 u_char *p;
198
199 esp = (struct esp *)bp;
200 spi = (u_int32_t)ntohl(esp->esp_spi);
201 secret = NULL;
202
203 #if 0
204 /* keep secret out of a register */
205 p = (u_char *)&secret;
206 #endif
207
208 /* 'ep' points to the end of available data. */
209 ep = snapend;
210
211 if ((u_char *)(esp + 1) >= ep - sizeof(struct esp)) {
212 fputs("[|ESP]", stdout);
213 goto fail;
214 }
215 printf("ESP(spi=0x%08x", spi);
216 printf(",seq=0x%x", (u_int32_t)ntohl(*(u_int32_t *)(esp + 1)));
217 printf(")");
218
219 /* if we don't have decryption key, we can't decrypt this packet. */
220 if (!espsecret)
221 goto fail;
222
223 if(!espsecret_xform) {
224 esp_print_decodesecret();
225 }
226 if(espsecret_xform->algo == NONE) {
227 goto fail;
228 }
229
230 ip = (struct ip *)bp2;
231 switch (IP_V(ip)) {
232 #ifdef INET6
233 case 6:
234 ip6 = (struct ip6_hdr *)bp2;
235 ip = NULL;
236 /* we do not attempt to decrypt jumbograms */
237 if (!ntohs(ip6->ip6_plen))
238 goto fail;
239 /* if we can't get nexthdr, we do not need to decrypt it */
240 len = sizeof(struct ip6_hdr) + ntohs(ip6->ip6_plen);
241 break;
242 #endif /*INET6*/
243 case 4:
244 /* nexthdr & padding are in the last fragment */
245 if (ntohs(ip->ip_off) & IP_MF)
246 goto fail;
247 #ifdef INET6
248 ip6 = NULL;
249 #endif
250 len = ntohs(ip->ip_len);
251 break;
252 default:
253 goto fail;
254 }
255
256 /* if we can't get nexthdr, we do not need to decrypt it */
257 if (ep - bp2 < len)
258 goto fail;
259
260 ivoff = (u_char *)(esp + 1) + espsecret_xform->replaysize;
261 ivlen = espsecret_xform->ivlen;
262 secret = espsecret_key;
263
264 switch (espsecret_xform->algo) {
265 case DESCBC:
266 #ifdef HAVE_LIBCRYPTO
267 {
268 u_char iv[8];
269 des_key_schedule schedule;
270
271 switch (ivlen) {
272 case 4:
273 memcpy(iv, ivoff, 4);
274 memcpy(&iv[4], ivoff, 4);
275 p = &iv[4];
276 *p++ ^= 0xff;
277 *p++ ^= 0xff;
278 *p++ ^= 0xff;
279 *p++ ^= 0xff;
280 break;
281 case 8:
282 memcpy(iv, ivoff, 8);
283 break;
284 default:
285 goto fail;
286 }
287
288 des_check_key = 0;
289 des_set_key((void *)secret, schedule);
290
291 p = ivoff + ivlen;
292 des_cbc_encrypt((void *)p, (void *)p,
293 (long)(ep - p), schedule, (void *)iv,
294 DES_DECRYPT);
295 advance = ivoff - (u_char *)esp + ivlen;
296 break;
297 }
298 #else
299 goto fail;
300 #endif /*HAVE_LIBCRYPTO*/
301
302 case BLOWFISH:
303 #ifdef HAVE_LIBCRYPTO
304 {
305 BF_KEY schedule;
306
307 BF_set_key(&schedule, strlen(secret), secret);
308
309 p = ivoff + ivlen;
310 BF_cbc_encrypt(p, p, (long)(ep - p), &schedule, ivoff,
311 BF_DECRYPT);
312 advance = ivoff - (u_char *)esp + ivlen;
313 break;
314 }
315 #else
316 goto fail;
317 #endif /*HAVE_LIBCRYPTO*/
318
319 case RC5:
320 #if defined(HAVE_LIBCRYPTO) && defined(HAVE_RC5_H)
321 {
322 RC5_32_KEY schedule;
323
324 RC5_32_set_key(&schedule, strlen(secret), secret,
325 RC5_16_ROUNDS);
326
327 p = ivoff + ivlen;
328 RC5_32_cbc_encrypt(p, p, (long)(ep - p), &schedule, ivoff,
329 RC5_DECRYPT);
330 advance = ivoff - (u_char *)esp + ivlen;
331 break;
332 }
333 #else
334 goto fail;
335 #endif /*HAVE_LIBCRYPTO*/
336
337 case CAST128:
338 #if defined(HAVE_LIBCRYPTO) && defined(HAVE_CAST_H) && !defined(HAVE_BUGGY_CAST128)
339 {
340 CAST_KEY schedule;
341
342 CAST_set_key(&schedule, strlen(secret), secret);
343
344 p = ivoff + ivlen;
345 CAST_cbc_encrypt(p, p, (long)(ep - p), &schedule, ivoff,
346 CAST_DECRYPT);
347 advance = ivoff - (u_char *)esp + ivlen;
348 break;
349 }
350 #else
351 goto fail;
352 #endif /*HAVE_LIBCRYPTO*/
353
354 case DES3CBC:
355 #if defined(HAVE_LIBCRYPTO)
356 {
357 des_key_schedule s1, s2, s3;
358
359 des_check_key = 1;
360 des_set_odd_parity((void *)secret);
361 des_set_odd_parity((void *)secret+8);
362 des_set_odd_parity((void *)secret+16);
363 if(des_set_key((void *)secret, s1) != 0) {
364 printf("failed to schedule key 1\n");
365 }
366 if(des_set_key((void *)(secret + 8), s2)!=0) {
367 printf("failed to schedule key 2\n");
368 }
369 if(des_set_key((void *)(secret + 16), s3)!=0) {
370 printf("failed to schedule key 3\n");
371 }
372
373 p = ivoff + ivlen;
374 des_ede3_cbc_encrypt((void *)p, (void *)p,
375 (long)(ep - p),
376 s1, s2, s3,
377 (void *)ivoff, DES_DECRYPT);
378 advance = ivoff - (u_char *)esp + ivlen;
379 break;
380 }
381 #else
382 goto fail;
383 #endif /*HAVE_LIBCRYPTO*/
384
385 case NONE:
386 default:
387 advance = sizeof(struct esp) + espsecret_xform->replaysize;
388 break;
389 }
390
391 ep = ep - espsecret_xform->authlen;
392 /* sanity check for pad length */
393 if (ep - bp < *(ep - 2))
394 goto fail;
395
396 if (padlen)
397 *padlen = *(ep - 2) + 2;
398
399 if (nhdr)
400 *nhdr = *(ep - 1);
401
402 printf(": ");
403 return advance;
404
405 fail:
406 if (nhdr)
407 *nhdr = -1;
408 return 65536;
409 }