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.44.2.4 2003/11/19 05:36:40 guy 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 #if defined(__MINGW32__) || defined(__WATCOMC__) 54 extern char *strsep(char **stringp, const char *delim); /* Missing/strsep.c */ 55 #endif 56 57 #include "interface.h" 58 #include "addrtoname.h" 59 #include "extract.h" 60 61 #ifndef HAVE_SOCKADDR_STORAGE 62 #ifdef INET6 63 struct sockaddr_storage { 64 union { 65 struct sockaddr_in sin; 66 struct sockaddr_in6 sin6; 67 } un; 68 }; 69 #else 70 #define sockaddr_storage sockaddr 71 #endif 72 #endif /* HAVE_SOCKADDR_STORAGE */ 73 74 #ifdef HAVE_LIBCRYPTO 75 struct sa_list { 76 struct sa_list *next; 77 struct sockaddr_storage daddr; 78 u_int32_t spi; 79 const EVP_CIPHER *evp; 80 int ivlen; 81 int authlen; 82 char secret[256]; /* is that big enough for all secrets? */ 83 int secretlen; 84 }; 85 86 static struct sa_list *sa_list_head = NULL; 87 static struct sa_list *sa_default = NULL; 88 89 static void esp_print_addsa(struct sa_list *sa, int sa_def) 90 { 91 /* copy the "sa" */ 92 93 struct sa_list *nsa; 94 95 nsa = (struct sa_list *)malloc(sizeof(struct sa_list)); 96 if (nsa == NULL) 97 error("ran out of memory to allocate sa structure"); 98 99 *nsa = *sa; 100 101 if (sa_def) 102 sa_default = nsa; 103 104 nsa->next = sa_list_head; 105 sa_list_head = nsa; 106 } 107 108 109 static int hexdigit(char hex) 110 { 111 if (hex >= '0' && hex <= '9') 112 return (hex - '0'); 113 else if (hex >= 'A' && hex <= 'F') 114 return (hex - 'A' + 10); 115 else if (hex >= 'a' && hex <= 'f') 116 return (hex - 'a' + 10); 117 else { 118 printf("invalid hex digit %c in espsecret\n", hex); 119 return 0; 120 } 121 } 122 123 static int hex2byte(char *hexstring) 124 { 125 int byte; 126 127 byte = (hexdigit(hexstring[0]) << 4) + hexdigit(hexstring[1]); 128 return byte; 129 } 130 131 /* 132 * decode the form: SPINUM@IP <tab> ALGONAME:0xsecret 133 * 134 * special form: file /name 135 * causes us to go read from this file instead. 136 * 137 */ 138 static void esp_print_decode_onesecret(char *line) 139 { 140 struct sa_list sa1; 141 int sa_def; 142 143 char *spikey; 144 char *decode; 145 146 spikey = strsep(&line, " \t"); 147 sa_def = 0; 148 memset(&sa1, 0, sizeof(struct sa_list)); 149 150 /* if there is only one token, then it is an algo:key token */ 151 if (line == NULL) { 152 decode = spikey; 153 spikey = NULL; 154 /* memset(&sa1.daddr, 0, sizeof(sa1.daddr)); */ 155 /* sa1.spi = 0; */ 156 sa_def = 1; 157 } else 158 decode = line; 159 160 if (spikey && strcasecmp(spikey, "file") == 0) { 161 /* open file and read it */ 162 FILE *secretfile; 163 char fileline[1024]; 164 char *nl; 165 166 secretfile = fopen(line, FOPEN_READ_TXT); 167 if (secretfile == NULL) { 168 perror(line); 169 exit(3); 170 } 171 172 while (fgets(fileline, sizeof(fileline)-1, secretfile) != NULL) { 173 /* remove newline from the line */ 174 nl = strchr(fileline, '\n'); 175 if (nl) 176 *nl = '\0'; 177 if (fileline[0] == '#') continue; 178 if (fileline[0] == '\0') continue; 179 180 esp_print_decode_onesecret(fileline); 181 } 182 fclose(secretfile); 183 184 return; 185 } 186 187 if (spikey) { 188 char *spistr, *foo; 189 u_int32_t spino; 190 struct sockaddr_in *sin; 191 #ifdef INET6 192 struct sockaddr_in6 *sin6; 193 #endif 194 195 spistr = strsep(&spikey, "@"); 196 197 spino = strtoul(spistr, &foo, 0); 198 if (spistr == foo || !spikey) { 199 printf("print_esp: failed to decode spi# %s\n", foo); 200 return; 201 } 202 203 sa1.spi = spino; 204 205 sin = (struct sockaddr_in *)&sa1.daddr; 206 #ifdef INET6 207 sin6 = (struct sockaddr_in6 *)&sa1.daddr; 208 if (inet_pton(AF_INET6, spikey, &sin6->sin6_addr) == 1) { 209 #ifdef HAVE_SOCKADDR_SA_LEN 210 sin6->sin6_len = sizeof(struct sockaddr_in6); 211 #endif 212 sin6->sin6_family = AF_INET6; 213 } else 214 #endif 215 if (inet_pton(AF_INET, spikey, &sin->sin_addr) == 1) { 216 #ifdef HAVE_SOCKADDR_SA_LEN 217 sin->sin_len = sizeof(struct sockaddr_in); 218 #endif 219 sin->sin_family = AF_INET; 220 } else { 221 printf("print_esp: can not decode IP# %s\n", spikey); 222 return; 223 } 224 } 225 226 if (decode) { 227 char *colon, *p; 228 char espsecret_key[256]; 229 int len; 230 size_t i; 231 const EVP_CIPHER *evp; 232 int ivlen = 8; 233 int authlen = 0; 234 235 /* skip any blank spaces */ 236 while (isspace((unsigned char)*decode)) 237 decode++; 238 239 colon = strchr(decode, ':'); 240 if (colon == NULL) { 241 printf("failed to decode espsecret: %s\n", decode); 242 return; 243 } 244 *colon = '\0'; 245 246 len = colon - decode; 247 if (strlen(decode) > strlen("-hmac96") && 248 !strcmp(decode + strlen(decode) - strlen("-hmac96"), 249 "-hmac96")) { 250 p = strstr(decode, "-hmac96"); 251 *p = '\0'; 252 authlen = 12; 253 } 254 if (strlen(decode) > strlen("-cbc") && 255 !strcmp(decode + strlen(decode) - strlen("-cbc"), "-cbc")) { 256 p = strstr(decode, "-cbc"); 257 *p = '\0'; 258 } 259 evp = EVP_get_cipherbyname(decode); 260 if (!evp) { 261 printf("failed to find cipher algo %s\n", decode); 262 sa1.evp = NULL; 263 sa1.authlen = 0; 264 sa1.ivlen = 0; 265 return; 266 } 267 268 sa1.evp = evp; 269 sa1.authlen = authlen; 270 sa1.ivlen = ivlen; 271 272 colon++; 273 if (colon[0] == '0' && colon[1] == 'x') { 274 /* decode some hex! */ 275 colon += 2; 276 len = strlen(colon) / 2; 277 278 if (len > 256) { 279 printf("secret is too big: %d\n", len); 280 return; 281 } 282 283 i = 0; 284 while (colon[0] != '\0' && colon[1]!='\0') { 285 espsecret_key[i] = hex2byte(colon); 286 colon += 2; 287 i++; 288 } 289 290 memcpy(sa1.secret, espsecret_key, i); 291 sa1.secretlen = i; 292 } else { 293 i = strlen(colon); 294 295 if (i < sizeof(sa1.secret)) { 296 memcpy(sa1.secret, colon, i); 297 sa1.secretlen = i; 298 } else { 299 memcpy(sa1.secret, colon, sizeof(sa1.secret)); 300 sa1.secretlen = sizeof(sa1.secret); 301 } 302 } 303 } 304 305 esp_print_addsa(&sa1, sa_def); 306 } 307 308 static void esp_print_decodesecret(void) 309 { 310 char *line; 311 char *p; 312 313 p = espsecret; 314 315 while (espsecret && espsecret[0] != '\0') { 316 /* pick out the first line or first thing until a comma */ 317 if ((line = strsep(&espsecret, "\n,")) == NULL) { 318 line = espsecret; 319 espsecret = NULL; 320 } 321 322 esp_print_decode_onesecret(line); 323 } 324 } 325 326 static void esp_init(void) 327 { 328 329 OpenSSL_add_all_algorithms(); 330 EVP_add_cipher_alias(SN_des_ede3_cbc, "3des"); 331 } 332 #endif 333 334 int 335 esp_print(const u_char *bp, const u_char *bp2 336 #ifndef HAVE_LIBCRYPTO 337 _U_ 338 #endif 339 , 340 int *nhdr 341 #ifndef HAVE_LIBCRYPTO 342 _U_ 343 #endif 344 , 345 int *padlen 346 #ifndef HAVE_LIBCRYPTO 347 _U_ 348 #endif 349 ) 350 { 351 register const struct newesp *esp; 352 register const u_char *ep; 353 #ifdef HAVE_LIBCRYPTO 354 struct ip *ip; 355 struct sa_list *sa = NULL; 356 int espsecret_keylen; 357 #ifdef INET6 358 struct ip6_hdr *ip6 = NULL; 359 #endif 360 int advance; 361 int len; 362 char *secret; 363 int ivlen = 0; 364 u_char *ivoff; 365 const u_char *p; 366 EVP_CIPHER_CTX ctx; 367 int blocksz; 368 static int initialized = 0; 369 #endif 370 371 esp = (struct newesp *)bp; 372 373 #ifdef HAVE_LIBCRYPTO 374 secret = NULL; 375 advance = 0; 376 377 if (!initialized) { 378 esp_init(); 379 initialized = 1; 380 } 381 #endif 382 383 #if 0 384 /* keep secret out of a register */ 385 p = (u_char *)&secret; 386 #endif 387 388 /* 'ep' points to the end of available data. */ 389 ep = snapend; 390 391 if ((u_char *)(esp + 1) >= ep) { 392 fputs("[|ESP]", stdout); 393 goto fail; 394 } 395 printf("ESP(spi=0x%08x", EXTRACT_32BITS(&esp->esp_spi)); 396 printf(",seq=0x%x", EXTRACT_32BITS(&esp->esp_seq)); 397 printf(")"); 398 399 #ifndef HAVE_LIBCRYPTO 400 goto fail; 401 #else 402 /* initiailize SAs */ 403 if (sa_list_head == NULL) { 404 if (!espsecret) 405 goto fail; 406 407 esp_print_decodesecret(); 408 } 409 410 if (sa_list_head == NULL) 411 goto fail; 412 413 ip = (struct ip *)bp2; 414 switch (IP_V(ip)) { 415 #ifdef INET6 416 case 6: 417 ip6 = (struct ip6_hdr *)bp2; 418 /* we do not attempt to decrypt jumbograms */ 419 if (!EXTRACT_16BITS(&ip6->ip6_plen)) 420 goto fail; 421 /* if we can't get nexthdr, we do not need to decrypt it */ 422 len = sizeof(struct ip6_hdr) + EXTRACT_16BITS(&ip6->ip6_plen); 423 424 /* see if we can find the SA, and if so, decode it */ 425 for (sa = sa_list_head; sa != NULL; sa = sa->next) { 426 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&sa->daddr; 427 if (sa->spi == ntohl(esp->esp_spi) && 428 sin6->sin6_family == AF_INET6 && 429 memcmp(&sin6->sin6_addr, &ip6->ip6_dst, 430 sizeof(struct in6_addr)) == 0) { 431 break; 432 } 433 } 434 break; 435 #endif /*INET6*/ 436 case 4: 437 /* nexthdr & padding are in the last fragment */ 438 if (EXTRACT_16BITS(&ip->ip_off) & IP_MF) 439 goto fail; 440 len = EXTRACT_16BITS(&ip->ip_len); 441 442 /* see if we can find the SA, and if so, decode it */ 443 for (sa = sa_list_head; sa != NULL; sa = sa->next) { 444 struct sockaddr_in *sin = (struct sockaddr_in *)&sa->daddr; 445 if (sa->spi == ntohl(esp->esp_spi) && 446 sin->sin_family == AF_INET && 447 sin->sin_addr.s_addr == ip->ip_dst.s_addr) { 448 break; 449 } 450 } 451 break; 452 default: 453 goto fail; 454 } 455 456 /* if we didn't find the specific one, then look for 457 * an unspecified one. 458 */ 459 if (sa == NULL) 460 sa = sa_default; 461 462 /* if not found fail */ 463 if (sa == NULL) 464 goto fail; 465 466 /* if we can't get nexthdr, we do not need to decrypt it */ 467 if (ep - bp2 < len) 468 goto fail; 469 if (ep - bp2 > len) { 470 /* FCS included at end of frame (NetBSD 1.6 or later) */ 471 ep = bp2 + len; 472 } 473 474 ivoff = (u_char *)(esp + 1) + 0; 475 ivlen = sa->ivlen; 476 secret = sa->secret; 477 espsecret_keylen = sa->secretlen; 478 479 if (sa->evp) { 480 memset(&ctx, 0, sizeof(ctx)); 481 if (EVP_CipherInit(&ctx, sa->evp, secret, NULL, 0) < 0) 482 printf("espkey init failed"); 483 484 blocksz = EVP_CIPHER_CTX_block_size(&ctx); 485 486 p = ivoff; 487 EVP_CipherInit(&ctx, NULL, NULL, p, 0); 488 EVP_Cipher(&ctx, p + ivlen, p + ivlen, ep - (p + ivlen)); 489 advance = ivoff - (u_char *)esp + ivlen; 490 } else 491 advance = sizeof(struct newesp); 492 493 ep = ep - sa->authlen; 494 /* sanity check for pad length */ 495 if (ep - bp < *(ep - 2)) 496 goto fail; 497 498 if (padlen) 499 *padlen = *(ep - 2) + 2; 500 501 if (nhdr) 502 *nhdr = *(ep - 1); 503 504 printf(": "); 505 return advance; 506 #endif 507 508 fail: 509 return -1; 510 } 511