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