1b0453382SBill Fenner /* $NetBSD: print-ah.c,v 1.4 1996/05/20 00:41:16 fvdl Exp $ */ 2b0453382SBill Fenner 3b0453382SBill Fenner /* 4b0453382SBill Fenner * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994 5b0453382SBill Fenner * The Regents of the University of California. All rights reserved. 6b0453382SBill Fenner * 7b0453382SBill Fenner * Redistribution and use in source and binary forms, with or without 8b0453382SBill Fenner * modification, are permitted provided that: (1) source code distributions 9b0453382SBill Fenner * retain the above copyright notice and this paragraph in its entirety, (2) 10b0453382SBill Fenner * distributions including binary code include the above copyright notice and 11b0453382SBill Fenner * this paragraph in its entirety in the documentation or other materials 12b0453382SBill Fenner * provided with the distribution, and (3) all advertising materials mentioning 13b0453382SBill Fenner * features or use of this software display the following acknowledgement: 14b0453382SBill Fenner * ``This product includes software developed by the University of California, 15b0453382SBill Fenner * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 16b0453382SBill Fenner * the University nor the names of its contributors may be used to endorse 17b0453382SBill Fenner * or promote products derived from this software without specific prior 18b0453382SBill Fenner * written permission. 19b0453382SBill Fenner * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 20b0453382SBill Fenner * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 21b0453382SBill Fenner * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 22b0453382SBill Fenner */ 23b0453382SBill Fenner 24b0453382SBill Fenner #ifndef lint 25b0453382SBill Fenner static const char rcsid[] = 26a90e161bSBill Fenner "@(#) $Header: /tcpdump/master/tcpdump/print-esp.c,v 1.20 2002/01/21 11:39:59 mcr Exp $ (LBL)"; 27b0453382SBill Fenner #endif 28b0453382SBill Fenner 29b0453382SBill Fenner #ifdef HAVE_CONFIG_H 30b0453382SBill Fenner #include "config.h" 31b0453382SBill Fenner #endif 32b0453382SBill Fenner 33b0453382SBill Fenner #include <string.h> 34b0453382SBill Fenner #include <sys/param.h> 35b0453382SBill Fenner #include <sys/time.h> 36b0453382SBill Fenner #include <sys/types.h> 37b0453382SBill Fenner #include <sys/socket.h> 38b0453382SBill Fenner 39b0453382SBill Fenner #include <netinet/in.h> 40b0453382SBill Fenner 41685295f4SBill Fenner #ifdef HAVE_LIBCRYPTO 42a90e161bSBill Fenner #include <openssl/des.h> 43a90e161bSBill Fenner #include <openssl/blowfish.h> 44b0453382SBill Fenner #ifdef HAVE_RC5_H 45a90e161bSBill Fenner #include <openssl/rc5.h> 46b0453382SBill Fenner #endif 47b0453382SBill Fenner #ifdef HAVE_CAST_H 48a90e161bSBill Fenner #include <openssl/cast.h> 49b0453382SBill Fenner #endif 50b0453382SBill Fenner #endif 51b0453382SBill Fenner 52b0453382SBill Fenner #include <stdio.h> 53b0453382SBill Fenner 54685295f4SBill Fenner #include "ip.h" 55685295f4SBill Fenner #include "esp.h" 56b0453382SBill Fenner #ifdef INET6 57685295f4SBill Fenner #include "ip6.h" 58b0453382SBill Fenner #endif 59b0453382SBill Fenner 60a90e161bSBill Fenner #define AVOID_CHURN 1 61b0453382SBill Fenner #include "interface.h" 62b0453382SBill Fenner #include "addrtoname.h" 63b0453382SBill Fenner 64a90e161bSBill Fenner static struct esp_algorithm *espsecret_xform=NULL; /* cache of decoded alg. */ 65a90e161bSBill Fenner static char *espsecret_key=NULL; 66a90e161bSBill Fenner 67a90e161bSBill Fenner 68a90e161bSBill Fenner enum cipher { NONE, 69a90e161bSBill Fenner DESCBC, 70a90e161bSBill Fenner BLOWFISH, 71a90e161bSBill Fenner RC5, 72a90e161bSBill Fenner CAST128, 73a90e161bSBill Fenner DES3CBC}; 74a90e161bSBill Fenner 75a90e161bSBill Fenner 76a90e161bSBill Fenner 77a90e161bSBill Fenner struct esp_algorithm { 78a90e161bSBill Fenner char *name; 79a90e161bSBill Fenner enum cipher algo; 80a90e161bSBill Fenner int ivlen; 81a90e161bSBill Fenner int authlen; 82a90e161bSBill Fenner int replaysize; 83a90e161bSBill Fenner }; 84a90e161bSBill Fenner 85a90e161bSBill Fenner struct esp_algorithm esp_xforms[]={ 86a90e161bSBill Fenner {"none", NONE, 0, 0, 0}, 87a90e161bSBill Fenner {"des-cbc", DESCBC, 8, 0, 0}, 88a90e161bSBill Fenner {"des-cbc-hmac96", DESCBC, 8, 12, 4}, 89a90e161bSBill Fenner {"blowfish-cbc", BLOWFISH,8, 0, 0}, 90a90e161bSBill Fenner {"blowfish-cbc-hmac96", BLOWFISH,8, 12, 4}, 91a90e161bSBill Fenner {"rc5-cbc", RC5, 8, 0, 0}, 92a90e161bSBill Fenner {"rc5-cbc-hmac96", RC5, 8, 12, 4}, 93a90e161bSBill Fenner {"cast128-cbc", CAST128, 8, 0, 0}, 94a90e161bSBill Fenner {"cast128-cbc-hmac96", CAST128, 8, 12, 4}, 95a90e161bSBill Fenner {"3des-cbc-hmac96", DES3CBC, 8, 12, 4}, 96a90e161bSBill Fenner }; 97a90e161bSBill Fenner 98a90e161bSBill Fenner static int hexdigit(char hex) 99a90e161bSBill Fenner { 100a90e161bSBill Fenner if(hex >= '0' && hex <= '9') { 101a90e161bSBill Fenner return (hex - '0'); 102a90e161bSBill Fenner } else if(hex >= 'A' && hex <= 'F') { 103a90e161bSBill Fenner return (hex - 'A' + 10); 104a90e161bSBill Fenner } else if(hex >= 'a' && hex <= 'f') { 105a90e161bSBill Fenner return (hex - 'a' + 10); 106a90e161bSBill Fenner } else { 107a90e161bSBill Fenner printf("invalid hex digit %c in espsecret\n", hex); 108a90e161bSBill Fenner return 0; 109a90e161bSBill Fenner } 110a90e161bSBill Fenner } 111a90e161bSBill Fenner 112a90e161bSBill Fenner static int hex2byte(char *hexstring) 113a90e161bSBill Fenner { 114a90e161bSBill Fenner int byte; 115a90e161bSBill Fenner 116a90e161bSBill Fenner byte = (hexdigit(hexstring[0]) << 4) + 117a90e161bSBill Fenner hexdigit(hexstring[1]); 118a90e161bSBill Fenner return byte; 119a90e161bSBill Fenner } 120a90e161bSBill Fenner 121a90e161bSBill Fenner 122a90e161bSBill Fenner void esp_print_decodesecret() 123a90e161bSBill Fenner { 124a90e161bSBill Fenner char *colon; 125a90e161bSBill Fenner int len, i; 126a90e161bSBill Fenner struct esp_algorithm *xf; 127a90e161bSBill Fenner 128a90e161bSBill Fenner if(espsecret == NULL) { 129a90e161bSBill Fenner /* set to NONE transform */ 130a90e161bSBill Fenner espsecret_xform = esp_xforms; 131a90e161bSBill Fenner return; 132a90e161bSBill Fenner } 133a90e161bSBill Fenner 134a90e161bSBill Fenner if(espsecret_key != NULL) { 135a90e161bSBill Fenner return; 136a90e161bSBill Fenner } 137a90e161bSBill Fenner 138a90e161bSBill Fenner colon = strchr(espsecret, ':'); 139a90e161bSBill Fenner if(colon == NULL) { 140a90e161bSBill Fenner printf("failed to decode espsecret: %s\n", 141a90e161bSBill Fenner espsecret); 142a90e161bSBill Fenner /* set to NONE transform */ 143a90e161bSBill Fenner espsecret_xform = esp_xforms; 144a90e161bSBill Fenner } 145a90e161bSBill Fenner 146a90e161bSBill Fenner len = colon - espsecret; 147a90e161bSBill Fenner xf = esp_xforms; 148a90e161bSBill Fenner while(xf->name && strncasecmp(espsecret, xf->name, len)!=0) { 149a90e161bSBill Fenner xf++; 150a90e161bSBill Fenner } 151a90e161bSBill Fenner if(xf->name == NULL) { 152a90e161bSBill Fenner printf("failed to find cipher algo %s\n", 153a90e161bSBill Fenner espsecret); 154a90e161bSBill Fenner espsecret_xform = esp_xforms; 155a90e161bSBill Fenner return; 156a90e161bSBill Fenner } 157a90e161bSBill Fenner espsecret_xform = xf; 158a90e161bSBill Fenner 159a90e161bSBill Fenner colon++; 160a90e161bSBill Fenner if(colon[0]=='0' && colon[1]=='x') { 161a90e161bSBill Fenner /* decode some hex! */ 162a90e161bSBill Fenner colon+=2; 163a90e161bSBill Fenner len = strlen(colon) / 2; 164a90e161bSBill Fenner espsecret_key = (char *)malloc(len); 165a90e161bSBill Fenner if(espsecret_key == NULL) { 166a90e161bSBill Fenner fprintf(stderr, "%s: ran out of memory (%d) to allocate secret key\n", 167a90e161bSBill Fenner program_name, len); 168a90e161bSBill Fenner exit(2); 169a90e161bSBill Fenner } 170a90e161bSBill Fenner i = 0; 171a90e161bSBill Fenner while(colon[0] != '\0' && colon[1]!='\0') { 172a90e161bSBill Fenner espsecret_key[i]=hex2byte(colon); 173a90e161bSBill Fenner colon+=2; 174a90e161bSBill Fenner i++; 175a90e161bSBill Fenner } 176a90e161bSBill Fenner } else { 177a90e161bSBill Fenner espsecret_key = colon; 178a90e161bSBill Fenner } 179a90e161bSBill Fenner } 180a90e161bSBill Fenner 181b0453382SBill Fenner int 182a90e161bSBill Fenner esp_print(register const u_char *bp, register const u_char *bp2, 183a90e161bSBill Fenner int *nhdr, int *padlen) 184b0453382SBill Fenner { 185b0453382SBill Fenner register const struct esp *esp; 186b0453382SBill Fenner register const u_char *ep; 187b0453382SBill Fenner u_int32_t spi; 188b0453382SBill Fenner struct ip *ip = NULL; 189b0453382SBill Fenner #ifdef INET6 190b0453382SBill Fenner struct ip6_hdr *ip6 = NULL; 191b0453382SBill Fenner #endif 192b0453382SBill Fenner int advance; 193b0453382SBill Fenner int len; 194a90e161bSBill Fenner char *secret; 195b0453382SBill Fenner int ivlen = 0; 196b0453382SBill Fenner u_char *ivoff; 197a90e161bSBill Fenner u_char *p; 198b0453382SBill Fenner 199b0453382SBill Fenner esp = (struct esp *)bp; 200b0453382SBill Fenner spi = (u_int32_t)ntohl(esp->esp_spi); 201a90e161bSBill Fenner secret = NULL; 202a90e161bSBill Fenner 203a90e161bSBill Fenner #if 0 204a90e161bSBill Fenner /* keep secret out of a register */ 205a90e161bSBill Fenner p = (u_char *)&secret; 206a90e161bSBill Fenner #endif 207b0453382SBill Fenner 208685295f4SBill Fenner /* 'ep' points to the end of available data. */ 209b0453382SBill Fenner ep = snapend; 210b0453382SBill Fenner 211b0453382SBill Fenner if ((u_char *)(esp + 1) >= ep - sizeof(struct esp)) { 212b0453382SBill Fenner fputs("[|ESP]", stdout); 213b0453382SBill Fenner goto fail; 214b0453382SBill Fenner } 215685295f4SBill Fenner printf("ESP(spi=0x%08x", spi); 216b0453382SBill Fenner printf(",seq=0x%x", (u_int32_t)ntohl(*(u_int32_t *)(esp + 1))); 217b0453382SBill Fenner printf(")"); 218b0453382SBill Fenner 219b0453382SBill Fenner /* if we don't have decryption key, we can't decrypt this packet. */ 220b0453382SBill Fenner if (!espsecret) 221b0453382SBill Fenner goto fail; 222b0453382SBill Fenner 223a90e161bSBill Fenner if(!espsecret_xform) { 224a90e161bSBill Fenner esp_print_decodesecret(); 225a90e161bSBill Fenner } 226a90e161bSBill Fenner if(espsecret_xform->algo == NONE) { 227a90e161bSBill Fenner goto fail; 228b0453382SBill Fenner } 229b0453382SBill Fenner 230b0453382SBill Fenner ip = (struct ip *)bp2; 231685295f4SBill Fenner switch (IP_V(ip)) { 232b0453382SBill Fenner #ifdef INET6 233b0453382SBill Fenner case 6: 234b0453382SBill Fenner ip6 = (struct ip6_hdr *)bp2; 235b0453382SBill Fenner ip = NULL; 236b0453382SBill Fenner /* we do not attempt to decrypt jumbograms */ 237b0453382SBill Fenner if (!ntohs(ip6->ip6_plen)) 238b0453382SBill Fenner goto fail; 239b0453382SBill Fenner /* if we can't get nexthdr, we do not need to decrypt it */ 240b0453382SBill Fenner len = sizeof(struct ip6_hdr) + ntohs(ip6->ip6_plen); 241b0453382SBill Fenner break; 242b0453382SBill Fenner #endif /*INET6*/ 243b0453382SBill Fenner case 4: 244a90e161bSBill Fenner /* nexthdr & padding are in the last fragment */ 245a90e161bSBill Fenner if (ntohs(ip->ip_off) & IP_MF) 246a90e161bSBill Fenner goto fail; 247b0453382SBill Fenner #ifdef INET6 248b0453382SBill Fenner ip6 = NULL; 249b0453382SBill Fenner #endif 250b0453382SBill Fenner len = ntohs(ip->ip_len); 251b0453382SBill Fenner break; 252b0453382SBill Fenner default: 253b0453382SBill Fenner goto fail; 254b0453382SBill Fenner } 255b0453382SBill Fenner 256b0453382SBill Fenner /* if we can't get nexthdr, we do not need to decrypt it */ 257b0453382SBill Fenner if (ep - bp2 < len) 258b0453382SBill Fenner goto fail; 259b0453382SBill Fenner 260a90e161bSBill Fenner ivoff = (u_char *)(esp + 1) + espsecret_xform->replaysize; 261a90e161bSBill Fenner ivlen = espsecret_xform->ivlen; 262a90e161bSBill Fenner secret = espsecret_key; 263b0453382SBill Fenner 264a90e161bSBill Fenner switch (espsecret_xform->algo) { 265b0453382SBill Fenner case DESCBC: 266685295f4SBill Fenner #ifdef HAVE_LIBCRYPTO 267b0453382SBill Fenner { 268b0453382SBill Fenner u_char iv[8]; 269b0453382SBill Fenner des_key_schedule schedule; 270b0453382SBill Fenner 271b0453382SBill Fenner switch (ivlen) { 272b0453382SBill Fenner case 4: 273b0453382SBill Fenner memcpy(iv, ivoff, 4); 274b0453382SBill Fenner memcpy(&iv[4], ivoff, 4); 275b0453382SBill Fenner p = &iv[4]; 276b0453382SBill Fenner *p++ ^= 0xff; 277b0453382SBill Fenner *p++ ^= 0xff; 278b0453382SBill Fenner *p++ ^= 0xff; 279b0453382SBill Fenner *p++ ^= 0xff; 280b0453382SBill Fenner break; 281b0453382SBill Fenner case 8: 282b0453382SBill Fenner memcpy(iv, ivoff, 8); 283b0453382SBill Fenner break; 284b0453382SBill Fenner default: 285b0453382SBill Fenner goto fail; 286b0453382SBill Fenner } 287b0453382SBill Fenner 288b0453382SBill Fenner des_check_key = 0; 289b0453382SBill Fenner des_set_key((void *)secret, schedule); 290b0453382SBill Fenner 291b0453382SBill Fenner p = ivoff + ivlen; 292b0453382SBill Fenner des_cbc_encrypt((void *)p, (void *)p, 293b0453382SBill Fenner (long)(ep - p), schedule, (void *)iv, 294b0453382SBill Fenner DES_DECRYPT); 295b0453382SBill Fenner advance = ivoff - (u_char *)esp + ivlen; 296b0453382SBill Fenner break; 297b0453382SBill Fenner } 298b0453382SBill Fenner #else 299b0453382SBill Fenner goto fail; 300685295f4SBill Fenner #endif /*HAVE_LIBCRYPTO*/ 301b0453382SBill Fenner 302b0453382SBill Fenner case BLOWFISH: 303685295f4SBill Fenner #ifdef HAVE_LIBCRYPTO 304b0453382SBill Fenner { 305b0453382SBill Fenner BF_KEY schedule; 306b0453382SBill Fenner 307b0453382SBill Fenner BF_set_key(&schedule, strlen(secret), secret); 308b0453382SBill Fenner 309b0453382SBill Fenner p = ivoff + ivlen; 310b0453382SBill Fenner BF_cbc_encrypt(p, p, (long)(ep - p), &schedule, ivoff, 311b0453382SBill Fenner BF_DECRYPT); 312b0453382SBill Fenner advance = ivoff - (u_char *)esp + ivlen; 313b0453382SBill Fenner break; 314b0453382SBill Fenner } 315b0453382SBill Fenner #else 316b0453382SBill Fenner goto fail; 317685295f4SBill Fenner #endif /*HAVE_LIBCRYPTO*/ 318b0453382SBill Fenner 319b0453382SBill Fenner case RC5: 320685295f4SBill Fenner #if defined(HAVE_LIBCRYPTO) && defined(HAVE_RC5_H) 321b0453382SBill Fenner { 322b0453382SBill Fenner RC5_32_KEY schedule; 323b0453382SBill Fenner 324b0453382SBill Fenner RC5_32_set_key(&schedule, strlen(secret), secret, 325b0453382SBill Fenner RC5_16_ROUNDS); 326b0453382SBill Fenner 327b0453382SBill Fenner p = ivoff + ivlen; 328b0453382SBill Fenner RC5_32_cbc_encrypt(p, p, (long)(ep - p), &schedule, ivoff, 329b0453382SBill Fenner RC5_DECRYPT); 330b0453382SBill Fenner advance = ivoff - (u_char *)esp + ivlen; 331b0453382SBill Fenner break; 332b0453382SBill Fenner } 333b0453382SBill Fenner #else 334b0453382SBill Fenner goto fail; 335685295f4SBill Fenner #endif /*HAVE_LIBCRYPTO*/ 336b0453382SBill Fenner 337b0453382SBill Fenner case CAST128: 338685295f4SBill Fenner #if defined(HAVE_LIBCRYPTO) && defined(HAVE_CAST_H) && !defined(HAVE_BUGGY_CAST128) 339b0453382SBill Fenner { 340b0453382SBill Fenner CAST_KEY schedule; 341b0453382SBill Fenner 342b0453382SBill Fenner CAST_set_key(&schedule, strlen(secret), secret); 343b0453382SBill Fenner 344b0453382SBill Fenner p = ivoff + ivlen; 345b0453382SBill Fenner CAST_cbc_encrypt(p, p, (long)(ep - p), &schedule, ivoff, 346b0453382SBill Fenner CAST_DECRYPT); 347b0453382SBill Fenner advance = ivoff - (u_char *)esp + ivlen; 348b0453382SBill Fenner break; 349b0453382SBill Fenner } 350b0453382SBill Fenner #else 351b0453382SBill Fenner goto fail; 352685295f4SBill Fenner #endif /*HAVE_LIBCRYPTO*/ 353b0453382SBill Fenner 354b0453382SBill Fenner case DES3CBC: 355685295f4SBill Fenner #if defined(HAVE_LIBCRYPTO) 356b0453382SBill Fenner { 357b0453382SBill Fenner des_key_schedule s1, s2, s3; 358b0453382SBill Fenner 359a90e161bSBill Fenner des_check_key = 1; 360a90e161bSBill Fenner des_set_odd_parity((void *)secret); 361a90e161bSBill Fenner des_set_odd_parity((void *)secret+8); 362a90e161bSBill Fenner des_set_odd_parity((void *)secret+16); 363a90e161bSBill Fenner if(des_set_key((void *)secret, s1) != 0) { 364a90e161bSBill Fenner printf("failed to schedule key 1\n"); 365a90e161bSBill Fenner } 366a90e161bSBill Fenner if(des_set_key((void *)(secret + 8), s2)!=0) { 367a90e161bSBill Fenner printf("failed to schedule key 2\n"); 368a90e161bSBill Fenner } 369a90e161bSBill Fenner if(des_set_key((void *)(secret + 16), s3)!=0) { 370a90e161bSBill Fenner printf("failed to schedule key 3\n"); 371a90e161bSBill Fenner } 372b0453382SBill Fenner 373b0453382SBill Fenner p = ivoff + ivlen; 374b0453382SBill Fenner des_ede3_cbc_encrypt((void *)p, (void *)p, 375a90e161bSBill Fenner (long)(ep - p), 376a90e161bSBill Fenner s1, s2, s3, 377a90e161bSBill Fenner (void *)ivoff, DES_DECRYPT); 378b0453382SBill Fenner advance = ivoff - (u_char *)esp + ivlen; 379b0453382SBill Fenner break; 380b0453382SBill Fenner } 381b0453382SBill Fenner #else 382b0453382SBill Fenner goto fail; 383685295f4SBill Fenner #endif /*HAVE_LIBCRYPTO*/ 384b0453382SBill Fenner 385b0453382SBill Fenner case NONE: 386b0453382SBill Fenner default: 387a90e161bSBill Fenner advance = sizeof(struct esp) + espsecret_xform->replaysize; 388b0453382SBill Fenner break; 389b0453382SBill Fenner } 390b0453382SBill Fenner 391a90e161bSBill Fenner ep = ep - espsecret_xform->authlen; 392b0453382SBill Fenner /* sanity check for pad length */ 393b0453382SBill Fenner if (ep - bp < *(ep - 2)) 394b0453382SBill Fenner goto fail; 395b0453382SBill Fenner 396a90e161bSBill Fenner if (padlen) 397a90e161bSBill Fenner *padlen = *(ep - 2) + 2; 398a90e161bSBill Fenner 399b0453382SBill Fenner if (nhdr) 400b0453382SBill Fenner *nhdr = *(ep - 1); 401b0453382SBill Fenner 402b0453382SBill Fenner printf(": "); 403b0453382SBill Fenner return advance; 404b0453382SBill Fenner 405b0453382SBill Fenner fail: 406b0453382SBill Fenner if (nhdr) 407b0453382SBill Fenner *nhdr = -1; 408b0453382SBill Fenner return 65536; 409b0453382SBill Fenner } 410