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