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