]> The Tcpdump Group git mirrors - tcpdump/commitdiff
print-esp understands various algorithms and RFC2406 encoding. tcpdump-3.7.1
authormcr <mcr>
Mon, 21 Jan 2002 11:39:58 +0000 (11:39 +0000)
committermcr <mcr>
Mon, 21 Jan 2002 11:39:58 +0000 (11:39 +0000)
interface.h
print-esp.c

index 6ad68a8d8fd591d4a3fbb6e3ea8a01e3913a4a18..c290d57683f67ace37a4c378a0e3719b3d348765 100644 (file)
@@ -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 */
index c06543f526925e490f74155386e3afe2ccd2fd19..6e76f1b26bac795e7daf98c5d72a6494d45365c3 100644 (file)
@@ -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;