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