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