]> The Tcpdump Group git mirrors - tcpdump/blobdiff - print-esp.c
Include the CFLAGS setting when configure was run in the compiler flags.
[tcpdump] / print-esp.c
index 0166a85a497d5e0538d3663e07fd87a254a77ee5..ade654a33709454634ab44335aad1635d5591d4f 100644 (file)
@@ -22,8 +22,8 @@
  */
 
 #ifndef lint
-static const char rcsid[] =
-    "@(#) $Header: /tcpdump/master/tcpdump/print-esp.c,v 1.40 2003-07-17 11:01:06 itojun Exp $ (LBL)";
+static const char rcsid[] _U_ =
+    "@(#) $Header: /tcpdump/master/tcpdump/print-esp.c,v 1.58 2007-12-07 00:03:07 mcr Exp $ (LBL)";
 #endif
 
 #ifdef HAVE_CONFIG_H
@@ -37,13 +37,8 @@ static const char rcsid[] =
 #include <stdlib.h>
 
 #ifdef HAVE_LIBCRYPTO
-#include <openssl/des.h>
-#include <openssl/blowfish.h>
-#ifdef HAVE_OPENSSL_RC5_H
-#include <openssl/rc5.h>
-#endif
-#ifdef HAVE_OPENSSL_CAST_H
-#include <openssl/cast.h>
+#ifdef HAVE_OPENSSL_EVP_H
+#include <openssl/evp.h>
 #endif
 #endif
 
@@ -55,42 +50,10 @@ static const char rcsid[] =
 #include "ip6.h"
 #endif
 
-#if defined(__MINGW32__) || defined(__WATCOMC__)
-extern char *strsep (char **stringp, const char *delim); /* Missing/strsep.c */
-#endif
-
-#include "interface.h"
+#include "netdissect.h"
 #include "addrtoname.h"
 #include "extract.h"
 
-enum cipher { NONE, DESCBC, BLOWFISH, RC5, CAST128, DES3CBC};
-
-struct esp_algorithm {
-       const char      *name;
-       enum cipher     algo;
-       int             ivlen;
-       int             authlen;
-       int             replaysize;     /* number of bytes, in excess of 4,
-                                          may be negative */
-};
-
-struct esp_algorithm esp_xforms[]={
-       {"none",                  NONE,    0,  0, 0},
-       {"des-cbc",               DESCBC,  8,  0, 0},
-       {"des-cbc-hmac96",        DESCBC,  8, 12, 0},
-       {"blowfish-cbc",          BLOWFISH,8,  0, 0},
-       {"blowfish-cbc-hmac96",   BLOWFISH,8, 12, 0},
-       {"rc5-cbc",               RC5,     8,  0, 0},
-       {"rc5-cbc-hmac96",        RC5,     8, 12, 0},
-       {"cast128-cbc",           CAST128, 8,  0, 0},
-       {"cast128-cbc-hmac96",    CAST128, 8, 12, 0},
-       {"3des-cbc-hmac96",       DES3CBC, 8, 12, 0},
-       {NULL,                    NONE,    0,  0, 0}
-};
-
-struct esp_algorithm *null_xf =
-  &esp_xforms[sizeof(esp_xforms)/sizeof(esp_xforms[0]) - 1];
-
 #ifndef HAVE_SOCKADDR_STORAGE
 #ifdef INET6
 struct sockaddr_storage {
@@ -104,19 +67,78 @@ struct sockaddr_storage {
 #endif
 #endif /* HAVE_SOCKADDR_STORAGE */
 
+#ifdef HAVE_LIBCRYPTO
 struct sa_list {
        struct sa_list  *next;
        struct sockaddr_storage daddr;
-       u_int32_t       spi;
-       struct esp_algorithm *xform;
-       char            secret[256];  /* is that big enough for all secrets? */
+       u_int32_t       spi;          /* if == 0, then IKEv2 */
+       int             initiator;
+       u_char          spii[8];      /* for IKEv2 */
+       u_char          spir[8];
+       const EVP_CIPHER *evp;
+       int             ivlen;
+       int             authlen;
+       u_char          authsecret[256];
+       int             authsecret_len;
+       u_char          secret[256];  /* is that big enough for all secrets? */
        int             secretlen;
 };
 
-static struct sa_list *sa_list_head = NULL;
-static struct sa_list *sa_default = NULL;
+/*
+ * this will adjust ndo_packetp and ndo_snapend to new buffer!
+ */
+int esp_print_decrypt_buffer_by_ikev2(netdissect_options *ndo,
+                                     int initiator,
+                                     u_char spii[8], u_char spir[8],
+                                     u_char *buf, u_char *end)
+{
+       struct sa_list *sa;
+       u_char *iv;
+       int len;
+       EVP_CIPHER_CTX ctx;
+
+       /* initiator arg is any non-zero value */
+       if(initiator) initiator=1;
+                                      
+       /* see if we can find the SA, and if so, decode it */
+       for (sa = ndo->ndo_sa_list_head; sa != NULL; sa = sa->next) {
+               if (sa->spi == 0
+                   && initiator == sa->initiator
+                   && memcmp(spii, sa->spii, 8) == 0
+                   && memcmp(spir, sa->spir, 8) == 0)
+                       break;
+       }
+
+       if(sa == NULL) return 0;
+       if(sa->evp == NULL) return 0;
+
+       /*
+        * remove authenticator, and see if we still have something to
+        * work with
+        */
+       end = end - sa->authlen;
+       iv  = buf;
+       buf = buf + sa->ivlen;
+       len = end-buf;
+
+       if(end <= buf) return 0;
+
+       memset(&ctx, 0, sizeof(ctx));
+       if (EVP_CipherInit(&ctx, sa->evp, sa->secret, NULL, 0) < 0)
+               (*ndo->ndo_warning)(ndo, "espkey init failed");
+       EVP_CipherInit(&ctx, NULL, NULL, iv, 0);
+       EVP_Cipher(&ctx, buf, buf, len);
+       EVP_CIPHER_CTX_cleanup(&ctx);
+
+       ndo->ndo_packetp = buf;
+       ndo->ndo_snapend = end;
 
-static void esp_print_addsa(struct sa_list *sa, int sa_def)
+       return 1;
+       
+}
+
+static void esp_print_addsa(netdissect_options *ndo,
+                           struct sa_list *sa, int sa_def)
 {
        /* copy the "sa" */
 
@@ -124,19 +146,19 @@ static void esp_print_addsa(struct sa_list *sa, int sa_def)
 
        nsa = (struct sa_list *)malloc(sizeof(struct sa_list));
        if (nsa == NULL)
-               error("ran out of memory to allocate sa structure");
+               (*ndo->ndo_error)(ndo, "ran out of memory to allocate sa structure");
 
        *nsa = *sa;
 
        if (sa_def)
-               sa_default = nsa;
+               ndo->ndo_sa_default = nsa;
 
-       nsa->next = sa_list_head;
-       sa_list_head = nsa;
+       nsa->next = ndo->ndo_sa_list_head;
+       ndo->ndo_sa_list_head = nsa;
 }
 
-static int hexdigit(char hex)
+
+static u_int hexdigit(netdissect_options *ndo, char hex)
 {
        if (hex >= '0' && hex <= '9')
                return (hex - '0');
@@ -145,29 +167,208 @@ static int hexdigit(char hex)
        else if (hex >= 'a' && hex <= 'f')
                return (hex - 'a' + 10);
        else {
-               printf("invalid hex digit %c in espsecret\n", hex);
+               (*ndo->ndo_error)(ndo, "invalid hex digit %c in espsecret\n", hex);
                return 0;
        }
 }
 
-static int hex2byte(char *hexstring)
+static u_int hex2byte(netdissect_options *ndo, char *hexstring)
 {
-       int byte;
+       u_int byte;
 
-       byte = (hexdigit(hexstring[0]) << 4) + hexdigit(hexstring[1]);
+       byte = (hexdigit(ndo, hexstring[0]) << 4) + hexdigit(ndo, hexstring[1]);
        return byte;
 }
 
-/* 
+/*
+ * returns size of binary, 0 on failure.
+ */
+static
+int espprint_decode_hex(netdissect_options *ndo,
+                       u_char *binbuf, unsigned int binbuf_len,
+                       char *hex)
+{
+       unsigned int len;
+       int i;
+
+       len = strlen(hex) / 2;
+               
+       if (len > binbuf_len) {
+               (*ndo->ndo_warning)(ndo, "secret is too big: %d\n", len);
+               return 0;
+       }
+               
+       i = 0;
+       while (hex[0] != '\0' && hex[1]!='\0') {
+               binbuf[i] = hex2byte(ndo, hex);
+               hex += 2;
+               i++;
+       }
+
+       return i;
+}
+
+/*
  * decode the form:    SPINUM@IP <tab> ALGONAME:0xsecret
+ */
+
+static int
+espprint_decode_encalgo(netdissect_options *ndo,
+                       char *decode, struct sa_list *sa)
+{
+       int len;
+       size_t i;
+       const EVP_CIPHER *evp;
+       int authlen = 0;
+       char *colon, *p;
+       
+       colon = strchr(decode, ':');
+       if (colon == NULL) {
+               (*ndo->ndo_warning)(ndo, "failed to decode espsecret: %s\n", decode);
+               return 0;
+       }
+       *colon = '\0';
+       
+       len = colon - decode;
+       if (strlen(decode) > strlen("-hmac96") &&
+           !strcmp(decode + strlen(decode) - strlen("-hmac96"),
+                   "-hmac96")) {
+               p = strstr(decode, "-hmac96");
+               *p = '\0';
+               authlen = 12;
+       }
+       if (strlen(decode) > strlen("-cbc") &&
+           !strcmp(decode + strlen(decode) - strlen("-cbc"), "-cbc")) {
+               p = strstr(decode, "-cbc");
+               *p = '\0';
+       }
+       evp = EVP_get_cipherbyname(decode);
+
+       if (!evp) {
+               (*ndo->ndo_warning)(ndo, "failed to find cipher algo %s\n", decode);
+               sa->evp = NULL;
+               sa->authlen = 0;
+               sa->ivlen = 0;
+               return 0;
+       }
+       
+       sa->evp = evp;
+       sa->authlen = authlen;
+       sa->ivlen = EVP_CIPHER_iv_length(evp);
+       
+       colon++;
+       if (colon[0] == '0' && colon[1] == 'x') {
+               /* decode some hex! */
+
+               colon += 2;
+               sa->secretlen = espprint_decode_hex(ndo, sa->secret, sizeof(sa->secret), colon);
+               if(sa->secretlen == 0) return 0;
+       } else {
+               i = strlen(colon);
+               
+               if (i < sizeof(sa->secret)) {
+                       memcpy(sa->secret, colon, i);
+                       sa->secretlen = i;
+               } else {
+                       memcpy(sa->secret, colon, sizeof(sa->secret));
+                       sa->secretlen = sizeof(sa->secret);
+               }
+       }
+
+       return 1;
+}
+
+/*
+ * for the moment, ignore the auth algorith, just hard code the authenticator
+ * length. Need to research how openssl looks up HMAC stuff.
+ */
+static int
+espprint_decode_authalgo(netdissect_options *ndo,
+                        char *decode, struct sa_list *sa)
+{
+       char *colon;
+
+       colon = strchr(decode, ':');
+       if (colon == NULL) {
+               (*ndo->ndo_warning)(ndo, "failed to decode espsecret: %s\n", decode);
+               return 0;
+       }
+       *colon = '\0';
+       
+       if(strcasecmp(colon,"sha1") == 0 ||
+          strcasecmp(colon,"md5") == 0) {
+               sa->authlen = 12;
+       }
+       return 1;
+}
+
+static void esp_print_decode_ikeline(netdissect_options *ndo, char *line,
+                                    const char *file, int lineno)
+{
+       /* it's an IKEv2 secret, store it instead */
+       struct sa_list sa1;
+
+       char *init;
+       char *icookie, *rcookie;
+       int   ilen, rlen;
+       char *authkey;
+       char *enckey;
+       
+       init = strsep(&line, " \t");
+       icookie = strsep(&line, " \t");
+       rcookie = strsep(&line, " \t");
+       authkey = strsep(&line, " \t");
+       enckey  = strsep(&line, " \t");
+       
+       /* if any fields are missing */
+       if(!init || !icookie || !rcookie || !authkey || !enckey) {
+               (*ndo->ndo_warning)(ndo, "print_esp: failed to find all fields for ikev2 at %s:%u",
+                                   file, lineno);
+               
+               return;
+       }
+       
+       ilen = strlen(icookie);
+       rlen = strlen(rcookie);
+
+       if((init[0]!='I' && init[0]!='R')
+          || icookie[0]!='0' || icookie[1]!='x'
+          || rcookie[0]!='0' || rcookie[1]!='x'
+          || ilen!=18
+          || rlen!=18) {
+               (*ndo->ndo_warning)(ndo, "print_esp: line %s:%u improperly formatted.",
+                                   file, lineno);
+
+               (*ndo->ndo_warning)(ndo, "init=%s icookie=%s(%u) rcookie=%s(%u)",
+                                   init, icookie, ilen, rcookie, rlen);
+               
+               return;
+       }
+
+       sa1.spi = 0;
+       sa1.initiator = (init[0] == 'I');
+       if(espprint_decode_hex(ndo, sa1.spii, sizeof(sa1.spii), icookie+2)!=8)
+               return;
+
+       if(espprint_decode_hex(ndo, sa1.spir, sizeof(sa1.spir), rcookie+2)!=8)
+               return;
+
+       if(!espprint_decode_encalgo(ndo, enckey, &sa1)) return;
+
+       if(!espprint_decode_authalgo(ndo, authkey, &sa1)) return;
+       
+       esp_print_addsa(ndo, &sa1, FALSE);
+}
+
+/*
  *
- * special form: file /name 
+ * special form: file /name
  * causes us to go read from this file instead.
  *
  */
-static void esp_print_decode_onesecret(char *line)
+static void esp_print_decode_onesecret(netdissect_options *ndo, char *line,
+                                      const char *file, int lineno)
 {
-       struct esp_algorithm *xf;
        struct sa_list sa1;
        int sa_def;
 
@@ -192,15 +393,18 @@ static void esp_print_decode_onesecret(char *line)
                /* open file and read it */
                FILE *secretfile;
                char  fileline[1024];
+               int   lineno=0;
                char  *nl;
+               char *filename = line;
 
-               secretfile = fopen(line, FOPEN_READ_TXT);
+               secretfile = fopen(filename, FOPEN_READ_TXT);
                if (secretfile == NULL) {
-                       perror(line);
+                       perror(filename);
                        exit(3);
                }
 
                while (fgets(fileline, sizeof(fileline)-1, secretfile) != NULL) {
+                       lineno++;
                        /* remove newline from the line */
                        nl = strchr(fileline, '\n');
                        if (nl)
@@ -208,31 +412,37 @@ static void esp_print_decode_onesecret(char *line)
                        if (fileline[0] == '#') continue;
                        if (fileline[0] == '\0') continue;
 
-                       esp_print_decode_onesecret(fileline);
+                       esp_print_decode_onesecret(ndo, fileline, filename, lineno);
                }
                fclose(secretfile);
 
                return;
        }
 
+       if (spikey && strcasecmp(spikey, "ikev2") == 0) {
+               esp_print_decode_ikeline(ndo, line, file, lineno);
+               return;
+       } 
+
        if (spikey) {
+               
                char *spistr, *foo;
                u_int32_t spino;
                struct sockaddr_in *sin;
 #ifdef INET6
                struct sockaddr_in6 *sin6;
 #endif
-
+               
                spistr = strsep(&spikey, "@");
-
+               
                spino = strtoul(spistr, &foo, 0);
                if (spistr == foo || !spikey) {
-                       printf("print_esp: failed to decode spi# %s\n", foo);
+                       (*ndo->ndo_warning)(ndo, "print_esp: failed to decode spi# %s\n", foo);
                        return;
                }
-
+               
                sa1.spi = spino;
-
+               
                sin = (struct sockaddr_in *)&sa1.daddr;
 #ifdef INET6
                sin6 = (struct sockaddr_in6 *)&sa1.daddr;
@@ -243,111 +453,86 @@ static void esp_print_decode_onesecret(char *line)
                        sin6->sin6_family = AF_INET6;
                } else
 #endif
-               if (inet_pton(AF_INET, spikey, &sin->sin_addr) == 1) {
+                       if (inet_pton(AF_INET, spikey, &sin->sin_addr) == 1) {
 #ifdef HAVE_SOCKADDR_SA_LEN
-                       sin->sin_len = sizeof(struct sockaddr_in);
+                               sin->sin_len = sizeof(struct sockaddr_in);
 #endif
-                       sin->sin_family = AF_INET;
-               } else {
-                       printf("print_esp: can not decode IP# %s\n", spikey);
-                       return;
-               }
+                               sin->sin_family = AF_INET;
+                       } else {
+                               (*ndo->ndo_warning)(ndo, "print_esp: can not decode IP# %s\n", spikey);
+                               return;
+                       }
        }
 
        if (decode) {
-               char *colon;
-               char  espsecret_key[256];
-               unsigned int   len, i;
-
                /* skip any blank spaces */
                while (isspace((unsigned char)*decode))
                        decode++;
-
-               colon = strchr(decode, ':');
-               if (colon == NULL) {
-                       printf("failed to decode espsecret: %s\n", decode);
+               
+               if(!espprint_decode_encalgo(ndo, decode, &sa1)) {
                        return;
                }
-
-               len = colon - decode;
-               xf = esp_xforms;
-               while (xf->name && strncasecmp(decode, xf->name, len) != 0)
-                       xf++;
-               if (xf->name == NULL) {
-                       printf("failed to find cipher algo %s\n", decode);
-                       /* set to NULL transform */
-                       return;
-               }
-               sa1.xform = xf;
-
-               colon++;
-               if (colon[0] == '0' && colon[1] == 'x') {
-                       /* decode some hex! */
-                       colon += 2;
-                       len = strlen(colon) / 2;
-
-                       if (len > 256) {
-                               printf("secret is too big: %d\n", len);
-                               return;
-                       }
-
-                       i = 0;
-                       while (colon[0] != '\0' && colon[1]!='\0') {
-                               espsecret_key[i] = hex2byte(colon);
-                               colon += 2;
-                               i++;
-                       }
-                       memcpy(sa1.secret, espsecret_key, i);
-                       sa1.secretlen=i;
-               } else {
-                       i = strlen(colon);
-                       if (i < sizeof(sa1.secret)) {
-                               memcpy(sa1.secret, espsecret_key, i);
-                               sa1.secretlen = i;
-                       } else {
-                               memcpy(sa1.secret, espsecret_key,
-                                   sizeof(sa1.secret));
-                               sa1.secretlen = sizeof(sa1.secret);
-                       }
-               }
        }
 
-       esp_print_addsa(&sa1, sa_def);
+       esp_print_addsa(ndo, &sa1, sa_def);
 }
 
+static void esp_init(netdissect_options *ndo _U_)
+{
 
-static void esp_print_decodesecret(void)
+       OpenSSL_add_all_algorithms();
+       EVP_add_cipher_alias(SN_des_ede3_cbc, "3des");
+}
+
+void esp_print_decodesecret(netdissect_options *ndo)
 {
        char *line;
        char *p;
+       static int initialized = 0;
 
-       if (espsecret == NULL) {
-               sa_list_head = NULL;
-               return;
+       if (!initialized) {
+               esp_init(ndo);
+               initialized = 1;
        }
 
-       if (sa_list_head != NULL)
-               return;
+       p = ndo->ndo_espsecret;
 
-       p = espsecret;
-
-       while (espsecret && espsecret[0] != '\0') { 
+       while (p && p[0] != '\0') {
                /* pick out the first line or first thing until a comma */
-               if ((line = strsep(&espsecret, "\n,")) == NULL) {
-                       line = espsecret;
-                       espsecret = NULL;
+               if ((line = strsep(&p, "\n,")) == NULL) {
+                       line = p;
+                       p = NULL;
                }
 
-               esp_print_decode_onesecret(line);
+               esp_print_decode_onesecret(ndo, line, "cmdline", 0);
        }
+
+       ndo->ndo_espsecret = NULL;
 }
 
+#endif
+
 int
-esp_print(register const u_char *bp, register const u_char *bp2,
-         int *nhdr, int *padlen)
+esp_print(netdissect_options *ndo,
+         const u_char *bp, const int length, const u_char *bp2
+#ifndef HAVE_LIBCRYPTO
+       _U_
+#endif
+       ,
+       int *nhdr
+#ifndef HAVE_LIBCRYPTO
+       _U_
+#endif
+       ,
+       int *padlen
+#ifndef HAVE_LIBCRYPTO
+       _U_
+#endif
+       )
 {
        register const struct newesp *esp;
        register const u_char *ep;
+#ifdef HAVE_LIBCRYPTO
        struct ip *ip;
        struct sa_list *sa = NULL;
        int espsecret_keylen;
@@ -356,16 +541,20 @@ esp_print(register const u_char *bp, register const u_char *bp2,
 #endif
        int advance;
        int len;
-       char *secret;
+       u_char *secret;
        int ivlen = 0;
        u_char *ivoff;
-#ifdef HAVE_LIBCRYPTO
        u_char *p;
+       EVP_CIPHER_CTX ctx;
+       int blocksz;
 #endif
 
        esp = (struct newesp *)bp;
+
+#ifdef HAVE_LIBCRYPTO
        secret = NULL;
        advance = 0;
+#endif
 
 #if 0
        /* keep secret out of a register */
@@ -373,24 +562,28 @@ esp_print(register const u_char *bp, register const u_char *bp2,
 #endif
 
        /* 'ep' points to the end of available data. */
-       ep = snapend;
+       ep = ndo->ndo_snapend;
 
        if ((u_char *)(esp + 1) >= ep) {
                fputs("[|ESP]", stdout);
                goto fail;
        }
-       printf("ESP(spi=0x%08x", EXTRACT_32BITS(&esp->esp_spi));
-       printf(",seq=0x%x", EXTRACT_32BITS(&esp->esp_seq));
-       printf(")");
+       (*ndo->ndo_printf)(ndo, "ESP(spi=0x%08x", EXTRACT_32BITS(&esp->esp_spi));
+       (*ndo->ndo_printf)(ndo, ",seq=0x%x)", EXTRACT_32BITS(&esp->esp_seq));
+        (*ndo->ndo_printf)(ndo, ", length %u", length);
 
-       /* if we don't have decryption key, we can't decrypt this packet. */
-       if (sa_list_head == NULL) {
-               if (!espsecret)
+#ifndef HAVE_LIBCRYPTO
+       goto fail;
+#else
+       /* initiailize SAs */
+       if (ndo->ndo_sa_list_head == NULL) {
+               if (!ndo->ndo_espsecret)
                        goto fail;
-               esp_print_decodesecret();
+
+               esp_print_decodesecret(ndo);
        }
 
-       if (sa_list_head == NULL)
+       if (ndo->ndo_sa_list_head == NULL)
                goto fail;
 
        ip = (struct ip *)bp2;
@@ -405,9 +598,9 @@ esp_print(register const u_char *bp, register const u_char *bp2,
                len = sizeof(struct ip6_hdr) + EXTRACT_16BITS(&ip6->ip6_plen);
 
                /* see if we can find the SA, and if so, decode it */
-               for (sa = sa_list_head; sa != NULL; sa = sa->next) {
+               for (sa = ndo->ndo_sa_list_head; sa != NULL; sa = sa->next) {
                        struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&sa->daddr;
-                       if (sa->spi == ntohl(esp->esp_spi) &&
+                       if (sa->spi == EXTRACT_32BITS(&esp->esp_spi) &&
                            sin6->sin6_family == AF_INET6 &&
                            memcmp(&sin6->sin6_addr, &ip6->ip6_dst,
                                   sizeof(struct in6_addr)) == 0) {
@@ -423,9 +616,9 @@ esp_print(register const u_char *bp, register const u_char *bp2,
                len = EXTRACT_16BITS(&ip->ip_len);
 
                /* see if we can find the SA, and if so, decode it */
-               for (sa = sa_list_head; sa != NULL; sa = sa->next) {
+               for (sa = ndo->ndo_sa_list_head; sa != NULL; sa = sa->next) {
                        struct sockaddr_in *sin = (struct sockaddr_in *)&sa->daddr;
-                       if (sa->spi == ntohl(esp->esp_spi) &&
+                       if (sa->spi == EXTRACT_32BITS(&esp->esp_spi) &&
                            sin->sin_family == AF_INET &&
                            sin->sin_addr.s_addr == ip->ip_dst.s_addr) {
                                break;
@@ -439,9 +632,8 @@ esp_print(register const u_char *bp, register const u_char *bp2,
        /* if we didn't find the specific one, then look for
         * an unspecified one.
         */
-       if (sa == NULL) {
-               sa = sa_default;
-       }
+       if (sa == NULL)
+               sa = ndo->ndo_sa_default;
        
        /* if not found fail */
        if (sa == NULL)
@@ -455,191 +647,27 @@ esp_print(register const u_char *bp, register const u_char *bp2,
                ep = bp2 + len;
        }
 
-       ivoff = (u_char *)(esp + 1) + sa->xform->replaysize;
-       ivlen = sa->xform->ivlen;
+       ivoff = (u_char *)(esp + 1) + 0;
+       ivlen = sa->ivlen;
        secret = sa->secret;
        espsecret_keylen = sa->secretlen;
+       ep = ep - sa->authlen;
 
-       switch (sa->xform->algo) {
-       case DESCBC:
-#ifdef HAVE_LIBCRYPTO
-           {
-               u_char iv[8];
-#if OPENSSL_VERSION_NUMBER >= 0x00907000L
-               DES_key_schedule schedule;
-#else
-               des_key_schedule schedule;
-#endif
-
-               switch (ivlen) {
-               case 4:
-                       memcpy(iv, ivoff, 4);
-                       memcpy(&iv[4], ivoff, 4);
-                       p = &iv[4];
-                       *p++ ^= 0xff;
-                       *p++ ^= 0xff;
-                       *p++ ^= 0xff;
-                       *p++ ^= 0xff;
-                       break;
-               case 8:
-                       memcpy(iv, ivoff, 8);
-                       break;
-               default:
-                       goto fail;
-               }
-               p = ivoff + ivlen;
-
-               if (espsecret_keylen != 8)
-                       goto fail;
+       if (sa->evp) {
+               memset(&ctx, 0, sizeof(ctx));
+               if (EVP_CipherInit(&ctx, sa->evp, secret, NULL, 0) < 0)
+                       (*ndo->ndo_warning)(ndo, "espkey init failed");
 
-#if OPENSSL_VERSION_NUMBER >= 0x00908000L
-               DES_set_key_unchecked((const_DES_cblock *)secret, &schedule);
+               blocksz = EVP_CIPHER_CTX_block_size(&ctx);
 
-               DES_cbc_encrypt((const unsigned char *)p, p,
-                   (long)(ep - p), &schedule, (DES_cblock *)iv, DES_DECRYPT);
-
-#elif OPENSSL_VERSION_NUMBER >= 0x00907000L
-               DES_set_key_unchecked((DES_cblock *)secret, schedule);
-
-               DES_cbc_encrypt((const unsigned char *)p, p,
-                   (long)(ep - p), schedule, (DES_cblock *)iv, DES_DECRYPT);
-#else
-               des_check_key = 0;
-               des_set_key((void *)secret, schedule);
-
-               des_cbc_encrypt((void *)p, (void *)p,
-                   (long)(ep - p), schedule, (void *)iv, DES_DECRYPT);
-#endif
+               p = ivoff;
+               EVP_CipherInit(&ctx, NULL, NULL, p, 0);
+               EVP_Cipher(&ctx, p + ivlen, p + ivlen, ep - (p + ivlen));
+               EVP_CIPHER_CTX_cleanup(&ctx);
                advance = ivoff - (u_char *)esp + ivlen;
-               break;
-           }
-#else
-               goto fail;
-#endif /*HAVE_LIBCRYPTO*/
-
-       case BLOWFISH:
-#ifdef HAVE_LIBCRYPTO
-           {
-               BF_KEY schedule;
-
-               if (espsecret_keylen < 5 || espsecret_keylen > 56)
-                       goto fail;
-               BF_set_key(&schedule, espsecret_keylen, secret);
-
-               p = ivoff + ivlen;
-               BF_cbc_encrypt(p, p, (long)(ep - p), &schedule, ivoff,
-                       BF_DECRYPT);
-               advance = ivoff - (u_char *)esp + ivlen;
-               break;
-           }
-#else
-               goto fail;
-#endif /*HAVE_LIBCRYPTO*/
-
-       case RC5:
-#if defined(HAVE_LIBCRYPTO) && defined(HAVE_RC5_H)
-           {
-               RC5_32_KEY schedule;
-
-               if (espsecret_keylen < 5 || espsecret_keylen > 255)
-                       goto fail;
-               RC5_32_set_key(&schedule, espsecret_keylen, secret,
-                       RC5_16_ROUNDS);
-
-               p = ivoff + ivlen;
-               RC5_32_cbc_encrypt(p, p, (long)(ep - p), &schedule, ivoff,
-                       RC5_DECRYPT);
-               advance = ivoff - (u_char *)esp + ivlen;
-               break;
-           }
-#else
-               goto fail;
-#endif /*HAVE_LIBCRYPTO*/
-
-       case CAST128:
-#if defined(HAVE_LIBCRYPTO) && defined(HAVE_CAST_H) && !defined(HAVE_BUGGY_CAST128)
-           {
-               CAST_KEY schedule;
-
-               if (espsecret_keylen < 5 || espsecret_keylen > 16)
-                       goto fail;
-               CAST_set_key(&schedule, espsecret_keylen, secret);
-
-               p = ivoff + ivlen;
-               CAST_cbc_encrypt(p, p, (long)(ep - p), &schedule, ivoff,
-                       CAST_DECRYPT);
-               advance = ivoff - (u_char *)esp + ivlen;
-               break;
-           }
-#else
-               goto fail;
-#endif /*HAVE_LIBCRYPTO*/
-
-       case DES3CBC:
-#if defined(HAVE_LIBCRYPTO)
-           {
-#if OPENSSL_VERSION_NUMBER >= 0x00907000L
-               DES_key_schedule s1, s2, s3;
-
-               if (espsecret_keylen != 24)
-                       goto fail;
-               DES_set_odd_parity((DES_cblock *)secret);
-               DES_set_odd_parity((DES_cblock *)(secret + 8));
-               DES_set_odd_parity((DES_cblock *)(secret + 16));
-#if OPENSSL_VERSION_NUMBER >= 0x00908000L
-               if (DES_set_key_checked((const_DES_cblock *)secret, &s1) != 0)
-                       printf("failed to schedule key 1\n");
-               if (DES_set_key_checked((const_DES_cblock *)(secret + 8), &s2) != 0)
-                       printf("failed to schedule key 2\n");
-               if (DES_set_key_checked((const_DES_cblock *)(secret + 16), &s3) != 0)
-                       printf("failed to schedule key 3\n");
-#else
-               if (DES_set_key_checked((DES_cblock *)secret, s1) != 0)
-                       printf("failed to schedule key 1\n");
-               if (DES_set_key_checked((DES_cblock *)(secret + 8), s2) != 0)
-                       printf("failed to schedule key 2\n");
-               if (DES_set_key_checked((DES_cblock *)(secret + 16), s3) != 0)
-                       printf("failed to schedule key 3\n");
-#endif
-
-               p = ivoff + ivlen;
-               DES_ede3_cbc_encrypt((const unsigned char *)p, p,
-                   (long)(ep - p), &s1, &s2, &s3, (DES_cblock *)ivoff,
-                   DES_DECRYPT);
-#else
-               des_key_schedule s1, s2, s3;
-
-               if (espsecret_keylen != 24)
-                       goto fail;
-               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);
-#endif
-               advance = ivoff - (u_char *)esp + ivlen;
-               break;
-           }
-#else
-               goto fail;
-#endif /*HAVE_LIBCRYPTO*/
-
-       case NONE:
-       default:
-               advance = sizeof(struct newesp) + sa->xform->replaysize;
-               break;
-       }
+       } else
+               advance = sizeof(struct newesp);
 
-       ep = ep - sa->xform->authlen;
        /* sanity check for pad length */
        if (ep - bp < *(ep - 2))
                goto fail;
@@ -650,11 +678,17 @@ esp_print(register const u_char *bp, register const u_char *bp2,
        if (nhdr)
                *nhdr = *(ep - 1);
 
-       printf(": ");
+       (ndo->ndo_printf)(ndo, ": ");
        return advance;
+#endif
 
 fail:
-       if (nhdr)
-               *nhdr = -1;
-       return 65536;
+       return -1;
 }
+
+/*
+ * Local Variables:
+ * c-style: whitesmith
+ * c-basic-offset: 8
+ * End:
+ */