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