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