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[] = 269afd0c29SBill Fenner "@(#) $Header: /tcpdump/master/tcpdump/print-esp.c,v 1.20.4.2 2002/02/22 09:26:27 guy 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> 389afd0c29SBill Fenner #include <stdlib.h> 39b0453382SBill Fenner 40b0453382SBill Fenner #include <netinet/in.h> 41b0453382SBill Fenner 42685295f4SBill Fenner #ifdef HAVE_LIBCRYPTO 43a90e161bSBill Fenner #include <openssl/des.h> 44a90e161bSBill Fenner #include <openssl/blowfish.h> 45b0453382SBill Fenner #ifdef HAVE_RC5_H 46a90e161bSBill Fenner #include <openssl/rc5.h> 47b0453382SBill Fenner #endif 48b0453382SBill Fenner #ifdef HAVE_CAST_H 49a90e161bSBill Fenner #include <openssl/cast.h> 50b0453382SBill Fenner #endif 51b0453382SBill Fenner #endif 52b0453382SBill Fenner 53b0453382SBill Fenner #include <stdio.h> 54b0453382SBill Fenner 55685295f4SBill Fenner #include "ip.h" 56685295f4SBill Fenner #include "esp.h" 57b0453382SBill Fenner #ifdef INET6 58685295f4SBill Fenner #include "ip6.h" 59b0453382SBill Fenner #endif 60b0453382SBill Fenner 61a90e161bSBill Fenner #define AVOID_CHURN 1 62b0453382SBill Fenner #include "interface.h" 63b0453382SBill Fenner #include "addrtoname.h" 64b0453382SBill Fenner 65a90e161bSBill Fenner static struct esp_algorithm *espsecret_xform=NULL; /* cache of decoded alg. */ 66a90e161bSBill Fenner static char *espsecret_key=NULL; 67a90e161bSBill Fenner 68a90e161bSBill Fenner 69a90e161bSBill Fenner enum cipher { NONE, 70a90e161bSBill Fenner DESCBC, 71a90e161bSBill Fenner BLOWFISH, 72a90e161bSBill Fenner RC5, 73a90e161bSBill Fenner CAST128, 74a90e161bSBill Fenner DES3CBC}; 75a90e161bSBill Fenner 76a90e161bSBill Fenner 77a90e161bSBill Fenner 78a90e161bSBill Fenner struct esp_algorithm { 79a90e161bSBill Fenner char *name; 80a90e161bSBill Fenner enum cipher algo; 81a90e161bSBill Fenner int ivlen; 82a90e161bSBill Fenner int authlen; 83a90e161bSBill Fenner int replaysize; 84a90e161bSBill Fenner }; 85a90e161bSBill Fenner 86a90e161bSBill Fenner struct esp_algorithm esp_xforms[]={ 87a90e161bSBill Fenner {"none", NONE, 0, 0, 0}, 88a90e161bSBill Fenner {"des-cbc", DESCBC, 8, 0, 0}, 89a90e161bSBill Fenner {"des-cbc-hmac96", DESCBC, 8, 12, 4}, 90a90e161bSBill Fenner {"blowfish-cbc", BLOWFISH,8, 0, 0}, 91a90e161bSBill Fenner {"blowfish-cbc-hmac96", BLOWFISH,8, 12, 4}, 92a90e161bSBill Fenner {"rc5-cbc", RC5, 8, 0, 0}, 93a90e161bSBill Fenner {"rc5-cbc-hmac96", RC5, 8, 12, 4}, 94a90e161bSBill Fenner {"cast128-cbc", CAST128, 8, 0, 0}, 95a90e161bSBill Fenner {"cast128-cbc-hmac96", CAST128, 8, 12, 4}, 96a90e161bSBill Fenner {"3des-cbc-hmac96", DES3CBC, 8, 12, 4}, 97a90e161bSBill Fenner }; 98a90e161bSBill Fenner 99a90e161bSBill Fenner static int hexdigit(char hex) 100a90e161bSBill Fenner { 101a90e161bSBill Fenner if(hex >= '0' && hex <= '9') { 102a90e161bSBill Fenner return (hex - '0'); 103a90e161bSBill Fenner } else if(hex >= 'A' && hex <= 'F') { 104a90e161bSBill Fenner return (hex - 'A' + 10); 105a90e161bSBill Fenner } else if(hex >= 'a' && hex <= 'f') { 106a90e161bSBill Fenner return (hex - 'a' + 10); 107a90e161bSBill Fenner } else { 108a90e161bSBill Fenner printf("invalid hex digit %c in espsecret\n", hex); 109a90e161bSBill Fenner return 0; 110a90e161bSBill Fenner } 111a90e161bSBill Fenner } 112a90e161bSBill Fenner 113a90e161bSBill Fenner static int hex2byte(char *hexstring) 114a90e161bSBill Fenner { 115a90e161bSBill Fenner int byte; 116a90e161bSBill Fenner 117a90e161bSBill Fenner byte = (hexdigit(hexstring[0]) << 4) + 118a90e161bSBill Fenner hexdigit(hexstring[1]); 119a90e161bSBill Fenner return byte; 120a90e161bSBill Fenner } 121a90e161bSBill Fenner 122a90e161bSBill Fenner 1239afd0c29SBill Fenner static void esp_print_decodesecret(void) 124a90e161bSBill Fenner { 125a90e161bSBill Fenner char *colon; 126a90e161bSBill Fenner int len, i; 127a90e161bSBill Fenner struct esp_algorithm *xf; 128a90e161bSBill Fenner 129a90e161bSBill Fenner if(espsecret == NULL) { 130a90e161bSBill Fenner /* set to NONE transform */ 131a90e161bSBill Fenner espsecret_xform = esp_xforms; 132a90e161bSBill Fenner return; 133a90e161bSBill Fenner } 134a90e161bSBill Fenner 135a90e161bSBill Fenner if(espsecret_key != NULL) { 136a90e161bSBill Fenner return; 137a90e161bSBill Fenner } 138a90e161bSBill Fenner 139a90e161bSBill Fenner colon = strchr(espsecret, ':'); 140a90e161bSBill Fenner if(colon == NULL) { 141a90e161bSBill Fenner printf("failed to decode espsecret: %s\n", 142a90e161bSBill Fenner espsecret); 143a90e161bSBill Fenner /* set to NONE transform */ 144a90e161bSBill Fenner espsecret_xform = esp_xforms; 145a90e161bSBill Fenner } 146a90e161bSBill Fenner 147a90e161bSBill Fenner len = colon - espsecret; 148a90e161bSBill Fenner xf = esp_xforms; 149a90e161bSBill Fenner while(xf->name && strncasecmp(espsecret, xf->name, len)!=0) { 150a90e161bSBill Fenner xf++; 151a90e161bSBill Fenner } 152a90e161bSBill Fenner if(xf->name == NULL) { 153a90e161bSBill Fenner printf("failed to find cipher algo %s\n", 154a90e161bSBill Fenner espsecret); 155a90e161bSBill Fenner espsecret_xform = esp_xforms; 156a90e161bSBill Fenner return; 157a90e161bSBill Fenner } 158a90e161bSBill Fenner espsecret_xform = xf; 159a90e161bSBill Fenner 160a90e161bSBill Fenner colon++; 161a90e161bSBill Fenner if(colon[0]=='0' && colon[1]=='x') { 162a90e161bSBill Fenner /* decode some hex! */ 163a90e161bSBill Fenner colon+=2; 164a90e161bSBill Fenner len = strlen(colon) / 2; 165a90e161bSBill Fenner espsecret_key = (char *)malloc(len); 166a90e161bSBill Fenner if(espsecret_key == NULL) { 167a90e161bSBill Fenner fprintf(stderr, "%s: ran out of memory (%d) to allocate secret key\n", 168a90e161bSBill Fenner program_name, len); 169a90e161bSBill Fenner exit(2); 170a90e161bSBill Fenner } 171a90e161bSBill Fenner i = 0; 172a90e161bSBill Fenner while(colon[0] != '\0' && colon[1]!='\0') { 173a90e161bSBill Fenner espsecret_key[i]=hex2byte(colon); 174a90e161bSBill Fenner colon+=2; 175a90e161bSBill Fenner i++; 176a90e161bSBill Fenner } 177a90e161bSBill Fenner } else { 178a90e161bSBill Fenner espsecret_key = colon; 179a90e161bSBill Fenner } 180a90e161bSBill Fenner } 181a90e161bSBill Fenner 182b0453382SBill Fenner int 183a90e161bSBill Fenner esp_print(register const u_char *bp, register const u_char *bp2, 184a90e161bSBill Fenner int *nhdr, int *padlen) 185b0453382SBill Fenner { 186b0453382SBill Fenner register const struct esp *esp; 187b0453382SBill Fenner register const u_char *ep; 188b0453382SBill Fenner u_int32_t spi; 189b0453382SBill Fenner struct ip *ip = NULL; 190b0453382SBill Fenner #ifdef INET6 191b0453382SBill Fenner struct ip6_hdr *ip6 = NULL; 192b0453382SBill Fenner #endif 193b0453382SBill Fenner int advance; 194b0453382SBill Fenner int len; 195a90e161bSBill Fenner char *secret; 196b0453382SBill Fenner int ivlen = 0; 197b0453382SBill Fenner u_char *ivoff; 198a90e161bSBill Fenner u_char *p; 199b0453382SBill Fenner 200b0453382SBill Fenner esp = (struct esp *)bp; 201b0453382SBill Fenner spi = (u_int32_t)ntohl(esp->esp_spi); 202a90e161bSBill Fenner secret = NULL; 203a90e161bSBill Fenner 204a90e161bSBill Fenner #if 0 205a90e161bSBill Fenner /* keep secret out of a register */ 206a90e161bSBill Fenner p = (u_char *)&secret; 207a90e161bSBill Fenner #endif 208b0453382SBill Fenner 209685295f4SBill Fenner /* 'ep' points to the end of available data. */ 210b0453382SBill Fenner ep = snapend; 211b0453382SBill Fenner 212b0453382SBill Fenner if ((u_char *)(esp + 1) >= ep - sizeof(struct esp)) { 213b0453382SBill Fenner fputs("[|ESP]", stdout); 214b0453382SBill Fenner goto fail; 215b0453382SBill Fenner } 216685295f4SBill Fenner printf("ESP(spi=0x%08x", spi); 217b0453382SBill Fenner printf(",seq=0x%x", (u_int32_t)ntohl(*(u_int32_t *)(esp + 1))); 218b0453382SBill Fenner printf(")"); 219b0453382SBill Fenner 220b0453382SBill Fenner /* if we don't have decryption key, we can't decrypt this packet. */ 221b0453382SBill Fenner if (!espsecret) 222b0453382SBill Fenner goto fail; 223b0453382SBill Fenner 224a90e161bSBill Fenner if(!espsecret_xform) { 225a90e161bSBill Fenner esp_print_decodesecret(); 226a90e161bSBill Fenner } 227a90e161bSBill Fenner if(espsecret_xform->algo == NONE) { 228a90e161bSBill Fenner goto fail; 229b0453382SBill Fenner } 230b0453382SBill Fenner 231b0453382SBill Fenner ip = (struct ip *)bp2; 232685295f4SBill Fenner switch (IP_V(ip)) { 233b0453382SBill Fenner #ifdef INET6 234b0453382SBill Fenner case 6: 235b0453382SBill Fenner ip6 = (struct ip6_hdr *)bp2; 236b0453382SBill Fenner ip = NULL; 237b0453382SBill Fenner /* we do not attempt to decrypt jumbograms */ 238b0453382SBill Fenner if (!ntohs(ip6->ip6_plen)) 239b0453382SBill Fenner goto fail; 240b0453382SBill Fenner /* if we can't get nexthdr, we do not need to decrypt it */ 241b0453382SBill Fenner len = sizeof(struct ip6_hdr) + ntohs(ip6->ip6_plen); 242b0453382SBill Fenner break; 243b0453382SBill Fenner #endif /*INET6*/ 244b0453382SBill Fenner case 4: 245a90e161bSBill Fenner /* nexthdr & padding are in the last fragment */ 246a90e161bSBill Fenner if (ntohs(ip->ip_off) & IP_MF) 247a90e161bSBill Fenner goto fail; 248b0453382SBill Fenner #ifdef INET6 249b0453382SBill Fenner ip6 = NULL; 250b0453382SBill Fenner #endif 251b0453382SBill Fenner len = ntohs(ip->ip_len); 252b0453382SBill Fenner break; 253b0453382SBill Fenner default: 254b0453382SBill Fenner goto fail; 255b0453382SBill Fenner } 256b0453382SBill Fenner 257b0453382SBill Fenner /* if we can't get nexthdr, we do not need to decrypt it */ 258b0453382SBill Fenner if (ep - bp2 < len) 259b0453382SBill Fenner goto fail; 260b0453382SBill Fenner 261a90e161bSBill Fenner ivoff = (u_char *)(esp + 1) + espsecret_xform->replaysize; 262a90e161bSBill Fenner ivlen = espsecret_xform->ivlen; 263a90e161bSBill Fenner secret = espsecret_key; 264b0453382SBill Fenner 265a90e161bSBill Fenner switch (espsecret_xform->algo) { 266b0453382SBill Fenner case DESCBC: 267685295f4SBill Fenner #ifdef HAVE_LIBCRYPTO 268b0453382SBill Fenner { 269b0453382SBill Fenner u_char iv[8]; 270b0453382SBill Fenner des_key_schedule schedule; 271b0453382SBill Fenner 272b0453382SBill Fenner switch (ivlen) { 273b0453382SBill Fenner case 4: 274b0453382SBill Fenner memcpy(iv, ivoff, 4); 275b0453382SBill Fenner memcpy(&iv[4], ivoff, 4); 276b0453382SBill Fenner p = &iv[4]; 277b0453382SBill Fenner *p++ ^= 0xff; 278b0453382SBill Fenner *p++ ^= 0xff; 279b0453382SBill Fenner *p++ ^= 0xff; 280b0453382SBill Fenner *p++ ^= 0xff; 281b0453382SBill Fenner break; 282b0453382SBill Fenner case 8: 283b0453382SBill Fenner memcpy(iv, ivoff, 8); 284b0453382SBill Fenner break; 285b0453382SBill Fenner default: 286b0453382SBill Fenner goto fail; 287b0453382SBill Fenner } 288b0453382SBill Fenner 289b0453382SBill Fenner des_check_key = 0; 290b0453382SBill Fenner des_set_key((void *)secret, schedule); 291b0453382SBill Fenner 292b0453382SBill Fenner p = ivoff + ivlen; 293b0453382SBill Fenner des_cbc_encrypt((void *)p, (void *)p, 294b0453382SBill Fenner (long)(ep - p), schedule, (void *)iv, 295b0453382SBill Fenner DES_DECRYPT); 296b0453382SBill Fenner advance = ivoff - (u_char *)esp + ivlen; 297b0453382SBill Fenner break; 298b0453382SBill Fenner } 299b0453382SBill Fenner #else 300b0453382SBill Fenner goto fail; 301685295f4SBill Fenner #endif /*HAVE_LIBCRYPTO*/ 302b0453382SBill Fenner 303b0453382SBill Fenner case BLOWFISH: 304685295f4SBill Fenner #ifdef HAVE_LIBCRYPTO 305b0453382SBill Fenner { 306b0453382SBill Fenner BF_KEY schedule; 307b0453382SBill Fenner 308b0453382SBill Fenner BF_set_key(&schedule, strlen(secret), secret); 309b0453382SBill Fenner 310b0453382SBill Fenner p = ivoff + ivlen; 311b0453382SBill Fenner BF_cbc_encrypt(p, p, (long)(ep - p), &schedule, ivoff, 312b0453382SBill Fenner BF_DECRYPT); 313b0453382SBill Fenner advance = ivoff - (u_char *)esp + ivlen; 314b0453382SBill Fenner break; 315b0453382SBill Fenner } 316b0453382SBill Fenner #else 317b0453382SBill Fenner goto fail; 318685295f4SBill Fenner #endif /*HAVE_LIBCRYPTO*/ 319b0453382SBill Fenner 320b0453382SBill Fenner case RC5: 321685295f4SBill Fenner #if defined(HAVE_LIBCRYPTO) && defined(HAVE_RC5_H) 322b0453382SBill Fenner { 323b0453382SBill Fenner RC5_32_KEY schedule; 324b0453382SBill Fenner 325b0453382SBill Fenner RC5_32_set_key(&schedule, strlen(secret), secret, 326b0453382SBill Fenner RC5_16_ROUNDS); 327b0453382SBill Fenner 328b0453382SBill Fenner p = ivoff + ivlen; 329b0453382SBill Fenner RC5_32_cbc_encrypt(p, p, (long)(ep - p), &schedule, ivoff, 330b0453382SBill Fenner RC5_DECRYPT); 331b0453382SBill Fenner advance = ivoff - (u_char *)esp + ivlen; 332b0453382SBill Fenner break; 333b0453382SBill Fenner } 334b0453382SBill Fenner #else 335b0453382SBill Fenner goto fail; 336685295f4SBill Fenner #endif /*HAVE_LIBCRYPTO*/ 337b0453382SBill Fenner 338b0453382SBill Fenner case CAST128: 339685295f4SBill Fenner #if defined(HAVE_LIBCRYPTO) && defined(HAVE_CAST_H) && !defined(HAVE_BUGGY_CAST128) 340b0453382SBill Fenner { 341b0453382SBill Fenner CAST_KEY schedule; 342b0453382SBill Fenner 343b0453382SBill Fenner CAST_set_key(&schedule, strlen(secret), secret); 344b0453382SBill Fenner 345b0453382SBill Fenner p = ivoff + ivlen; 346b0453382SBill Fenner CAST_cbc_encrypt(p, p, (long)(ep - p), &schedule, ivoff, 347b0453382SBill Fenner CAST_DECRYPT); 348b0453382SBill Fenner advance = ivoff - (u_char *)esp + ivlen; 349b0453382SBill Fenner break; 350b0453382SBill Fenner } 351b0453382SBill Fenner #else 352b0453382SBill Fenner goto fail; 353685295f4SBill Fenner #endif /*HAVE_LIBCRYPTO*/ 354b0453382SBill Fenner 355b0453382SBill Fenner case DES3CBC: 356685295f4SBill Fenner #if defined(HAVE_LIBCRYPTO) 357b0453382SBill Fenner { 358b0453382SBill Fenner des_key_schedule s1, s2, s3; 359b0453382SBill Fenner 360a90e161bSBill Fenner des_check_key = 1; 361a90e161bSBill Fenner des_set_odd_parity((void *)secret); 3629afd0c29SBill Fenner des_set_odd_parity((void *)(secret + 8)); 3639afd0c29SBill Fenner des_set_odd_parity((void *)(secret + 16)); 364a90e161bSBill Fenner if(des_set_key((void *)secret, s1) != 0) { 365a90e161bSBill Fenner printf("failed to schedule key 1\n"); 366a90e161bSBill Fenner } 367a90e161bSBill Fenner if(des_set_key((void *)(secret + 8), s2)!=0) { 368a90e161bSBill Fenner printf("failed to schedule key 2\n"); 369a90e161bSBill Fenner } 370a90e161bSBill Fenner if(des_set_key((void *)(secret + 16), s3)!=0) { 371a90e161bSBill Fenner printf("failed to schedule key 3\n"); 372a90e161bSBill Fenner } 373b0453382SBill Fenner 374b0453382SBill Fenner p = ivoff + ivlen; 375b0453382SBill Fenner des_ede3_cbc_encrypt((void *)p, (void *)p, 376a90e161bSBill Fenner (long)(ep - p), 377a90e161bSBill Fenner s1, s2, s3, 378a90e161bSBill Fenner (void *)ivoff, DES_DECRYPT); 379b0453382SBill Fenner advance = ivoff - (u_char *)esp + ivlen; 380b0453382SBill Fenner break; 381b0453382SBill Fenner } 382b0453382SBill Fenner #else 383b0453382SBill Fenner goto fail; 384685295f4SBill Fenner #endif /*HAVE_LIBCRYPTO*/ 385b0453382SBill Fenner 386b0453382SBill Fenner case NONE: 387b0453382SBill Fenner default: 388a90e161bSBill Fenner advance = sizeof(struct esp) + espsecret_xform->replaysize; 389b0453382SBill Fenner break; 390b0453382SBill Fenner } 391b0453382SBill Fenner 392a90e161bSBill Fenner ep = ep - espsecret_xform->authlen; 393b0453382SBill Fenner /* sanity check for pad length */ 394b0453382SBill Fenner if (ep - bp < *(ep - 2)) 395b0453382SBill Fenner goto fail; 396b0453382SBill Fenner 397a90e161bSBill Fenner if (padlen) 398a90e161bSBill Fenner *padlen = *(ep - 2) + 2; 399a90e161bSBill Fenner 400b0453382SBill Fenner if (nhdr) 401b0453382SBill Fenner *nhdr = *(ep - 1); 402b0453382SBill Fenner 403b0453382SBill Fenner printf(": "); 404b0453382SBill Fenner return advance; 405b0453382SBill Fenner 406b0453382SBill Fenner fail: 407b0453382SBill Fenner if (nhdr) 408b0453382SBill Fenner *nhdr = -1; 409b0453382SBill Fenner return 65536; 410b0453382SBill Fenner } 411