]> The Tcpdump Group git mirrors - tcpdump/blob - print-esp.c
Merge remote-tracking branch 'bpf/master'
[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[] _U_ =
26 "@(#) $Header: /tcpdump/master/tcpdump/print-esp.c,v 1.58 2007-12-07 00:03:07 mcr Exp $ (LBL)";
27 #endif
28
29 #ifdef HAVE_CONFIG_H
30 #include "config.h"
31 #endif
32
33 #include <string.h>
34
35 #include <tcpdump-stdinc.h>
36
37 #include <stdlib.h>
38
39 /* Any code in this file that depends on HAVE_LIBCRYPTO depends on
40 * HAVE_OPENSSL_EVP_H too. Undefining the former when the latter isn't defined
41 * is the simplest way of handling the dependency.
42 */
43 #ifdef HAVE_LIBCRYPTO
44 #ifdef HAVE_OPENSSL_EVP_H
45 #include <openssl/evp.h>
46 #else
47 #undef HAVE_LIBCRYPTO
48 #endif
49 #endif
50
51 #include <stdio.h>
52
53 #include "ip.h"
54 #include "esp.h"
55 #ifdef INET6
56 #include "ip6.h"
57 #endif
58
59 #include "netdissect.h"
60 #include "addrtoname.h"
61 #include "extract.h"
62
63 #ifndef HAVE_SOCKADDR_STORAGE
64 #ifdef INET6
65 struct sockaddr_storage {
66 union {
67 struct sockaddr_in sin;
68 struct sockaddr_in6 sin6;
69 } un;
70 };
71 #else
72 #define sockaddr_storage sockaddr
73 #endif
74 #endif /* HAVE_SOCKADDR_STORAGE */
75
76 #ifdef HAVE_LIBCRYPTO
77 struct sa_list {
78 struct sa_list *next;
79 struct sockaddr_storage daddr;
80 u_int32_t spi; /* if == 0, then IKEv2 */
81 int initiator;
82 u_char spii[8]; /* for IKEv2 */
83 u_char spir[8];
84 const EVP_CIPHER *evp;
85 int ivlen;
86 int authlen;
87 u_char authsecret[256];
88 int authsecret_len;
89 u_char secret[256]; /* is that big enough for all secrets? */
90 int secretlen;
91 };
92
93 /*
94 * this will adjust ndo_packetp and ndo_snapend to new buffer!
95 */
96 int esp_print_decrypt_buffer_by_ikev2(netdissect_options *ndo,
97 int initiator,
98 u_char spii[8], u_char spir[8],
99 u_char *buf, u_char *end)
100 {
101 struct sa_list *sa;
102 u_char *iv;
103 int len;
104 EVP_CIPHER_CTX ctx;
105
106 /* initiator arg is any non-zero value */
107 if(initiator) initiator=1;
108
109 /* see if we can find the SA, and if so, decode it */
110 for (sa = ndo->ndo_sa_list_head; sa != NULL; sa = sa->next) {
111 if (sa->spi == 0
112 && initiator == sa->initiator
113 && memcmp(spii, sa->spii, 8) == 0
114 && memcmp(spir, sa->spir, 8) == 0)
115 break;
116 }
117
118 if(sa == NULL) return 0;
119 if(sa->evp == NULL) return 0;
120
121 /*
122 * remove authenticator, and see if we still have something to
123 * work with
124 */
125 end = end - sa->authlen;
126 iv = buf;
127 buf = buf + sa->ivlen;
128 len = end-buf;
129
130 if(end <= buf) return 0;
131
132 memset(&ctx, 0, sizeof(ctx));
133 if (EVP_CipherInit(&ctx, sa->evp, sa->secret, NULL, 0) < 0)
134 (*ndo->ndo_warning)(ndo, "espkey init failed");
135 EVP_CipherInit(&ctx, NULL, NULL, iv, 0);
136 EVP_Cipher(&ctx, buf, buf, len);
137 EVP_CIPHER_CTX_cleanup(&ctx);
138
139 ndo->ndo_packetp = buf;
140 ndo->ndo_snapend = end;
141
142 return 1;
143
144 }
145
146 static void esp_print_addsa(netdissect_options *ndo,
147 struct sa_list *sa, int sa_def)
148 {
149 /* copy the "sa" */
150
151 struct sa_list *nsa;
152
153 nsa = (struct sa_list *)malloc(sizeof(struct sa_list));
154 if (nsa == NULL)
155 (*ndo->ndo_error)(ndo, "ran out of memory to allocate sa structure");
156
157 *nsa = *sa;
158
159 if (sa_def)
160 ndo->ndo_sa_default = nsa;
161
162 nsa->next = ndo->ndo_sa_list_head;
163 ndo->ndo_sa_list_head = nsa;
164 }
165
166
167 static u_int hexdigit(netdissect_options *ndo, char hex)
168 {
169 if (hex >= '0' && hex <= '9')
170 return (hex - '0');
171 else if (hex >= 'A' && hex <= 'F')
172 return (hex - 'A' + 10);
173 else if (hex >= 'a' && hex <= 'f')
174 return (hex - 'a' + 10);
175 else {
176 (*ndo->ndo_error)(ndo, "invalid hex digit %c in espsecret\n", hex);
177 return 0;
178 }
179 }
180
181 static u_int hex2byte(netdissect_options *ndo, char *hexstring)
182 {
183 u_int byte;
184
185 byte = (hexdigit(ndo, hexstring[0]) << 4) + hexdigit(ndo, hexstring[1]);
186 return byte;
187 }
188
189 /*
190 * returns size of binary, 0 on failure.
191 */
192 static
193 int espprint_decode_hex(netdissect_options *ndo,
194 u_char *binbuf, unsigned int binbuf_len,
195 char *hex)
196 {
197 unsigned int len;
198 int i;
199
200 len = strlen(hex) / 2;
201
202 if (len > binbuf_len) {
203 (*ndo->ndo_warning)(ndo, "secret is too big: %d\n", len);
204 return 0;
205 }
206
207 i = 0;
208 while (hex[0] != '\0' && hex[1]!='\0') {
209 binbuf[i] = hex2byte(ndo, hex);
210 hex += 2;
211 i++;
212 }
213
214 return i;
215 }
216
217 /*
218 * decode the form: SPINUM@IP <tab> ALGONAME:0xsecret
219 */
220
221 static int
222 espprint_decode_encalgo(netdissect_options *ndo,
223 char *decode, struct sa_list *sa)
224 {
225 int len;
226 size_t i;
227 const EVP_CIPHER *evp;
228 int authlen = 0;
229 char *colon, *p;
230
231 colon = strchr(decode, ':');
232 if (colon == NULL) {
233 (*ndo->ndo_warning)(ndo, "failed to decode espsecret: %s\n", decode);
234 return 0;
235 }
236 *colon = '\0';
237
238 len = colon - decode;
239 if (strlen(decode) > strlen("-hmac96") &&
240 !strcmp(decode + strlen(decode) - strlen("-hmac96"),
241 "-hmac96")) {
242 p = strstr(decode, "-hmac96");
243 *p = '\0';
244 authlen = 12;
245 }
246 if (strlen(decode) > strlen("-cbc") &&
247 !strcmp(decode + strlen(decode) - strlen("-cbc"), "-cbc")) {
248 p = strstr(decode, "-cbc");
249 *p = '\0';
250 }
251 evp = EVP_get_cipherbyname(decode);
252
253 if (!evp) {
254 (*ndo->ndo_warning)(ndo, "failed to find cipher algo %s\n", decode);
255 sa->evp = NULL;
256 sa->authlen = 0;
257 sa->ivlen = 0;
258 return 0;
259 }
260
261 sa->evp = evp;
262 sa->authlen = authlen;
263 sa->ivlen = EVP_CIPHER_iv_length(evp);
264
265 colon++;
266 if (colon[0] == '0' && colon[1] == 'x') {
267 /* decode some hex! */
268
269 colon += 2;
270 sa->secretlen = espprint_decode_hex(ndo, sa->secret, sizeof(sa->secret), colon);
271 if(sa->secretlen == 0) return 0;
272 } else {
273 i = strlen(colon);
274
275 if (i < sizeof(sa->secret)) {
276 memcpy(sa->secret, colon, i);
277 sa->secretlen = i;
278 } else {
279 memcpy(sa->secret, colon, sizeof(sa->secret));
280 sa->secretlen = sizeof(sa->secret);
281 }
282 }
283
284 return 1;
285 }
286
287 /*
288 * for the moment, ignore the auth algorith, just hard code the authenticator
289 * length. Need to research how openssl looks up HMAC stuff.
290 */
291 static int
292 espprint_decode_authalgo(netdissect_options *ndo,
293 char *decode, struct sa_list *sa)
294 {
295 char *colon;
296
297 colon = strchr(decode, ':');
298 if (colon == NULL) {
299 (*ndo->ndo_warning)(ndo, "failed to decode espsecret: %s\n", decode);
300 return 0;
301 }
302 *colon = '\0';
303
304 if(strcasecmp(colon,"sha1") == 0 ||
305 strcasecmp(colon,"md5") == 0) {
306 sa->authlen = 12;
307 }
308 return 1;
309 }
310
311 static void esp_print_decode_ikeline(netdissect_options *ndo, char *line,
312 const char *file, int lineno)
313 {
314 /* it's an IKEv2 secret, store it instead */
315 struct sa_list sa1;
316
317 char *init;
318 char *icookie, *rcookie;
319 int ilen, rlen;
320 char *authkey;
321 char *enckey;
322
323 init = strsep(&line, " \t");
324 icookie = strsep(&line, " \t");
325 rcookie = strsep(&line, " \t");
326 authkey = strsep(&line, " \t");
327 enckey = strsep(&line, " \t");
328
329 /* if any fields are missing */
330 if(!init || !icookie || !rcookie || !authkey || !enckey) {
331 (*ndo->ndo_warning)(ndo, "print_esp: failed to find all fields for ikev2 at %s:%u",
332 file, lineno);
333
334 return;
335 }
336
337 ilen = strlen(icookie);
338 rlen = strlen(rcookie);
339
340 if((init[0]!='I' && init[0]!='R')
341 || icookie[0]!='0' || icookie[1]!='x'
342 || rcookie[0]!='0' || rcookie[1]!='x'
343 || ilen!=18
344 || rlen!=18) {
345 (*ndo->ndo_warning)(ndo, "print_esp: line %s:%u improperly formatted.",
346 file, lineno);
347
348 (*ndo->ndo_warning)(ndo, "init=%s icookie=%s(%u) rcookie=%s(%u)",
349 init, icookie, ilen, rcookie, rlen);
350
351 return;
352 }
353
354 sa1.spi = 0;
355 sa1.initiator = (init[0] == 'I');
356 if(espprint_decode_hex(ndo, sa1.spii, sizeof(sa1.spii), icookie+2)!=8)
357 return;
358
359 if(espprint_decode_hex(ndo, sa1.spir, sizeof(sa1.spir), rcookie+2)!=8)
360 return;
361
362 if(!espprint_decode_encalgo(ndo, enckey, &sa1)) return;
363
364 if(!espprint_decode_authalgo(ndo, authkey, &sa1)) return;
365
366 esp_print_addsa(ndo, &sa1, FALSE);
367 }
368
369 /*
370 *
371 * special form: file /name
372 * causes us to go read from this file instead.
373 *
374 */
375 static void esp_print_decode_onesecret(netdissect_options *ndo, char *line,
376 const char *file, int lineno)
377 {
378 struct sa_list sa1;
379 int sa_def;
380
381 char *spikey;
382 char *decode;
383
384 spikey = strsep(&line, " \t");
385 sa_def = 0;
386 memset(&sa1, 0, sizeof(struct sa_list));
387
388 /* if there is only one token, then it is an algo:key token */
389 if (line == NULL) {
390 decode = spikey;
391 spikey = NULL;
392 /* memset(&sa1.daddr, 0, sizeof(sa1.daddr)); */
393 /* sa1.spi = 0; */
394 sa_def = 1;
395 } else
396 decode = line;
397
398 if (spikey && strcasecmp(spikey, "file") == 0) {
399 /* open file and read it */
400 FILE *secretfile;
401 char fileline[1024];
402 int lineno=0;
403 char *nl;
404 char *filename = line;
405
406 secretfile = fopen(filename, FOPEN_READ_TXT);
407 if (secretfile == NULL) {
408 perror(filename);
409 exit(3);
410 }
411
412 while (fgets(fileline, sizeof(fileline)-1, secretfile) != NULL) {
413 lineno++;
414 /* remove newline from the line */
415 nl = strchr(fileline, '\n');
416 if (nl)
417 *nl = '\0';
418 if (fileline[0] == '#') continue;
419 if (fileline[0] == '\0') continue;
420
421 esp_print_decode_onesecret(ndo, fileline, filename, lineno);
422 }
423 fclose(secretfile);
424
425 return;
426 }
427
428 if (spikey && strcasecmp(spikey, "ikev2") == 0) {
429 esp_print_decode_ikeline(ndo, line, file, lineno);
430 return;
431 }
432
433 if (spikey) {
434
435 char *spistr, *foo;
436 u_int32_t spino;
437 struct sockaddr_in *sin;
438 #ifdef INET6
439 struct sockaddr_in6 *sin6;
440 #endif
441
442 spistr = strsep(&spikey, "@");
443
444 spino = strtoul(spistr, &foo, 0);
445 if (spistr == foo || !spikey) {
446 (*ndo->ndo_warning)(ndo, "print_esp: failed to decode spi# %s\n", foo);
447 return;
448 }
449
450 sa1.spi = spino;
451
452 sin = (struct sockaddr_in *)&sa1.daddr;
453 #ifdef INET6
454 sin6 = (struct sockaddr_in6 *)&sa1.daddr;
455 if (inet_pton(AF_INET6, spikey, &sin6->sin6_addr) == 1) {
456 #ifdef HAVE_SOCKADDR_SA_LEN
457 sin6->sin6_len = sizeof(struct sockaddr_in6);
458 #endif
459 sin6->sin6_family = AF_INET6;
460 } else
461 #endif
462 if (inet_pton(AF_INET, spikey, &sin->sin_addr) == 1) {
463 #ifdef HAVE_SOCKADDR_SA_LEN
464 sin->sin_len = sizeof(struct sockaddr_in);
465 #endif
466 sin->sin_family = AF_INET;
467 } else {
468 (*ndo->ndo_warning)(ndo, "print_esp: can not decode IP# %s\n", spikey);
469 return;
470 }
471 }
472
473 if (decode) {
474 /* skip any blank spaces */
475 while (isspace((unsigned char)*decode))
476 decode++;
477
478 if(!espprint_decode_encalgo(ndo, decode, &sa1)) {
479 return;
480 }
481 }
482
483 esp_print_addsa(ndo, &sa1, sa_def);
484 }
485
486 static void esp_init(netdissect_options *ndo _U_)
487 {
488
489 OpenSSL_add_all_algorithms();
490 EVP_add_cipher_alias(SN_des_ede3_cbc, "3des");
491 }
492
493 void esp_print_decodesecret(netdissect_options *ndo)
494 {
495 char *line;
496 char *p;
497 static int initialized = 0;
498
499 if (!initialized) {
500 esp_init(ndo);
501 initialized = 1;
502 }
503
504 p = ndo->ndo_espsecret;
505
506 while (p && p[0] != '\0') {
507 /* pick out the first line or first thing until a comma */
508 if ((line = strsep(&p, "\n,")) == NULL) {
509 line = p;
510 p = NULL;
511 }
512
513 esp_print_decode_onesecret(ndo, line, "cmdline", 0);
514 }
515
516 ndo->ndo_espsecret = NULL;
517 }
518
519 #endif
520
521 int
522 esp_print(netdissect_options *ndo,
523 const u_char *bp, const int length, const u_char *bp2
524 #ifndef HAVE_LIBCRYPTO
525 _U_
526 #endif
527 ,
528 int *nhdr
529 #ifndef HAVE_LIBCRYPTO
530 _U_
531 #endif
532 ,
533 int *padlen
534 #ifndef HAVE_LIBCRYPTO
535 _U_
536 #endif
537 )
538 {
539 register const struct newesp *esp;
540 register const u_char *ep;
541 #ifdef HAVE_LIBCRYPTO
542 struct ip *ip;
543 struct sa_list *sa = NULL;
544 int espsecret_keylen;
545 #ifdef INET6
546 struct ip6_hdr *ip6 = NULL;
547 #endif
548 int advance;
549 int len;
550 u_char *secret;
551 int ivlen = 0;
552 u_char *ivoff;
553 u_char *p;
554 EVP_CIPHER_CTX ctx;
555 int blocksz;
556 #endif
557
558 esp = (struct newesp *)bp;
559
560 #ifdef HAVE_LIBCRYPTO
561 secret = NULL;
562 advance = 0;
563 #endif
564
565 #if 0
566 /* keep secret out of a register */
567 p = (u_char *)&secret;
568 #endif
569
570 /* 'ep' points to the end of available data. */
571 ep = ndo->ndo_snapend;
572
573 if ((u_char *)(esp + 1) >= ep) {
574 fputs("[|ESP]", stdout);
575 goto fail;
576 }
577 (*ndo->ndo_printf)(ndo, "ESP(spi=0x%08x", EXTRACT_32BITS(&esp->esp_spi));
578 (*ndo->ndo_printf)(ndo, ",seq=0x%x)", EXTRACT_32BITS(&esp->esp_seq));
579 (*ndo->ndo_printf)(ndo, ", length %u", length);
580
581 #ifndef HAVE_LIBCRYPTO
582 goto fail;
583 #else
584 /* initiailize SAs */
585 if (ndo->ndo_sa_list_head == NULL) {
586 if (!ndo->ndo_espsecret)
587 goto fail;
588
589 esp_print_decodesecret(ndo);
590 }
591
592 if (ndo->ndo_sa_list_head == NULL)
593 goto fail;
594
595 ip = (struct ip *)bp2;
596 switch (IP_V(ip)) {
597 #ifdef INET6
598 case 6:
599 ip6 = (struct ip6_hdr *)bp2;
600 /* we do not attempt to decrypt jumbograms */
601 if (!EXTRACT_16BITS(&ip6->ip6_plen))
602 goto fail;
603 /* if we can't get nexthdr, we do not need to decrypt it */
604 len = sizeof(struct ip6_hdr) + EXTRACT_16BITS(&ip6->ip6_plen);
605
606 /* see if we can find the SA, and if so, decode it */
607 for (sa = ndo->ndo_sa_list_head; sa != NULL; sa = sa->next) {
608 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&sa->daddr;
609 if (sa->spi == EXTRACT_32BITS(&esp->esp_spi) &&
610 sin6->sin6_family == AF_INET6 &&
611 memcmp(&sin6->sin6_addr, &ip6->ip6_dst,
612 sizeof(struct in6_addr)) == 0) {
613 break;
614 }
615 }
616 break;
617 #endif /*INET6*/
618 case 4:
619 /* nexthdr & padding are in the last fragment */
620 if (EXTRACT_16BITS(&ip->ip_off) & IP_MF)
621 goto fail;
622 len = EXTRACT_16BITS(&ip->ip_len);
623
624 /* see if we can find the SA, and if so, decode it */
625 for (sa = ndo->ndo_sa_list_head; sa != NULL; sa = sa->next) {
626 struct sockaddr_in *sin = (struct sockaddr_in *)&sa->daddr;
627 if (sa->spi == EXTRACT_32BITS(&esp->esp_spi) &&
628 sin->sin_family == AF_INET &&
629 sin->sin_addr.s_addr == ip->ip_dst.s_addr) {
630 break;
631 }
632 }
633 break;
634 default:
635 goto fail;
636 }
637
638 /* if we didn't find the specific one, then look for
639 * an unspecified one.
640 */
641 if (sa == NULL)
642 sa = ndo->ndo_sa_default;
643
644 /* if not found fail */
645 if (sa == NULL)
646 goto fail;
647
648 /* if we can't get nexthdr, we do not need to decrypt it */
649 if (ep - bp2 < len)
650 goto fail;
651 if (ep - bp2 > len) {
652 /* FCS included at end of frame (NetBSD 1.6 or later) */
653 ep = bp2 + len;
654 }
655
656 ivoff = (u_char *)(esp + 1) + 0;
657 ivlen = sa->ivlen;
658 secret = sa->secret;
659 espsecret_keylen = sa->secretlen;
660 ep = ep - sa->authlen;
661
662 if (sa->evp) {
663 memset(&ctx, 0, sizeof(ctx));
664 if (EVP_CipherInit(&ctx, sa->evp, secret, NULL, 0) < 0)
665 (*ndo->ndo_warning)(ndo, "espkey init failed");
666
667 blocksz = EVP_CIPHER_CTX_block_size(&ctx);
668
669 p = ivoff;
670 EVP_CipherInit(&ctx, NULL, NULL, p, 0);
671 EVP_Cipher(&ctx, p + ivlen, p + ivlen, ep - (p + ivlen));
672 EVP_CIPHER_CTX_cleanup(&ctx);
673 advance = ivoff - (u_char *)esp + ivlen;
674 } else
675 advance = sizeof(struct newesp);
676
677 /* sanity check for pad length */
678 if (ep - bp < *(ep - 2))
679 goto fail;
680
681 if (padlen)
682 *padlen = *(ep - 2) + 2;
683
684 if (nhdr)
685 *nhdr = *(ep - 1);
686
687 (ndo->ndo_printf)(ndo, ": ");
688 return advance;
689 #endif
690
691 fail:
692 return -1;
693 }
694
695 /*
696 * Local Variables:
697 * c-style: whitesmith
698 * c-basic-offset: 8
699 * End:
700 */