+ register const struct esp *esp;
+ register const u_char *ep;
+ u_int32_t spi;
+ struct ip *ip = NULL;
+#ifdef INET6
+ struct ip6_hdr *ip6 = NULL;
+#endif
+ int advance;
+ int len;
+ char *secret;
+ int ivlen = 0;
+ u_char *ivoff;
+#ifdef HAVE_LIBCRYPTO
+ u_char *p;
+#endif
+
+ 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;
+
+ if ((u_char *)(esp + 1) >= ep - sizeof(struct esp)) {
+ fputs("[|ESP]", stdout);
+ goto fail;
+ }
+ printf("ESP(spi=0x%08x", spi);
+ printf(",seq=0x%x", (u_int32_t)ntohl(*(u_int32_t *)(esp + 1)));
+ printf(")");
+
+ /* if we don't have decryption key, we can't decrypt this packet. */
+ if (!espsecret)
+ goto fail;
+
+ if(!espsecret_xform) {
+ esp_print_decodesecret();
+ }
+ if(espsecret_xform->algo == NONE) {
+ goto fail;
+ }
+
+ ip = (struct ip *)bp2;
+ switch (IP_V(ip)) {
+#ifdef INET6
+ case 6:
+ ip6 = (struct ip6_hdr *)bp2;
+ ip = NULL;
+ /* we do not attempt to decrypt jumbograms */
+ if (!ntohs(ip6->ip6_plen))
+ goto fail;
+ /* if we can't get nexthdr, we do not need to decrypt it */
+ len = sizeof(struct ip6_hdr) + ntohs(ip6->ip6_plen);
+ break;
+#endif /*INET6*/
+ case 4:
+ /* nexthdr & padding are in the last fragment */
+ if (ntohs(ip->ip_off) & IP_MF)
+ goto fail;
+#ifdef INET6
+ ip6 = NULL;
+#endif
+ len = ntohs(ip->ip_len);
+ break;
+ default:
+ goto fail;
+ }
+
+ /* if we can't get nexthdr, we do not need to decrypt it */
+ if (ep - bp2 < len)
+ goto fail;
+
+ ivoff = (u_char *)(esp + 1) + espsecret_xform->replaysize;
+ ivlen = espsecret_xform->ivlen;
+ secret = espsecret_key;
+
+ switch (espsecret_xform->algo) {
+ case DESCBC:
+#ifdef HAVE_LIBCRYPTO
+ {
+ u_char iv[8];
+ des_key_schedule schedule;
+
+ 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;
+ }
+
+ des_check_key = 0;
+ des_set_key((void *)secret, schedule);
+
+ p = ivoff + ivlen;
+ des_cbc_encrypt((void *)p, (void *)p,
+ (long)(ep - p), schedule, (void *)iv,
+ DES_DECRYPT);
+ advance = ivoff - (u_char *)esp + ivlen;
+ break;
+ }
+#else
+ goto fail;
+#endif /*HAVE_LIBCRYPTO*/
+
+ case BLOWFISH:
+#ifdef HAVE_LIBCRYPTO
+ {
+ BF_KEY schedule;
+
+ BF_set_key(&schedule, strlen(secret), 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;
+
+ RC5_32_set_key(&schedule, strlen(secret), 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;
+
+ CAST_set_key(&schedule, strlen(secret), 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)
+ {
+ des_key_schedule s1, s2, 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");
+ }