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.2 2010/12/05 05:11:30 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 int len; 225 size_t i; 226 const EVP_CIPHER *evp; 227 int authlen = 0; 228 char *colon, *p; 229 230 colon = strchr(decode, ':'); 231 if (colon == NULL) { 232 (*ndo->ndo_warning)(ndo, "failed to decode espsecret: %s\n", decode); 233 return 0; 234 } 235 *colon = '\0'; 236 237 len = colon - decode; 238 if (strlen(decode) > strlen("-hmac96") && 239 !strcmp(decode + strlen(decode) - strlen("-hmac96"), 240 "-hmac96")) { 241 p = strstr(decode, "-hmac96"); 242 *p = '\0'; 243 authlen = 12; 244 } 245 if (strlen(decode) > strlen("-cbc") && 246 !strcmp(decode + strlen(decode) - strlen("-cbc"), "-cbc")) { 247 p = strstr(decode, "-cbc"); 248 *p = '\0'; 249 } 250 evp = EVP_get_cipherbyname(decode); 251 252 if (!evp) { 253 (*ndo->ndo_warning)(ndo, "failed to find cipher algo %s\n", decode); 254 sa->evp = NULL; 255 sa->authlen = 0; 256 sa->ivlen = 0; 257 return 0; 258 } 259 260 sa->evp = evp; 261 sa->authlen = authlen; 262 sa->ivlen = EVP_CIPHER_iv_length(evp); 263 264 colon++; 265 if (colon[0] == '0' && colon[1] == 'x') { 266 /* decode some hex! */ 267 268 colon += 2; 269 sa->secretlen = espprint_decode_hex(ndo, sa->secret, sizeof(sa->secret), colon); 270 if(sa->secretlen == 0) return 0; 271 } else { 272 i = strlen(colon); 273 274 if (i < sizeof(sa->secret)) { 275 memcpy(sa->secret, colon, i); 276 sa->secretlen = i; 277 } else { 278 memcpy(sa->secret, colon, sizeof(sa->secret)); 279 sa->secretlen = sizeof(sa->secret); 280 } 281 } 282 283 return 1; 284 } 285 286 /* 287 * for the moment, ignore the auth algorith, just hard code the authenticator 288 * length. Need to research how openssl looks up HMAC stuff. 289 */ 290 static int 291 espprint_decode_authalgo(netdissect_options *ndo, 292 char *decode, struct sa_list *sa) 293 { 294 char *colon; 295 296 colon = strchr(decode, ':'); 297 if (colon == NULL) { 298 (*ndo->ndo_warning)(ndo, "failed to decode espsecret: %s\n", decode); 299 return 0; 300 } 301 *colon = '\0'; 302 303 if(strcasecmp(colon,"sha1") == 0 || 304 strcasecmp(colon,"md5") == 0) { 305 sa->authlen = 12; 306 } 307 return 1; 308 } 309 310 static void esp_print_decode_ikeline(netdissect_options *ndo, char *line, 311 const char *file, int lineno) 312 { 313 /* it's an IKEv2 secret, store it instead */ 314 struct sa_list sa1; 315 316 char *init; 317 char *icookie, *rcookie; 318 int ilen, rlen; 319 char *authkey; 320 char *enckey; 321 322 init = strsep(&line, " \t"); 323 icookie = strsep(&line, " \t"); 324 rcookie = strsep(&line, " \t"); 325 authkey = strsep(&line, " \t"); 326 enckey = strsep(&line, " \t"); 327 328 /* if any fields are missing */ 329 if(!init || !icookie || !rcookie || !authkey || !enckey) { 330 (*ndo->ndo_warning)(ndo, "print_esp: failed to find all fields for ikev2 at %s:%u", 331 file, lineno); 332 333 return; 334 } 335 336 ilen = strlen(icookie); 337 rlen = strlen(rcookie); 338 339 if((init[0]!='I' && init[0]!='R') 340 || icookie[0]!='0' || icookie[1]!='x' 341 || rcookie[0]!='0' || rcookie[1]!='x' 342 || ilen!=18 343 || rlen!=18) { 344 (*ndo->ndo_warning)(ndo, "print_esp: line %s:%u improperly formatted.", 345 file, lineno); 346 347 (*ndo->ndo_warning)(ndo, "init=%s icookie=%s(%u) rcookie=%s(%u)", 348 init, icookie, ilen, rcookie, rlen); 349 350 return; 351 } 352 353 sa1.spi = 0; 354 sa1.initiator = (init[0] == 'I'); 355 if(espprint_decode_hex(ndo, sa1.spii, sizeof(sa1.spii), icookie+2)!=8) 356 return; 357 358 if(espprint_decode_hex(ndo, sa1.spir, sizeof(sa1.spir), rcookie+2)!=8) 359 return; 360 361 if(!espprint_decode_encalgo(ndo, enckey, &sa1)) return; 362 363 if(!espprint_decode_authalgo(ndo, authkey, &sa1)) return; 364 365 esp_print_addsa(ndo, &sa1, FALSE); 366 } 367 368 /* 369 * 370 * special form: file /name 371 * causes us to go read from this file instead. 372 * 373 */ 374 static void esp_print_decode_onesecret(netdissect_options *ndo, char *line, 375 const char *file, int lineno) 376 { 377 struct sa_list sa1; 378 int sa_def; 379 380 char *spikey; 381 char *decode; 382 383 spikey = strsep(&line, " \t"); 384 sa_def = 0; 385 memset(&sa1, 0, sizeof(struct sa_list)); 386 387 /* if there is only one token, then it is an algo:key token */ 388 if (line == NULL) { 389 decode = spikey; 390 spikey = NULL; 391 /* memset(&sa1.daddr, 0, sizeof(sa1.daddr)); */ 392 /* sa1.spi = 0; */ 393 sa_def = 1; 394 } else 395 decode = line; 396 397 if (spikey && strcasecmp(spikey, "file") == 0) { 398 /* open file and read it */ 399 FILE *secretfile; 400 char fileline[1024]; 401 int lineno=0; 402 char *nl; 403 char *filename = line; 404 405 secretfile = fopen(filename, FOPEN_READ_TXT); 406 if (secretfile == NULL) { 407 perror(filename); 408 exit(3); 409 } 410 411 while (fgets(fileline, sizeof(fileline)-1, secretfile) != NULL) { 412 lineno++; 413 /* remove newline from the line */ 414 nl = strchr(fileline, '\n'); 415 if (nl) 416 *nl = '\0'; 417 if (fileline[0] == '#') continue; 418 if (fileline[0] == '\0') continue; 419 420 esp_print_decode_onesecret(ndo, fileline, filename, lineno); 421 } 422 fclose(secretfile); 423 424 return; 425 } 426 427 if (spikey && strcasecmp(spikey, "ikev2") == 0) { 428 esp_print_decode_ikeline(ndo, line, file, lineno); 429 return; 430 } 431 432 if (spikey) { 433 434 char *spistr, *foo; 435 u_int32_t spino; 436 struct sockaddr_in *sin; 437 #ifdef INET6 438 struct sockaddr_in6 *sin6; 439 #endif 440 441 spistr = strsep(&spikey, "@"); 442 443 spino = strtoul(spistr, &foo, 0); 444 if (spistr == foo || !spikey) { 445 (*ndo->ndo_warning)(ndo, "print_esp: failed to decode spi# %s\n", foo); 446 return; 447 } 448 449 sa1.spi = spino; 450 451 sin = (struct sockaddr_in *)&sa1.daddr; 452 #ifdef INET6 453 sin6 = (struct sockaddr_in6 *)&sa1.daddr; 454 if (inet_pton(AF_INET6, spikey, &sin6->sin6_addr) == 1) { 455 #ifdef HAVE_SOCKADDR_SA_LEN 456 sin6->sin6_len = sizeof(struct sockaddr_in6); 457 #endif 458 sin6->sin6_family = AF_INET6; 459 } else 460 #endif 461 if (inet_pton(AF_INET, spikey, &sin->sin_addr) == 1) { 462 #ifdef HAVE_SOCKADDR_SA_LEN 463 sin->sin_len = sizeof(struct sockaddr_in); 464 #endif 465 sin->sin_family = AF_INET; 466 } else { 467 (*ndo->ndo_warning)(ndo, "print_esp: can not decode IP# %s\n", spikey); 468 return; 469 } 470 } 471 472 if (decode) { 473 /* skip any blank spaces */ 474 while (isspace((unsigned char)*decode)) 475 decode++; 476 477 if(!espprint_decode_encalgo(ndo, decode, &sa1)) { 478 return; 479 } 480 } 481 482 esp_print_addsa(ndo, &sa1, sa_def); 483 } 484 485 static void esp_init(netdissect_options *ndo _U_) 486 { 487 488 OpenSSL_add_all_algorithms(); 489 EVP_add_cipher_alias(SN_des_ede3_cbc, "3des"); 490 } 491 492 void esp_print_decodesecret(netdissect_options *ndo) 493 { 494 char *line; 495 char *p; 496 static int initialized = 0; 497 498 if (!initialized) { 499 esp_init(ndo); 500 initialized = 1; 501 } 502 503 p = ndo->ndo_espsecret; 504 505 while (p && p[0] != '\0') { 506 /* pick out the first line or first thing until a comma */ 507 if ((line = strsep(&p, "\n,")) == NULL) { 508 line = p; 509 p = NULL; 510 } 511 512 esp_print_decode_onesecret(ndo, line, "cmdline", 0); 513 } 514 515 ndo->ndo_espsecret = NULL; 516 } 517 518 #endif 519 520 int 521 esp_print(netdissect_options *ndo, 522 const u_char *bp, const int length, const u_char *bp2 523 #ifndef HAVE_LIBCRYPTO 524 _U_ 525 #endif 526 , 527 int *nhdr 528 #ifndef HAVE_LIBCRYPTO 529 _U_ 530 #endif 531 , 532 int *padlen 533 #ifndef HAVE_LIBCRYPTO 534 _U_ 535 #endif 536 ) 537 { 538 register const struct newesp *esp; 539 register const u_char *ep; 540 #ifdef HAVE_LIBCRYPTO 541 struct ip *ip; 542 struct sa_list *sa = NULL; 543 int espsecret_keylen; 544 #ifdef INET6 545 struct ip6_hdr *ip6 = NULL; 546 #endif 547 int advance; 548 int len; 549 u_char *secret; 550 int ivlen = 0; 551 u_char *ivoff; 552 u_char *p; 553 EVP_CIPHER_CTX ctx; 554 int blocksz; 555 #endif 556 557 esp = (struct newesp *)bp; 558 559 #ifdef HAVE_LIBCRYPTO 560 secret = NULL; 561 advance = 0; 562 #endif 563 564 #if 0 565 /* keep secret out of a register */ 566 p = (u_char *)&secret; 567 #endif 568 569 /* 'ep' points to the end of available data. */ 570 ep = ndo->ndo_snapend; 571 572 if ((u_char *)(esp + 1) >= ep) { 573 fputs("[|ESP]", stdout); 574 goto fail; 575 } 576 (*ndo->ndo_printf)(ndo, "ESP(spi=0x%08x", EXTRACT_32BITS(&esp->esp_spi)); 577 (*ndo->ndo_printf)(ndo, ",seq=0x%x)", EXTRACT_32BITS(&esp->esp_seq)); 578 (*ndo->ndo_printf)(ndo, ", length %u", length); 579 580 #ifndef HAVE_LIBCRYPTO 581 goto fail; 582 #else 583 /* initiailize SAs */ 584 if (ndo->ndo_sa_list_head == NULL) { 585 if (!ndo->ndo_espsecret) 586 goto fail; 587 588 esp_print_decodesecret(ndo); 589 } 590 591 if (ndo->ndo_sa_list_head == NULL) 592 goto fail; 593 594 ip = (struct ip *)bp2; 595 switch (IP_V(ip)) { 596 #ifdef INET6 597 case 6: 598 ip6 = (struct ip6_hdr *)bp2; 599 /* we do not attempt to decrypt jumbograms */ 600 if (!EXTRACT_16BITS(&ip6->ip6_plen)) 601 goto fail; 602 /* if we can't get nexthdr, we do not need to decrypt it */ 603 len = sizeof(struct ip6_hdr) + EXTRACT_16BITS(&ip6->ip6_plen); 604 605 /* see if we can find the SA, and if so, decode it */ 606 for (sa = ndo->ndo_sa_list_head; sa != NULL; sa = sa->next) { 607 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&sa->daddr; 608 if (sa->spi == EXTRACT_32BITS(&esp->esp_spi) && 609 sin6->sin6_family == AF_INET6 && 610 memcmp(&sin6->sin6_addr, &ip6->ip6_dst, 611 sizeof(struct in6_addr)) == 0) { 612 break; 613 } 614 } 615 break; 616 #endif /*INET6*/ 617 case 4: 618 /* nexthdr & padding are in the last fragment */ 619 if (EXTRACT_16BITS(&ip->ip_off) & IP_MF) 620 goto fail; 621 len = EXTRACT_16BITS(&ip->ip_len); 622 623 /* see if we can find the SA, and if so, decode it */ 624 for (sa = ndo->ndo_sa_list_head; sa != NULL; sa = sa->next) { 625 struct sockaddr_in *sin = (struct sockaddr_in *)&sa->daddr; 626 if (sa->spi == EXTRACT_32BITS(&esp->esp_spi) && 627 sin->sin_family == AF_INET && 628 sin->sin_addr.s_addr == ip->ip_dst.s_addr) { 629 break; 630 } 631 } 632 break; 633 default: 634 goto fail; 635 } 636 637 /* if we didn't find the specific one, then look for 638 * an unspecified one. 639 */ 640 if (sa == NULL) 641 sa = ndo->ndo_sa_default; 642 643 /* if not found fail */ 644 if (sa == NULL) 645 goto fail; 646 647 /* if we can't get nexthdr, we do not need to decrypt it */ 648 if (ep - bp2 < len) 649 goto fail; 650 if (ep - bp2 > len) { 651 /* FCS included at end of frame (NetBSD 1.6 or later) */ 652 ep = bp2 + len; 653 } 654 655 ivoff = (u_char *)(esp + 1) + 0; 656 ivlen = sa->ivlen; 657 secret = sa->secret; 658 espsecret_keylen = sa->secretlen; 659 ep = ep - sa->authlen; 660 661 if (sa->evp) { 662 memset(&ctx, 0, sizeof(ctx)); 663 if (EVP_CipherInit(&ctx, sa->evp, secret, NULL, 0) < 0) 664 (*ndo->ndo_warning)(ndo, "espkey init failed"); 665 666 blocksz = EVP_CIPHER_CTX_block_size(&ctx); 667 668 p = ivoff; 669 EVP_CipherInit(&ctx, NULL, NULL, p, 0); 670 EVP_Cipher(&ctx, p + ivlen, p + ivlen, ep - (p + ivlen)); 671 EVP_CIPHER_CTX_cleanup(&ctx); 672 advance = ivoff - (u_char *)esp + ivlen; 673 } else 674 advance = sizeof(struct newesp); 675 676 /* sanity check for pad length */ 677 if (ep - bp < *(ep - 2)) 678 goto fail; 679 680 if (padlen) 681 *padlen = *(ep - 2) + 2; 682 683 if (nhdr) 684 *nhdr = *(ep - 1); 685 686 (ndo->ndo_printf)(ndo, ": "); 687 return advance; 688 #endif 689 690 fail: 691 return -1; 692 } 693 694 /* 695 * Local Variables: 696 * c-style: whitesmith 697 * c-basic-offset: 8 698 * End: 699 */ 700