From: mcr Date: Mon, 21 Jan 2002 11:39:58 +0000 (+0000) Subject: print-esp understands various algorithms and RFC2406 encoding. X-Git-Tag: tcpdump-3.7.1 X-Git-Url: https://git.tcpdump.org/tcpdump/commitdiff_plain/19fb01819f284061bd4390e846410b95b4a27464 print-esp understands various algorithms and RFC2406 encoding. --- diff --git a/interface.h b/interface.h index 6ad68a8d..c290d576 100644 --- a/interface.h +++ b/interface.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1999, 2000 + * Copyright (c) 1988-2002 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -18,7 +18,7 @@ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * @(#) $Header: /tcpdump/master/tcpdump/interface.h,v 1.177 2001-12-10 08:21:23 guy Exp $ (LBL) + * @(#) $Header: /tcpdump/master/tcpdump/interface.h,v 1.178 2002-01-21 11:39:58 mcr Exp $ (LBL) */ #ifndef tcpdump_interface_h @@ -81,6 +81,8 @@ extern int xflag; /* print packet in hex */ extern int Xflag; /* print packet in hex/ascii */ extern char *espsecret; +extern struct esp_algorithm *espsecret_xform; /* cache of decoded alg. */ +extern char *espsecret_key; extern int packettype; /* as specified by -T */ #define PT_VAT 1 /* Visual Audio Tool */ diff --git a/print-esp.c b/print-esp.c index c06543f5..6e76f1b2 100644 --- a/print-esp.c +++ b/print-esp.c @@ -23,7 +23,7 @@ #ifndef lint static const char rcsid[] = - "@(#) $Header: /tcpdump/master/tcpdump/print-esp.c,v 1.19 2001-08-20 17:52:38 fenner Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/tcpdump/print-esp.c,v 1.20 2002-01-21 11:39:59 mcr Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -57,28 +57,153 @@ static const char rcsid[] = #include "ip6.h" #endif +#define AVOID_CHURN 1 #include "interface.h" #include "addrtoname.h" +static struct esp_algorithm *espsecret_xform=NULL; /* cache of decoded alg. */ +static char *espsecret_key=NULL; + + +enum cipher { NONE, + DESCBC, + BLOWFISH, + RC5, + CAST128, + DES3CBC}; + + + +struct esp_algorithm { + char *name; + enum cipher algo; + int ivlen; + int authlen; + int replaysize; +}; + +struct esp_algorithm esp_xforms[]={ + {"none", NONE, 0, 0, 0}, + {"des-cbc", DESCBC, 8, 0, 0}, + {"des-cbc-hmac96", DESCBC, 8, 12, 4}, + {"blowfish-cbc", BLOWFISH,8, 0, 0}, + {"blowfish-cbc-hmac96", BLOWFISH,8, 12, 4}, + {"rc5-cbc", RC5, 8, 0, 0}, + {"rc5-cbc-hmac96", RC5, 8, 12, 4}, + {"cast128-cbc", CAST128, 8, 0, 0}, + {"cast128-cbc-hmac96", CAST128, 8, 12, 4}, + {"3des-cbc-hmac96", DES3CBC, 8, 12, 4}, +}; + +static int hexdigit(char hex) +{ + if(hex >= '0' && hex <= '9') { + return (hex - '0'); + } else if(hex >= 'A' && hex <= 'F') { + return (hex - 'A' + 10); + } else if(hex >= 'a' && hex <= 'f') { + return (hex - 'a' + 10); + } else { + printf("invalid hex digit %c in espsecret\n", hex); + return 0; + } +} + +static int hex2byte(char *hexstring) +{ + int byte; + + byte = (hexdigit(hexstring[0]) << 4) + + hexdigit(hexstring[1]); + return byte; +} + + +void esp_print_decodesecret() +{ + char *colon; + int len, i; + struct esp_algorithm *xf; + + if(espsecret == NULL) { + /* set to NONE transform */ + espsecret_xform = esp_xforms; + return; + } + + if(espsecret_key != NULL) { + return; + } + + colon = strchr(espsecret, ':'); + if(colon == NULL) { + printf("failed to decode espsecret: %s\n", + espsecret); + /* set to NONE transform */ + espsecret_xform = esp_xforms; + } + + len = colon - espsecret; + xf = esp_xforms; + while(xf->name && strncasecmp(espsecret, xf->name, len)!=0) { + xf++; + } + if(xf->name == NULL) { + printf("failed to find cipher algo %s\n", + espsecret); + espsecret_xform = esp_xforms; + return; + } + espsecret_xform = xf; + + colon++; + if(colon[0]=='0' && colon[1]=='x') { + /* decode some hex! */ + colon+=2; + len = strlen(colon) / 2; + espsecret_key = (char *)malloc(len); + if(espsecret_key == NULL) { + fprintf(stderr, "%s: ran out of memory (%d) to allocate secret key\n", + program_name, len); + exit(2); + } + i = 0; + while(colon[0] != '\0' && colon[1]!='\0') { + espsecret_key[i]=hex2byte(colon); + colon+=2; + i++; + } + } else { + espsecret_key = colon; + } +} + int -esp_print(register const u_char *bp, register const u_char *bp2, int *nhdr, int *padlen) +esp_print(register const u_char *bp, register const u_char *bp2, + int *nhdr, int *padlen) { register const struct esp *esp; register const u_char *ep; u_int32_t spi; - enum { NONE, DESCBC, BLOWFISH, RC5, CAST128, DES3CBC } algo = NONE; struct ip *ip = NULL; #ifdef INET6 struct ip6_hdr *ip6 = NULL; #endif int advance; int len; - char *secret = NULL; + char *secret; int ivlen = 0; u_char *ivoff; - + u_char *p; + esp = (struct esp *)bp; spi = (u_int32_t)ntohl(esp->esp_spi); + secret = NULL; + +#if 0 + /* keep secret out of a register */ + p = (u_char *)&secret; +#endif /* 'ep' points to the end of available data. */ ep = snapend; @@ -95,40 +220,11 @@ esp_print(register const u_char *bp, register const u_char *bp2, int *nhdr, int if (!espsecret) goto fail; - if (strncmp(espsecret, "des-cbc:", 8) == 0 - && strlen(espsecret + 8) == 8) { - algo = DESCBC; - ivlen = 8; - secret = espsecret + 8; - } else if (strncmp(espsecret, "blowfish-cbc:", 13) == 0) { - algo = BLOWFISH; - ivlen = 8; - secret = espsecret + 13; - } else if (strncmp(espsecret, "rc5-cbc:", 8) == 0) { - algo = RC5; - ivlen = 8; - secret = espsecret + 8; - } else if (strncmp(espsecret, "cast128-cbc:", 12) == 0) { - algo = CAST128; - ivlen = 8; - secret = espsecret + 12; - } else if (strncmp(espsecret, "3des-cbc:", 9) == 0 - && strlen(espsecret + 9) == 24) { - algo = DES3CBC; - ivlen = 8; - secret = espsecret + 9; - } else if (strncmp(espsecret, "none:", 5) == 0) { - algo = NONE; - ivlen = 0; - secret = espsecret + 5; - } else if (strlen(espsecret) == 8) { - algo = DESCBC; - ivlen = 8; - secret = espsecret; - } else { - algo = NONE; - ivlen = 0; - secret = espsecret; + if(!espsecret_xform) { + esp_print_decodesecret(); + } + if(espsecret_xform->algo == NONE) { + goto fail; } ip = (struct ip *)bp2; @@ -161,18 +257,16 @@ esp_print(register const u_char *bp, register const u_char *bp2, int *nhdr, int if (ep - bp2 < len) goto fail; - if (Rflag) - ivoff = (u_char *)(esp + 1) + sizeof(u_int32_t); - else - ivoff = (u_char *)(esp + 1); + ivoff = (u_char *)(esp + 1) + espsecret_xform->replaysize; + ivlen = espsecret_xform->ivlen; + secret = espsecret_key; - switch (algo) { + switch (espsecret_xform->algo) { case DESCBC: #ifdef HAVE_LIBCRYPTO { u_char iv[8]; des_key_schedule schedule; - u_char *p; switch (ivlen) { case 4: @@ -209,7 +303,6 @@ esp_print(register const u_char *bp, register const u_char *bp2, int *nhdr, int #ifdef HAVE_LIBCRYPTO { BF_KEY schedule; - u_char *p; BF_set_key(&schedule, strlen(secret), secret); @@ -227,7 +320,6 @@ esp_print(register const u_char *bp, register const u_char *bp2, int *nhdr, int #if defined(HAVE_LIBCRYPTO) && defined(HAVE_RC5_H) { RC5_32_KEY schedule; - u_char *p; RC5_32_set_key(&schedule, strlen(secret), secret, RC5_16_ROUNDS); @@ -246,7 +338,6 @@ esp_print(register const u_char *bp, register const u_char *bp2, int *nhdr, int #if defined(HAVE_LIBCRYPTO) && defined(HAVE_CAST_H) && !defined(HAVE_BUGGY_CAST128) { CAST_KEY schedule; - u_char *p; CAST_set_key(&schedule, strlen(secret), secret); @@ -264,16 +355,26 @@ esp_print(register const u_char *bp, register const u_char *bp2, int *nhdr, int #if defined(HAVE_LIBCRYPTO) { des_key_schedule s1, s2, s3; - u_char *p; - des_check_key = 0; - des_set_key((void *)secret, s1); - des_set_key((void *)(secret + 8), s2); - des_set_key((void *)(secret + 16), s3); + des_check_key = 1; + des_set_odd_parity((void *)secret); + des_set_odd_parity((void *)secret+8); + des_set_odd_parity((void *)secret+16); + if(des_set_key((void *)secret, s1) != 0) { + printf("failed to schedule key 1\n"); + } + if(des_set_key((void *)(secret + 8), s2)!=0) { + printf("failed to schedule key 2\n"); + } + if(des_set_key((void *)(secret + 16), s3)!=0) { + printf("failed to schedule key 3\n"); + } p = ivoff + ivlen; des_ede3_cbc_encrypt((void *)p, (void *)p, - (long)(ep - p), s1, s2, s3, (void *)ivoff, DES_DECRYPT); + (long)(ep - p), + s1, s2, s3, + (void *)ivoff, DES_DECRYPT); advance = ivoff - (u_char *)esp + ivlen; break; } @@ -283,13 +384,11 @@ esp_print(register const u_char *bp, register const u_char *bp2, int *nhdr, int case NONE: default: - if (Rflag) - advance = sizeof(struct esp) + sizeof(u_int32_t); - else - advance = sizeof(struct esp); + advance = sizeof(struct esp) + espsecret_xform->replaysize; break; } + ep = ep - espsecret_xform->authlen; /* sanity check for pad length */ if (ep - bp < *(ep - 2)) goto fail;