summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/conf/files8
-rw-r--r--sys/net/pfkeyv2.c45
-rw-r--r--sys/net/pfkeyv2.h26
-rw-r--r--sys/netinet/in_proto.c8
-rw-r--r--sys/netinet/ip_ah.c (renamed from sys/netinet/ip_ah_new.c)357
-rw-r--r--sys/netinet/ip_ah.h42
-rw-r--r--sys/netinet/ip_ah_old.c589
-rw-r--r--sys/netinet/ip_esp.c (renamed from sys/netinet/ip_esp_new.c)398
-rw-r--r--sys/netinet/ip_esp.h34
-rw-r--r--sys/netinet/ip_esp_old.c811
-rw-r--r--sys/netinet/ip_ipsp.c41
-rw-r--r--sys/netinet/ip_ipsp.h77
-rw-r--r--sys/netinet/ip_xform.c12
-rw-r--r--sys/netinet/ipsec_input.c14
14 files changed, 666 insertions, 1796 deletions
diff --git a/sys/conf/files b/sys/conf/files
index b3d6294c202..710404cfd22 100644
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -1,4 +1,4 @@
-# $OpenBSD: files,v 1.149 2000/01/21 03:15:06 angelos Exp $
+# $OpenBSD: files,v 1.150 2000/01/27 08:09:07 angelos Exp $
# $NetBSD: files,v 1.87 1996/05/19 17:17:50 jonathan Exp $
# @(#)files.newconf 7.5 (Berkeley) 5/10/93
@@ -500,10 +500,8 @@ file netinet/ip_ipip.c inet | inet6
file netinet/ip_ether.c inet & ipsec
file netinet/ipsec_input.c (inet | inet6) & ipsec
file netinet/ip_xform.c inet & ipsec
-file netinet/ip_esp_old.c inet & ipsec
-file netinet/ip_esp_new.c inet & ipsec
-file netinet/ip_ah_old.c inet & ipsec
-file netinet/ip_ah_new.c inet & ipsec
+file netinet/ip_esp.c inet & ipsec
+file netinet/ip_ah.c inet & ipsec
file netinet/ip_rmd160.c inet & ipsec
file netinet/ip_sha1.c inet & ipsec
file netinet/ip_blf.c (inet & ipsec) | uvm_swap_encrypt
diff --git a/sys/net/pfkeyv2.c b/sys/net/pfkeyv2.c
index d2e8b7e0069..844d2493350 100644
--- a/sys/net/pfkeyv2.c
+++ b/sys/net/pfkeyv2.c
@@ -179,6 +179,12 @@ import_sa(struct tdb *tdb, struct sadb_sa *sadb_sa, struct ipsecinit *ii)
if (sadb_sa->sadb_sa_flags & SADB_X_SAFLAGS_TUNNEL)
tdb->tdb_flags |= TDBF_TUNNELING;
+
+ if (sadb_sa->sadb_sa_flags & SADB_X_SAFLAGS_RANDOMPADDING)
+ tdb->tdb_flags |= TDBF_RANDOMPADDING;
+
+ if (sadb_sa->sadb_sa_flags & SADB_X_SAFLAGS_NOREPLAY)
+ tdb->tdb_flags |= TDBF_NOREPLAY;
}
if (sadb_sa->sadb_sa_state != SADB_SASTATE_MATURE)
@@ -217,6 +223,12 @@ export_sa(void **p, struct tdb *tdb)
if (tdb->tdb_flags & TDBF_TUNNELING)
sadb_sa->sadb_sa_flags |= SADB_X_SAFLAGS_TUNNEL;
+ if (tdb->tdb_flags & TDBF_RANDOMPADDING)
+ sadb_sa->sadb_sa_flags |= SADB_X_SAFLAGS_RANDOMPADDING;
+
+ if (tdb->tdb_flags & TDBF_NOREPLAY)
+ sadb_sa->sadb_sa_flags |= SADB_X_SAFLAGS_NOREPLAY;
+
*p += sizeof(struct sadb_sa);
}
@@ -807,26 +819,24 @@ pfkeyv2_get_proto_alg(u_int8_t satype, u_int8_t *sproto, int *alg)
switch (satype)
{
case SADB_SATYPE_AH:
- case SADB_X_SATYPE_AH_OLD:
if (!ah_enable)
return EOPNOTSUPP;
*sproto = IPPROTO_AH;
if(alg != NULL)
- *alg = satype == SADB_SATYPE_AH ? XF_NEW_AH : XF_OLD_AH;
+ *alg = satype = XF_AH;
break;
case SADB_SATYPE_ESP:
- case SADB_X_SATYPE_ESP_OLD:
if (!esp_enable)
return EOPNOTSUPP;
*sproto = IPPROTO_ESP;
if(alg != NULL)
- *alg = satype == SADB_SATYPE_ESP ? XF_NEW_ESP : XF_OLD_ESP;
+ *alg = satype = XF_ESP;
break;
@@ -1307,8 +1317,6 @@ pfkeyv2_send(struct socket *socket, void *message, int len)
case SADB_SATYPE_AH:
case SADB_SATYPE_ESP:
- case SADB_X_SATYPE_AH_OLD:
- case SADB_X_SATYPE_ESP_OLD:
case SADB_X_SATYPE_IPIP:
#ifdef TCP_SIGNATURE
case SADB_X_SATYPE_TCPSIGNATURE:
@@ -1356,8 +1364,13 @@ pfkeyv2_send(struct socket *socket, void *message, int len)
struct rtentry *rt;
ssa = (struct sadb_sa *) headers[SADB_EXT_SA];
- sunionp = (union sockaddr_union *) (headers[SADB_EXT_ADDRESS_DST] +
- sizeof(struct sadb_address));
+
+ if (headers[SADB_EXT_ADDRESS_DST])
+ sunionp = (union sockaddr_union *)
+ (headers[SADB_EXT_ADDRESS_DST] +
+ sizeof(struct sadb_address));
+ else
+ sunionp = NULL;
/*
* SADB_X_SAFLAGS_REPLACEFLOW set means we should remove any
@@ -1410,6 +1423,12 @@ pfkeyv2_send(struct socket *socket, void *message, int len)
if (!delflag || ingress)
{
+ if ((ssa == NULL) || (sunionp == NULL))
+ {
+ rval = EINVAL;
+ goto splxret;
+ }
+
/* Find the relevant SA */
sa2 = gettdb(ssa->sadb_sa_spi, sunionp,
SADB_GETSPROTO(smsg->sadb_msg_satype));
@@ -1463,8 +1482,8 @@ pfkeyv2_send(struct socket *socket, void *message, int len)
else
if (ingress)
{
- /* If we're deleting a flow... */
- flow = find_flow(src, dst, srcmask, dstmask, sproto,
+ /* If we're deleting an ingress flow... */
+ flow = find_flow(src, srcmask, dst, dstmask, sproto,
sa2, FLOW_INGRESS);
if (flow == NULL)
{
@@ -1481,6 +1500,7 @@ pfkeyv2_send(struct socket *socket, void *message, int len)
encapdst.sen_family = PF_KEY;
switch (flow->flow_src.sa.sa_family)
{
+#ifdef INET
case AF_INET:
encapdst.sen_len = SENT_IP4_LEN;
encapdst.sen_type = SENT_IP4;
@@ -1496,8 +1516,9 @@ pfkeyv2_send(struct socket *socket, void *message, int len)
encapnetmask.sen_ip_src = flow->flow_srcmask.sin.sin_addr;
encapnetmask.sen_ip_dst = flow->flow_dstmask.sin.sin_addr;
break;
+#endif /* INET */
-#if INET6
+#ifdef INET6
case AF_INET6:
encapdst.sen_len = SENT_IP6_LEN;
encapdst.sen_type = SENT_IP6;
@@ -1522,6 +1543,7 @@ pfkeyv2_send(struct socket *socket, void *message, int len)
{
switch (sa2->tdb_dst.sa.sa_family)
{
+#ifdef INET
case AF_INET:
encapgw.sen_len = SENT_IPSP_LEN;
encapgw.sen_family = PF_KEY;
@@ -1541,6 +1563,7 @@ pfkeyv2_send(struct socket *socket, void *message, int len)
encapnetmask.sen_dport = 0xffff;
}
break;
+#endif /* INET */
#if INET6
case AF_INET6:
diff --git a/sys/net/pfkeyv2.h b/sys/net/pfkeyv2.h
index 4c8f30fdd57..1952b82a05b 100644
--- a/sys/net/pfkeyv2.h
+++ b/sys/net/pfkeyv2.h
@@ -160,9 +160,7 @@ struct sadb_protocol {
};
#define SADB_GETSPROTO(x) ( (x) == SADB_SATYPE_AH ? IPPROTO_AH :\
- (x) == SADB_X_SATYPE_AH_OLD ? IPPROTO_AH :\
(x) == SADB_SATYPE_ESP ? IPPROTO_ESP :\
- (x) == SADB_X_SATYPE_ESP_OLD ? IPPROTO_ESP :\
(x) == SADB_X_SATYPE_BYPASS ? IPPROTO_IP :\
IPPROTO_IPIP )
@@ -199,12 +197,10 @@ struct sadb_protocol {
#define SADB_SATYPE_OSPFV2 4
#define SADB_SATYPE_RIPV2 5
#define SADB_SATYPE_MIP 6
-#define SADB_X_SATYPE_AH_OLD 7
-#define SADB_X_SATYPE_ESP_OLD 8
-#define SADB_X_SATYPE_IPIP 9
-#define SADB_X_SATYPE_TCPSIGNATURE 10
-#define SADB_X_SATYPE_BYPASS 11
-#define SADB_SATYPE_MAX 11
+#define SADB_X_SATYPE_IPIP 7
+#define SADB_X_SATYPE_TCPSIGNATURE 8
+#define SADB_X_SATYPE_BYPASS 9
+#define SADB_SATYPE_MAX 9
#define SADB_SASTATE_LARVAL 0
#define SADB_SASTATE_MATURE 1
@@ -230,12 +226,14 @@ struct sadb_protocol {
#define SADB_X_EALG_SKIPJACK 5
#define SADB_EALG_MAX 5
-#define SADB_SAFLAGS_PFS 0x01 /* perfect forward secrecy */
-#define SADB_X_SAFLAGS_HALFIV 0x02 /* Used for ESP-old */
-#define SADB_X_SAFLAGS_TUNNEL 0x04 /* Force tunneling */
-#define SADB_X_SAFLAGS_CHAINDEL 0x08 /* Delete whole SA chain */
-#define SADB_X_SAFLAGS_REPLACEFLOW 0x20 /* Replace existing flow */
-#define SADB_X_SAFLAGS_INGRESS_FLOW 0x40 /* Ingress ACL entry */
+#define SADB_SAFLAGS_PFS 0x001 /* perfect forward secrecy */
+#define SADB_X_SAFLAGS_HALFIV 0x002 /* Used for ESP-old */
+#define SADB_X_SAFLAGS_TUNNEL 0x004 /* Force tunneling */
+#define SADB_X_SAFLAGS_CHAINDEL 0x008 /* Delete whole SA chain */
+#define SADB_X_SAFLAGS_REPLACEFLOW 0x020 /* Replace existing flow */
+#define SADB_X_SAFLAGS_INGRESS_FLOW 0x040 /* Ingress ACL entry */
+#define SADB_X_SAFLAGS_RANDOMPADDING 0x080 /* Random ESP padding */
+#define SADB_X_SAFLAGS_NOREPLAY 0x100 /* No replay counter */
#define SADB_IDENTTYPE_RESERVED 0
#define SADB_IDENTTYPE_PREFIX 1
diff --git a/sys/netinet/in_proto.c b/sys/netinet/in_proto.c
index da7125e73fa..ca30664e986 100644
--- a/sys/netinet/in_proto.c
+++ b/sys/netinet/in_proto.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: in_proto.c,v 1.24 2000/01/21 03:15:05 angelos Exp $ */
+/* $OpenBSD: in_proto.c,v 1.25 2000/01/27 08:09:08 angelos Exp $ */
/* $NetBSD: in_proto.c,v 1.14 1996/02/18 18:58:32 christos Exp $ */
/*
@@ -154,8 +154,6 @@ void iplinit __P((void));
#ifdef IPSEC
#include <netinet/ip_ipsp.h>
-#include <netinet/ip_ah.h>
-#include <netinet/ip_esp.h>
#include <netinet/ip_ether.h>
#endif
@@ -258,12 +256,12 @@ struct protosw inetsw[] = {
#endif /* NSIP */
#ifdef IPSEC
{ SOCK_RAW, &inetdomain, IPPROTO_AH, PR_ATOMIC|PR_ADDR,
- ah_input, rip_output, 0, rip_ctloutput,
+ ah4_input, rip_output, 0, rip_ctloutput,
rip_usrreq,
0, 0, 0, 0, ah_sysctl
},
{ SOCK_RAW, &inetdomain, IPPROTO_ESP, PR_ATOMIC|PR_ADDR,
- esp_input, rip_output, 0, rip_ctloutput,
+ esp4_input, rip_output, 0, rip_ctloutput,
rip_usrreq,
0, 0, 0, 0, esp_sysctl
},
diff --git a/sys/netinet/ip_ah_new.c b/sys/netinet/ip_ah.c
index d317df7b48b..39e54483cb9 100644
--- a/sys/netinet/ip_ah_new.c
+++ b/sys/netinet/ip_ah.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_ah_new.c,v 1.36 2000/01/09 23:42:37 angelos Exp $ */
+/* $OpenBSD: ip_ah.c,v 1.33 2000/01/27 08:09:08 angelos Exp $ */
/*
* The authors of this code are John Ioannidis (ji@tla.org),
@@ -35,10 +35,6 @@
* PURPOSE.
*/
-/*
- * Based on RFC 2085.
- */
-
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/malloc.h>
@@ -57,6 +53,7 @@
#include <net/route.h>
#include <net/netisr.h>
#include <net/raw_cb.h>
+#include <net/bpf.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
@@ -70,6 +67,9 @@
#include <netinet/ip_ipsp.h>
#include <netinet/ip_ah.h>
#include <net/pfkeyv2.h>
+#include <net/if_enc.h>
+
+#include "bpfilter.h"
#ifdef ENCDEBUG
#define DPRINTF(x) if (encdebug) printf x
@@ -84,47 +84,50 @@
extern struct auth_hash auth_hash_hmac_md5_96;
extern struct auth_hash auth_hash_hmac_sha1_96;
extern struct auth_hash auth_hash_hmac_ripemd_160_96;
+extern struct auth_hash auth_hash_key_md5;
+extern struct auth_hash auth_hash_key_sha1;
-struct auth_hash *ah_new_hash[] = {
+struct auth_hash *ah_hash[] = {
&auth_hash_hmac_md5_96,
&auth_hash_hmac_sha1_96,
- &auth_hash_hmac_ripemd_160_96
+ &auth_hash_hmac_ripemd_160_96,
+ &auth_hash_key_md5,
+ &auth_hash_key_sha1,
};
/*
- * ah_new_attach() is called from the transformation initialization code
+ * ah_attach() is called from the transformation initialization code
*/
int
-ah_new_attach()
+ah_attach()
{
return 0;
}
/*
- * ah_new_init() is called when an SPI is being set up.
+ * ah_init() is called when an SPI is being set up.
*/
-
int
-ah_new_init(struct tdb *tdbp, struct xformsw *xsp, struct ipsecinit *ii)
+ah_init(struct tdb *tdbp, struct xformsw *xsp, struct ipsecinit *ii)
{
struct auth_hash *thash = NULL;
int i;
- for (i = sizeof(ah_new_hash) / sizeof(ah_new_hash[0]) - 1; i >= 0; i--)
- if (ii->ii_authalg == ah_new_hash[i]->type)
+ for (i = sizeof(ah_hash) / sizeof(ah_hash[0]) - 1; i >= 0; i--)
+ if (ii->ii_authalg == ah_hash[i]->type)
break;
if (i < 0)
{
- DPRINTF(("ah_new_init(): unsupported authentication algorithm %d specified\n", ii->ii_authalg));
+ DPRINTF(("ah_init(): unsupported authentication algorithm %d specified\n", ii->ii_authalg));
return EINVAL;
}
- thash = ah_new_hash[i];
+ thash = ah_hash[i];
- if (ii->ii_authkeylen != thash->keysize)
+ if ((ii->ii_authkeylen != thash->keysize) && (thash->keysize != 0))
{
- DPRINTF(("ah_new_init(): keylength %d doesn't match algorithm %s keysize (%d)\n", ii->ii_authkeylen, thash->name, thash->keysize));
+ DPRINTF(("ah_init(): keylength %d doesn't match algorithm %s keysize (%d)\n", ii->ii_authkeylen, thash->name, thash->keysize));
return EINVAL;
}
@@ -133,29 +136,47 @@ ah_new_init(struct tdb *tdbp, struct xformsw *xsp, struct ipsecinit *ii)
tdbp->tdb_bitmap = 0;
tdbp->tdb_rpl = AH_HMAC_INITIAL_RPL;
- DPRINTF(("ah_new_init(): initialized TDB with hash algorithm %s\n",
+ DPRINTF(("ah_init(): initialized TDB with hash algorithm %s\n",
thash->name));
- /* Precompute the I and O pads of the HMAC */
- for (i = 0; i < ii->ii_authkeylen; i++)
- ii->ii_authkey[i] ^= HMAC_IPAD_VAL;
-
- MALLOC(tdbp->tdb_ictx, u_int8_t *, thash->ctxsize, M_XDATA, M_WAITOK);
- bzero(tdbp->tdb_ictx, thash->ctxsize);
- thash->Init(tdbp->tdb_ictx);
- thash->Update(tdbp->tdb_ictx, ii->ii_authkey, ii->ii_authkeylen);
- thash->Update(tdbp->tdb_ictx, hmac_ipad_buffer,
- HMAC_BLOCK_LEN - ii->ii_authkeylen);
+ tdbp->tdb_amxkeylen = ii->ii_authkeylen;
+ MALLOC(tdbp->tdb_amxkey, u_int8_t *, tdbp->tdb_amxkeylen, M_XDATA,
+ M_WAITOK);
- for (i = 0; i < ii->ii_authkeylen; i++)
- ii->ii_authkey[i] ^= (HMAC_IPAD_VAL ^ HMAC_OPAD_VAL);
+ bcopy(ii->ii_authkey, tdbp->tdb_amxkey, tdbp->tdb_amxkeylen);
- MALLOC(tdbp->tdb_octx, u_int8_t *, thash->ctxsize, M_XDATA, M_WAITOK);
- bzero(tdbp->tdb_octx, thash->ctxsize);
- thash->Init(tdbp->tdb_octx);
- thash->Update(tdbp->tdb_octx, ii->ii_authkey, ii->ii_authkeylen);
- thash->Update(tdbp->tdb_octx, hmac_opad_buffer,
- HMAC_BLOCK_LEN - ii->ii_authkeylen);
+ /* "Old" AH */
+ if ((thash->type == SADB_X_AALG_MD5) || (thash->type == SADB_X_AALG_SHA1))
+ {
+ MALLOC(tdbp->tdb_ictx, u_int8_t *, thash->ctxsize, M_XDATA, M_WAITOK);
+ bzero(tdbp->tdb_ictx, thash->ctxsize);
+ thash->Init(tdbp->tdb_ictx);
+ thash->Update(tdbp->tdb_ictx, tdbp->tdb_amxkey, tdbp->tdb_amxkeylen);
+ thash->Final(NULL, tdbp->tdb_ictx);
+ }
+ else /* HMAC */
+ {
+ /* Precompute the I and O pads of the HMAC */
+ for (i = 0; i < ii->ii_authkeylen; i++)
+ ii->ii_authkey[i] ^= HMAC_IPAD_VAL;
+
+ MALLOC(tdbp->tdb_ictx, u_int8_t *, thash->ctxsize, M_XDATA, M_WAITOK);
+ bzero(tdbp->tdb_ictx, thash->ctxsize);
+ thash->Init(tdbp->tdb_ictx);
+ thash->Update(tdbp->tdb_ictx, ii->ii_authkey, ii->ii_authkeylen);
+ thash->Update(tdbp->tdb_ictx, hmac_ipad_buffer,
+ HMAC_BLOCK_LEN - ii->ii_authkeylen);
+
+ for (i = 0; i < ii->ii_authkeylen; i++)
+ ii->ii_authkey[i] ^= (HMAC_IPAD_VAL ^ HMAC_OPAD_VAL);
+
+ MALLOC(tdbp->tdb_octx, u_int8_t *, thash->ctxsize, M_XDATA, M_WAITOK);
+ bzero(tdbp->tdb_octx, thash->ctxsize);
+ thash->Init(tdbp->tdb_octx);
+ thash->Update(tdbp->tdb_octx, ii->ii_authkey, ii->ii_authkeylen);
+ thash->Update(tdbp->tdb_octx, hmac_opad_buffer,
+ HMAC_BLOCK_LEN - ii->ii_authkeylen);
+ }
bzero(ipseczeroes, IPSEC_ZEROES_SIZE); /* paranoid */
@@ -164,8 +185,15 @@ ah_new_init(struct tdb *tdbp, struct xformsw *xsp, struct ipsecinit *ii)
/* Free memory */
int
-ah_new_zeroize(struct tdb *tdbp)
+ah_zeroize(struct tdb *tdbp)
{
+ if (tdbp->tdb_amxkey)
+ {
+ bzero(tdbp->tdb_amxkey, tdbp->tdb_amxkeylen);
+ FREE(tdbp->tdb_amxkey, M_XDATA);
+ tdbp->tdb_amxkey = NULL;
+ }
+
if (tdbp->tdb_ictx)
{
if (tdbp->tdb_authalgxform)
@@ -188,20 +216,20 @@ ah_new_zeroize(struct tdb *tdbp)
}
/*
- * ah_new_input() gets called to verify that an input packet
+ * ah_input() gets called to verify that an input packet
* passes authentication
*/
struct mbuf *
-ah_new_input(struct mbuf *m, struct tdb *tdb, int skip, int protoff)
+ah_input(struct mbuf *m, struct tdb *tdb, int skip, int protoff)
{
struct auth_hash *ahx = (struct auth_hash *) tdb->tdb_authalgxform;
- unsigned char calcauth[AH_MAX_HASHLEN];
- int len, count, off, roff;
+ unsigned char calcauth[AH_MAX_HASHLEN], savauth[AH_MAX_HASHLEN];
+ int len, count, off, roff, rplen;
struct mbuf *m0, *m1;
unsigned char *ptr;
union authctx ctx;
- struct ah_new ah;
+ struct ah ah;
#ifdef INET
struct ip ipo;
@@ -213,11 +241,19 @@ ah_new_input(struct mbuf *m, struct tdb *tdb, int skip, int protoff)
int last;
#endif /* INET6 */
+ if (!(tdb->tdb_flags & TDBF_NOREPLAY))
+ rplen = sizeof(u_int32_t);
+ else
+ rplen = 0;
+
/* Save the AH header, we use it throughout */
- m_copydata(m, skip, sizeof(ah), (unsigned char *) &ah);
+ m_copydata(m, skip, AH_FLENGTH + rplen, (unsigned char *) &ah);
- /* Replay window checking */
- if (tdb->tdb_wnd > 0)
+ /* Save the Authenticator too */
+ m_copydata(m, skip + AH_FLENGTH + rplen, ahx->authsize, savauth);
+
+ /* Replay window checking, if applicable */
+ if ((tdb->tdb_wnd > 0) && (!(tdb->tdb_flags & TDBF_NOREPLAY)))
{
switch (checkreplaywindow32(ntohl(ah.ah_rpl), 0, &(tdb->tdb_rpl),
tdb->tdb_wnd, &(tdb->tdb_bitmap)))
@@ -226,20 +262,20 @@ ah_new_input(struct mbuf *m, struct tdb *tdb, int skip, int protoff)
break;
case 1:
- DPRINTF(("ah_new_input(): replay counter wrapped for SA %s/%08x\n", ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
+ DPRINTF(("ah_input(): replay counter wrapped for SA %s/%08x\n", ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
ahstat.ahs_wrap++;
m_freem(m);
return NULL;
case 2:
case 3:
- DPRINTF(("ah_new_input(): duplicate packet received in SA %s/%08x\n", ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
+ DPRINTF(("ah_input(): duplicate packet received in SA %s/%08x\n", ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
ahstat.ahs_replay++;
m_freem(m);
return NULL;
default:
- DPRINTF(("ah_new_input(): bogus value from checkreplaywindow32() in SA %s/%08x\n", ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
+ DPRINTF(("ah_input(): bogus value from checkreplaywindow32() in SA %s/%08x\n", ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
ahstat.ahs_replay++;
m_freem(m);
return NULL;
@@ -247,9 +283,9 @@ ah_new_input(struct mbuf *m, struct tdb *tdb, int skip, int protoff)
}
/* Verify AH header length */
- if (ah.ah_hl * sizeof(u_int32_t) != AH_HMAC_HASHLEN + AH_HMAC_RPLENGTH)
+ if (ah.ah_hl * sizeof(u_int32_t) != ahx->authsize + rplen)
{
- DPRINTF(("ah_new_input(): bad authenticator length %d for packet in SA %s/%08x\n", ah.ah_hl * sizeof(u_int32_t), ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
+ DPRINTF(("ah_input(): bad authenticator length %d for packet in SA %s/%08x\n", ah.ah_hl * sizeof(u_int32_t), ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
ahstat.ahs_badauthl++;
m_freem(m);
return NULL;
@@ -293,7 +329,7 @@ ah_new_input(struct mbuf *m, struct tdb *tdb, int skip, int protoff)
m = m_pullup(m, skip);
if (m == NULL)
{
- DPRINTF(("ah_new_input(): m_pullup() failed, SA %s/%08x\n",
+ DPRINTF(("ah_input(): m_pullup() failed, SA %s/%08x\n",
ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
ahstat.ahs_hdrops++;
return NULL;
@@ -308,7 +344,12 @@ ah_new_input(struct mbuf *m, struct tdb *tdb, int skip, int protoff)
ipo.ip_len += skip; /* adjusted in ip_intr() */
HTONS(ipo.ip_len);
HTONS(ipo.ip_id);
- ipo.ip_off = 0;
+
+ if ((ahx->type == SADB_X_AALG_MD5) ||
+ (ahx->type == SADB_X_AALG_SHA1))
+ ipo.ip_off = htons(ipo.ip_off & IP_DF);
+ else
+ ipo.ip_off = 0;
ipo.ip_ttl = 0;
ipo.ip_sum = 0;
@@ -339,7 +380,7 @@ ah_new_input(struct mbuf *m, struct tdb *tdb, int skip, int protoff)
/* Sanity check for zero-length options */
if (ptr[off + 1] == 0)
{
- DPRINTF(("ah_new_input(): illegal zero-length IPv4 option %d in SA %s/%08x\n", ptr[off], ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
+ DPRINTF(("ah_input(): illegal zero-length IPv4 option %d in SA %s/%08x\n", ptr[off], ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
ahstat.ahs_hdrops++;
m_freem(m);
return NULL;
@@ -357,7 +398,7 @@ ah_new_input(struct mbuf *m, struct tdb *tdb, int skip, int protoff)
/* Sanity check */
if (off > skip)
{
- DPRINTF(("ah_new_input(): malformed IPv4 options header in SA %s/%08x\n", ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
+ DPRINTF(("ah_input(): malformed IPv4 options header in SA %s/%08x\n", ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
ahstat.ahs_hdrops++;
m_freem(m);
return NULL;
@@ -375,7 +416,7 @@ ah_new_input(struct mbuf *m, struct tdb *tdb, int skip, int protoff)
/* We don't do IPv6 Jumbograms */
if (ip6.ip6_plen == 0)
{
- DPRINTF(("ah_new_input(): unsupported IPv6 jumbogram in SA %s/%08x\n", ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
+ DPRINTF(("ah_input(): unsupported IPv6 jumbogram in SA %s/%08x\n", ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
ahstat.ahs_hdrops++;
m_freem(m);
return NULL;
@@ -433,7 +474,7 @@ ah_new_input(struct mbuf *m, struct tdb *tdb, int skip, int protoff)
if (count + sizeof(struct ip6_ext) > len +
((ip6e->ip6e_len + 1) << 3))
{
- DPRINTF(("ah_new_input(): malformed IPv6 options header in SA %s/%08x\n", ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
+ DPRINTF(("ah_input(): malformed IPv6 options header in SA %s/%08x\n", ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
ahstat.ahs_hdrops++;
m_freem(m);
@@ -470,7 +511,7 @@ ah_new_input(struct mbuf *m, struct tdb *tdb, int skip, int protoff)
/* Sanity check */
if (count > skip - sizeof(struct ip6_hdr))
{
- DPRINTF(("ah_new_input(): malformed IPv6 options header in SA %s/%08x\n", ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
+ DPRINTF(("ah_input(): malformed IPv6 options header in SA %s/%08x\n", ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
ahstat.ahs_hdrops++;
m_freem(m);
@@ -500,7 +541,7 @@ ah_new_input(struct mbuf *m, struct tdb *tdb, int skip, int protoff)
break;
default:
- DPRINTF(("ah_new_input(): unexpected IPv6 header type %d in SA %s/%08x\n", off, ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
+ DPRINTF(("ah_input(): unexpected IPv6 header type %d in SA %s/%08x\n", off, ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
len = skip - sizeof(struct ip6_hdr);
break;
}
@@ -516,7 +557,7 @@ ah_new_input(struct mbuf *m, struct tdb *tdb, int skip, int protoff)
#endif /* INET6 */
default:
- DPRINTF(("ah_new_input(): unsupported protocol family %d in SA %s/%08x\n", ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
+ DPRINTF(("ah_input(): unsupported protocol family %d in SA %s/%08x\n", ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
ahstat.ahs_hdrops++;
m_freem(m);
return NULL;
@@ -528,7 +569,7 @@ ah_new_input(struct mbuf *m, struct tdb *tdb, int skip, int protoff)
if (m1 == NULL)
{
- DPRINTF(("ah_new_input(): bad mbuf chain for packet in SA %s/%08x\n",
+ DPRINTF(("ah_input(): bad mbuf chain for packet in SA %s/%08x\n",
ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
ahstat.ahs_hdrops++;
m_freem(m);
@@ -539,36 +580,36 @@ ah_new_input(struct mbuf *m, struct tdb *tdb, int skip, int protoff)
/* Skip the AH header */
for (len = 0, m0 = m1;
- m0 && (len + m0->m_len <= AH_NEW_FLENGTH + roff);
+ m0 && (len + m0->m_len <= AH_FLENGTH + rplen + ahx->authsize + roff);
m0 = m0->m_next)
len += m0->m_len;
if (m0 == NULL)
{
- DPRINTF(("ah_new_input(): bad mbuf chain for packet in SA %s/%08x\n",
+ DPRINTF(("ah_input(): bad mbuf chain for packet in SA %s/%08x\n",
ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
ahstat.ahs_hdrops++;
m_freem(m);
return NULL;
}
else
- off = (AH_NEW_FLENGTH + roff) - len;
+ off = (AH_FLENGTH + rplen + ahx->authsize + roff) - len;
/* Include the AH header (minus the authenticator) in the computation */
- ahx->Update(&ctx, (unsigned char *) &ah, AH_NEW_FLENGTH - AH_HMAC_HASHLEN);
+ ahx->Update(&ctx, (unsigned char *) &ah, AH_FLENGTH + rplen);
/* All-zeroes for the authenticator */
- ahx->Update(&ctx, ipseczeroes, AH_HMAC_HASHLEN);
+ ahx->Update(&ctx, ipseczeroes, ahx->authsize);
/* Amount of data to be verified */
- len = m->m_pkthdr.len - skip - AH_NEW_FLENGTH;
+ len = m->m_pkthdr.len - skip - AH_FLENGTH - rplen - ahx->authsize;
/* Loop through the mbuf chain computing the HMAC */
while (len > 0)
{
if (m0 == NULL)
{
- DPRINTF(("ah_new_input(): bad mbuf chain for packet in SA %s/%08x\n", ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
+ DPRINTF(("ah_input(): bad mbuf chain for packet in SA %s/%08x\n", ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
ahstat.ahs_hdrops++;
m_freem(m);
return NULL;
@@ -583,23 +624,33 @@ ah_new_input(struct mbuf *m, struct tdb *tdb, int skip, int protoff)
m0 = m0->m_next;
}
- /* Finish HMAC computation */
- ahx->Final(calcauth, &ctx);
- bcopy(tdb->tdb_octx, &ctx, ahx->ctxsize);
- ahx->Update(&ctx, calcauth, ahx->hashsize);
- ahx->Final(calcauth, &ctx);
+ /* Finish computation */
+ if ((ahx->type == SADB_X_AALG_MD5) || (ahx->type == SADB_X_AALG_SHA1))
+ {
+ ahx->Update(&ctx, (unsigned char *) tdb->tdb_amxkey,
+ tdb->tdb_amxkeylen);
+ ahx->Final(calcauth, &ctx);
+ }
+ else
+ {
+ /* Finish HMAC computation */
+ ahx->Final(calcauth, &ctx);
+ bcopy(tdb->tdb_octx, &ctx, ahx->ctxsize);
+ ahx->Update(&ctx, calcauth, ahx->hashsize);
+ ahx->Final(calcauth, &ctx);
+ }
/* Verify */
- if (bcmp(&(ah.ah_data), calcauth, AH_HMAC_HASHLEN))
+ if (bcmp(savauth, calcauth, ahx->authsize))
{
- DPRINTF(("ah_new_input(): authentication failed for packet in SA %s/%08x\n", ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
+ DPRINTF(("ah_input(): authentication failed for packet in SA %s/%08x\n", ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
ahstat.ahs_badauth++;
m_freem(m);
return NULL;
}
/* Fix the Next Protocol field */
- m_copyback(m, protoff, 1, (u_char *) &(ah.ah_nh));
+ m_copyback(m, protoff, sizeof(u_int8_t), (u_char *) &(ah.ah_nh));
/*
* Remove the AH header from the mbuf.
@@ -607,25 +658,27 @@ ah_new_input(struct mbuf *m, struct tdb *tdb, int skip, int protoff)
if (roff == 0)
{
/* The AH header was conveniently at the beginning of the mbuf */
- m_adj(m1, AH_NEW_FLENGTH);
+ m_adj(m1, AH_FLENGTH + rplen + ahx->authsize);
if (!(m1->m_flags & M_PKTHDR))
- m->m_pkthdr.len -= AH_NEW_FLENGTH;
+ m->m_pkthdr.len -= AH_FLENGTH + rplen + ahx->authsize;
}
else
- if (roff + AH_NEW_FLENGTH >= m1->m_len)
+ if (roff + AH_FLENGTH + rplen + ahx->authsize >= m1->m_len)
{
/*
* Part or all of the AH header is at the end of this mbuf, so first
* let's remove the remainder of the AH header from the
* beginning of the remainder of the mbuf chain, if any.
*/
- if (roff + AH_NEW_FLENGTH > m1->m_len)
+ if (roff + AH_FLENGTH + rplen + ahx->authsize > m1->m_len)
{
/* Adjust the next mbuf by the remainder */
- m_adj(m1->m_next, roff + AH_NEW_FLENGTH - m1->m_len);
+ m_adj(m1->m_next, roff + AH_FLENGTH + rplen +
+ ahx->authsize - m1->m_len);
/* The second mbuf is guaranteed not to have a pkthdr... */
- m->m_pkthdr.len -= (roff + AH_NEW_FLENGTH - m1->m_len);
+ m->m_pkthdr.len -= (roff + AH_FLENGTH + rplen +
+ ahx->authsize - m1->m_len);
}
/* Now, let's unlink the mbuf chain for a second...*/
@@ -647,27 +700,27 @@ ah_new_input(struct mbuf *m, struct tdb *tdb, int skip, int protoff)
* overlapping copy of the remainder of the mbuf over the ESP
* header.
*/
- bcopy(mtod(m1, u_char *) + roff + AH_NEW_FLENGTH,
+ bcopy(mtod(m1, u_char *) + roff + AH_FLENGTH + rplen + ahx->authsize,
mtod(m1, u_char *) + roff,
- m1->m_len - (roff + AH_NEW_FLENGTH));
- m1->m_len -= AH_NEW_FLENGTH;
- m->m_pkthdr.len -= AH_NEW_FLENGTH;
+ m1->m_len - (roff + AH_FLENGTH + rplen + ahx->authsize));
+ m1->m_len -= AH_FLENGTH + rplen + ahx->authsize;
+ m->m_pkthdr.len -= AH_FLENGTH + rplen + ahx->authsize;
}
return m;
}
int
-ah_new_output(struct mbuf *m, struct tdb *tdb, struct mbuf **mp, int skip,
+ah_output(struct mbuf *m, struct tdb *tdb, struct mbuf **mp, int skip,
int protoff)
{
struct auth_hash *ahx = (struct auth_hash *) tdb->tdb_authalgxform;
unsigned char calcauth[AH_MAX_HASHLEN];
- int len, off, count;
+ int len, off, count, rplen;
unsigned char *ptr;
- struct ah_new *ah;
union authctx ctx;
struct mbuf *mo;
+ struct ah *ah;
#ifdef INET
struct ip ipo;
@@ -679,28 +732,74 @@ ah_new_output(struct mbuf *m, struct tdb *tdb, struct mbuf **mp, int skip,
int last;
#endif /* INET6 */
+#if NBPFILTER > 0
+ {
+ struct ifnet *ifn;
+ struct enchdr hdr;
+ struct mbuf m1;
+
+ bzero (&hdr, sizeof(hdr));
+
+ hdr.af = tdb->tdb_dst.sa.sa_family;
+ hdr.spi = tdb->tdb_spi;
+ hdr.flags |= M_AUTH;
+
+ m1.m_next = m;
+ m1.m_len = ENC_HDRLEN;
+ m1.m_data = (char *) &hdr;
+
+ if (tdb->tdb_interface)
+ ifn = (struct ifnet *) tdb->tdb_interface;
+ else
+ ifn = &(encif[0].sc_if);
+
+ if (ifn->if_bpf)
+ bpf_mtap(ifn->if_bpf, &m1);
+ }
+#endif
+
ahstat.ahs_output++;
/* Check for replay counter wrap-around in automatic (not manual) keying */
- if ((tdb->tdb_rpl == 0) && (tdb->tdb_wnd > 0))
+ if ((tdb->tdb_rpl == 0) && (tdb->tdb_wnd > 0) &&
+ (!(tdb->tdb_flags & TDBF_NOREPLAY)))
{
- DPRINTF(("ah_new_output(): SA %s/%08x should have expired\n",
+ DPRINTF(("ah_output(): SA %s/%08x should have expired\n",
ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
m_freem(m);
ahstat.ahs_wrap++;
return NULL;
}
+ if (!(tdb->tdb_flags & TDBF_NOREPLAY))
+ rplen = sizeof(u_int32_t);
+ else
+ rplen = 0;
+
#ifdef INET
- if (AH_NEW_FLENGTH + m->m_pkthdr.len > IP_MAXPACKET)
+ if ((tdb->tdb_dst.sa.sa_family == AF_INET) &&
+ (AH_FLENGTH + rplen + ahx->authsize + m->m_pkthdr.len > IP_MAXPACKET))
{
- DPRINTF(("ah_new_output(): packet in SA %s/%08x got too big\n",
+ DPRINTF(("ah_output(): packet in SA %s/%08x got too big\n",
ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
m_freem(m);
ahstat.ahs_toobig++;
return EMSGSIZE;
}
-#endif /* INET */
+#endif /* INET */
+
+#ifdef INET6
+ if ((tdb->tdb_dst.sa.sa_family == AF_INET6) &&
+ (AH_FLENGTH + rplen + ahx->authsize + m->m_pkthdr.len >
+ IPV6_MAXPACKET))
+ {
+ DPRINTF(("ah_output(): packet in SA %s/%08x got too big\n",
+ ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
+ m_freem(m);
+ ahstat.ahs_toobig++;
+ return EMSGSIZE;
+ }
+#endif /* INET6 */
/* Update the counters */
tdb->tdb_cur_bytes += m->m_pkthdr.len - skip;
@@ -776,7 +875,7 @@ ah_new_output(struct mbuf *m, struct tdb *tdb, struct mbuf **mp, int skip,
m = m_pullup(m, skip);
if (m == NULL)
{
- DPRINTF(("ah_new_output(): m_pullup() failed, SA %s/%08x\n",
+ DPRINTF(("ah_output(): m_pullup() failed, SA %s/%08x\n",
ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
ahstat.ahs_hdrops++;
return ENOBUFS;
@@ -788,11 +887,16 @@ ah_new_output(struct mbuf *m, struct tdb *tdb, struct mbuf **mp, int skip,
sizeof(struct ip));
ipo.ip_tos = 0;
- ipo.ip_off = 0;
+ if ((ahx->type == SADB_X_AALG_MD5) ||
+ (ahx->type == SADB_X_AALG_SHA1))
+ ipo.ip_off = htons(ntohs(ipo.ip_off) & IP_DF);
+ else
+ ipo.ip_off = 0;
ipo.ip_ttl = 0;
ipo.ip_sum = 0;
ipo.ip_p = IPPROTO_AH;
- ipo.ip_len = htons(ntohs(ipo.ip_len) + AH_NEW_FLENGTH);
+ ipo.ip_len = htons(ntohs(ipo.ip_len) + AH_FLENGTH + rplen +
+ ahx->authsize);
/*
* If we have a loose or strict routing option, we are
@@ -815,7 +919,7 @@ ah_new_output(struct mbuf *m, struct tdb *tdb, struct mbuf **mp, int skip,
if ((ptr[off] != IPOPT_EOL) && (ptr[off] != IPOPT_NOP) &&
(ptr[off + 1] == 0))
{
- DPRINTF(("ah_new_output(): illegal zero-length IPv4 option %d in SA %s/%08x\n", ptr[off], ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
+ DPRINTF(("ah_output(): illegal zero-length IPv4 option %d in SA %s/%08x\n", ptr[off], ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
ahstat.ahs_hdrops++;
m_freem(m);
return EMSGSIZE;
@@ -828,7 +932,7 @@ ah_new_output(struct mbuf *m, struct tdb *tdb, struct mbuf **mp, int skip,
/* Sanity check for length */
if (ptr[off + 1] < 2 + sizeof(struct in_addr))
{
- DPRINTF(("ah_new_output(): malformed LSRR or SSRR IPv4 option header in SA %s/%08x\n", ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
+ DPRINTF(("ah_output(): malformed LSRR or SSRR IPv4 option header in SA %s/%08x\n", ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
ahstat.ahs_hdrops++;
m_freem(m);
return EMSGSIZE;
@@ -856,7 +960,7 @@ ah_new_output(struct mbuf *m, struct tdb *tdb, struct mbuf **mp, int skip,
/* Sanity check */
if (off > skip)
{
- DPRINTF(("ah_new_output(): malformed IPv4 options header in SA %s/%08x\n", ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
+ DPRINTF(("ah_output(): malformed IPv4 options header in SA %s/%08x\n", ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
ahstat.ahs_hdrops++;
m_freem(m);
return EMSGSIZE;
@@ -900,7 +1004,7 @@ ah_new_output(struct mbuf *m, struct tdb *tdb, struct mbuf **mp, int skip,
/* Sanity check */
if (off > skip)
{
- DPRINTF(("ah_new_output(): malformed IPv4 options header in SA %s/%08x\n", ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
+ DPRINTF(("ah_output(): malformed IPv4 options header in SA %s/%08x\n", ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
ahstat.ahs_hdrops++;
m_freem(m);
return EMSGSIZE;
@@ -917,7 +1021,7 @@ ah_new_output(struct mbuf *m, struct tdb *tdb, struct mbuf **mp, int skip,
/* We don't do IPv6 Jumbograms */
if (ip6.ip6_plen == 0)
{
- DPRINTF(("ah_new_output(): unsupported IPv6 jumbogram in SA %s/%08x\n", ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
+ DPRINTF(("ah_output(): unsupported IPv6 jumbogram in SA %s/%08x\n", ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
ahstat.ahs_hdrops++;
m_freem(m);
return EMSGSIZE;
@@ -983,7 +1087,7 @@ ah_new_output(struct mbuf *m, struct tdb *tdb, struct mbuf **mp, int skip,
if (count + sizeof(struct ip6_ext) > len +
((ip6e->ip6e_len + 1) << 3))
{
- DPRINTF(("ah_new_output(): malformed IPv6 options header in SA %s/%08x\n", ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
+ DPRINTF(("ah_output(): malformed IPv6 options header in SA %s/%08x\n", ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
ahstat.ahs_hdrops++;
m_freem(m);
@@ -1014,7 +1118,7 @@ ah_new_output(struct mbuf *m, struct tdb *tdb, struct mbuf **mp, int skip,
/* Sanity check */
if (count > skip - sizeof(struct ip6_hdr))
{
- DPRINTF(("ah_new_output(): malformed IPv6 options header in SA %s/%08x\n", ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
+ DPRINTF(("ah_output(): malformed IPv6 options header in SA %s/%08x\n", ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
ahstat.ahs_hdrops++;
m_freem(m);
@@ -1052,17 +1156,17 @@ ah_new_output(struct mbuf *m, struct tdb *tdb, struct mbuf **mp, int skip,
#endif /* INET6 */
default:
- DPRINTF(("ah_new_output(): unsupported protocol family %d in SA %s/%08x\n", ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
+ DPRINTF(("ah_output(): unsupported protocol family %d in SA %s/%08x\n", ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
ahstat.ahs_nopf++;
m_freem(m);
return EPFNOSUPPORT;
}
/* Inject AH header */
- (*mp) = m_inject(m, skip, AH_NEW_FLENGTH, M_WAITOK);
+ (*mp) = m_inject(m, skip, AH_FLENGTH + rplen + ahx->authsize, M_WAITOK);
if ((*mp) == NULL)
{
- DPRINTF(("ah_new_output(): failed to inject AH header for SA %s/%08x\n", ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
+ DPRINTF(("ah_output(): failed to inject AH header for SA %s/%08x\n", ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
m_freem(m);
ahstat.ahs_wrap++;
return ENOBUFS;
@@ -1072,32 +1176,34 @@ ah_new_output(struct mbuf *m, struct tdb *tdb, struct mbuf **mp, int skip,
* The AH header is guaranteed by m_inject() to be in contiguous memory,
* at the beginning of the returned mbuf.
*/
- ah = mtod((*mp), struct ah_new *);
+ ah = mtod((*mp), struct ah *);
/* Initialize the AH header */
- m_copydata(m, protoff, 1, &(ah->ah_nh)); /* Save Next Protocol field */
- ah->ah_hl = ((AH_HMAC_RPLENGTH + AH_HMAC_HASHLEN) >> 2);
+ m_copydata(m, protoff, sizeof(u_int8_t), (caddr_t) &ah->ah_nh);
+ ah->ah_hl = (rplen + ahx->authsize) / sizeof(u_int32_t);
ah->ah_rv = 0;
ah->ah_spi = tdb->tdb_spi;
- ah->ah_rpl = htonl(tdb->tdb_rpl++);
+
+ if (!(tdb->tdb_flags & TDBF_NOREPLAY))
+ ah->ah_rpl = htonl(tdb->tdb_rpl++);
/* Update the Next Protocol field in the IP header */
len = IPPROTO_AH;
- m_copyback(m, protoff, 1, (unsigned char *) &len);
+ m_copyback(m, protoff, sizeof(u_int8_t), (caddr_t) &len);
/* Include the header AH in the authenticator computation */
- ahx->Update(&ctx, (unsigned char *) ah, AH_NEW_FLENGTH - AH_HMAC_HASHLEN);
- ahx->Update(&ctx, ipseczeroes, AH_HMAC_HASHLEN);
+ ahx->Update(&ctx, (unsigned char *) ah, AH_FLENGTH + rplen);
+ ahx->Update(&ctx, ipseczeroes, ahx->authsize);
/* Calculate the authenticator over the rest of the packet */
- len = m->m_pkthdr.len - (skip + AH_NEW_FLENGTH);
- off = AH_NEW_FLENGTH;
+ len = m->m_pkthdr.len - (skip + AH_FLENGTH + rplen + ahx->authsize);
+ off = AH_FLENGTH + rplen + ahx->authsize;
while (len > 0)
{
if ((*mp) == 0)
{
- DPRINTF(("ah_new_output(): bad mbuf chain for packet in SA %s/%08x\n", ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
+ DPRINTF(("ah_output(): bad mbuf chain for packet in SA %s/%08x\n", ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
ahstat.ahs_hdrops++;
m_freem(m);
(*mp) = NULL;
@@ -1113,14 +1219,21 @@ ah_new_output(struct mbuf *m, struct tdb *tdb, struct mbuf **mp, int skip,
(*mp) = (*mp)->m_next;
}
- /* Finish computing the authenticator */
- ahx->Final(calcauth, &ctx);
- bcopy(tdb->tdb_octx, &ctx, ahx->ctxsize);
- ahx->Update(&ctx, calcauth, ahx->hashsize);
+ if ((ahx->type == SADB_X_AALG_MD5) || (ahx->type == SADB_X_AALG_SHA1))
+ ahx->Update(&ctx, (unsigned char *) tdb->tdb_amxkey,
+ tdb->tdb_amxkeylen);
+ else
+ {
+ /* HMAC */
+ ahx->Final(calcauth, &ctx);
+ bcopy(tdb->tdb_octx, &ctx, ahx->ctxsize);
+ ahx->Update(&ctx, calcauth, ahx->hashsize);
+ }
+
ahx->Final(calcauth, &ctx);
/* Copy the authenticator */
- bcopy(calcauth, ah->ah_data, AH_HMAC_HASHLEN);
+ bcopy(calcauth, ((caddr_t) ah) + AH_FLENGTH + rplen, ahx->authsize);
*mp = m;
diff --git a/sys/netinet/ip_ah.h b/sys/netinet/ip_ah.h
index be7f3a2be65..1938abad340 100644
--- a/sys/netinet/ip_ah.h
+++ b/sys/netinet/ip_ah.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_ah.h,v 1.23 2000/01/13 05:03:45 angelos Exp $ */
+/* $OpenBSD: ip_ah.h,v 1.24 2000/01/27 08:09:08 angelos Exp $ */
/*
* The authors of this code are John Ioannidis (ji@tla.org),
@@ -35,25 +35,9 @@
* PURPOSE.
*/
-/*
- * Authentication Header Processing
- * Per RFC1826 (Atkinson, 1995)
- */
-
#ifndef _NETINET_AH_H_
#define _NETINET_AH_H_
-struct ah_old
-{
- u_int8_t ah_nh; /* Next header (protocol) */
- u_int8_t ah_hl; /* AH length, in 32-bit words */
- u_int16_t ah_rv; /* reserved, must be 0 */
- u_int32_t ah_spi; /* Security Parameters Index */
- u_int8_t ah_data[1]; /* More, really */
-};
-
-#define AH_OLD_FLENGTH 8 /* size of fixed part */
-
struct ahstat
{
u_int32_t ahs_hdrops; /* packet shorter than header shows */
@@ -75,17 +59,17 @@ struct ahstat
u_int32_t ahs_pdrops; /* packet blocked due to policy */
};
-struct ah_new
+struct ah
{
- u_int8_t ah_nh; /* Next header (protocol) */
- u_int8_t ah_hl; /* AH length, in 32-bit words */
- u_int16_t ah_rv; /* reserved, must be 0 */
- u_int32_t ah_spi; /* Security Parameters Index */
- u_int32_t ah_rpl; /* Replay prevention */
- u_int8_t ah_data[AH_HMAC_HASHLEN];/* Authenticator */
+ u_int8_t ah_nh;
+ u_int8_t ah_hl;
+ u_int16_t ah_rv;
+ u_int32_t ah_spi;
+ u_int32_t ah_rpl; /* We may not use this, if we're using old xforms */
};
-#define AH_NEW_FLENGTH (sizeof(struct ah_new))
+/* Length of base AH header */
+#define AH_FLENGTH 8
/* Size of the largest hash function output used in AH-new, in bytes */
#define AH_MAX_HASHLEN 20
@@ -102,14 +86,6 @@ struct ah_new
}
#ifdef _KERNEL
-void ah_input __P((struct mbuf *, ...));
-int ah_output __P((struct mbuf *, struct tdb *, struct mbuf **));
-int ah_sysctl __P((int *, u_int, void *, size_t *, void *, size_t));
-
-#ifdef INET6
-int ah6_input __P((struct mbuf **, int *, int));
-#endif /* INET6 */
-
extern int ah_enable;
struct ahstat ahstat;
#endif /* _KERNEL */
diff --git a/sys/netinet/ip_ah_old.c b/sys/netinet/ip_ah_old.c
deleted file mode 100644
index 8e2a6f62458..00000000000
--- a/sys/netinet/ip_ah_old.c
+++ /dev/null
@@ -1,589 +0,0 @@
-/* $OpenBSD: ip_ah_old.c,v 1.26 1999/12/06 07:14:35 angelos Exp $ */
-
-/*
- * The authors of this code are John Ioannidis (ji@tla.org),
- * Angelos D. Keromytis (kermit@csd.uch.gr) and
- * Niels Provos (provos@physnet.uni-hamburg.de).
- *
- * This code was written by John Ioannidis for BSD/OS in Athens, Greece,
- * in November 1995.
- *
- * Ported to OpenBSD and NetBSD, with additional transforms, in December 1996,
- * by Angelos D. Keromytis.
- *
- * Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis
- * and Niels Provos.
- *
- * Additional features in 1999 by Angelos D. Keromytis.
- *
- * Copyright (C) 1995, 1996, 1997, 1998, 1999 by John Ioannidis,
- * Angelos D. Keromytis and Niels Provos.
- *
- * Permission to use, copy, and modify this software without fee
- * is hereby granted, provided that this entire notice is included in
- * all copies of any software which is or includes a copy or
- * modification of this software.
- * You may use this code under the GNU public license if you so wish. Please
- * contribute changes back to the authors under this freer than GPL license
- * so that we may further the use of strong encryption without limitations to
- * all.
- *
- * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY
- * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE
- * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
- * PURPOSE.
- */
-
-/*
- * Authentication Header Processing
- * Per RFCs 1828/1852 (Metzger & Simpson)
- */
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/malloc.h>
-#include <sys/mbuf.h>
-#include <sys/domain.h>
-#include <sys/protosw.h>
-#include <sys/socket.h>
-#include <sys/errno.h>
-#include <sys/time.h>
-#include <sys/kernel.h>
-#include <machine/cpu.h>
-
-#include <net/if.h>
-#include <net/route.h>
-#include <net/netisr.h>
-
-#include <netinet/in.h>
-#include <netinet/in_systm.h>
-#include <netinet/ip.h>
-#include <netinet/in_pcb.h>
-#include <netinet/in_var.h>
-#include <netinet/ip_var.h>
-#include <netinet/ip_icmp.h>
-
-#include <sys/socketvar.h>
-#include <net/raw_cb.h>
-
-#include <netinet/ip_ipsp.h>
-#include <netinet/ip_ah.h>
-#include <net/pfkeyv2.h>
-
-#ifdef ENCDEBUG
-#define DPRINTF(x) if (encdebug) printf x
-#else
-#define DPRINTF(x)
-#endif
-
-extern struct auth_hash auth_hash_key_md5;
-extern struct auth_hash auth_hash_key_sha1;
-
-struct auth_hash *ah_old_hash[] = {
- &auth_hash_key_md5,
- &auth_hash_key_sha1,
-};
-
-/*
- * ah_old_attach() is called from the transformation initialization code.
- */
-
-int
-ah_old_attach()
-{
- return 0;
-}
-
-/*
- * ah_old_init() is called when an SPI is being set up.
- */
-
-int
-ah_old_init(struct tdb *tdbp, struct xformsw *xsp, struct ipsecinit *ii)
-{
- struct auth_hash *thash = NULL;
- int i;
-
- /* Check whether the hash algorithm is supported */
- for (i = sizeof(ah_old_hash) / sizeof(ah_old_hash[0]) - 1; i >= 0; i--)
- if (ii->ii_authalg == ah_old_hash[i]->type)
- break;
-
- if (i < 0)
- {
- DPRINTF(("ah_old_init(): unsupported authentication algorithm %d specified\n", ii->ii_authalg));
- return EINVAL;
- }
-
- thash = ah_old_hash[i];
-
- DPRINTF(("ah_old_init(): initalized TDB with hash algorithm %s\n",
- thash->name));
-
- tdbp->tdb_xform = xsp;
- tdbp->tdb_authalgxform = thash;
-
- tdbp->tdb_amxkeylen = ii->ii_authkeylen;
- MALLOC(tdbp->tdb_amxkey, u_int8_t *, tdbp->tdb_amxkeylen,
- M_XDATA, M_WAITOK);
-
- bcopy(ii->ii_authkey, tdbp->tdb_amxkey, tdbp->tdb_amxkeylen);
-
- MALLOC(tdbp->tdb_ictx, u_int8_t *, thash->ctxsize, M_XDATA, M_WAITOK);
- bzero(tdbp->tdb_ictx, thash->ctxsize);
- thash->Init(tdbp->tdb_ictx);
- thash->Update(tdbp->tdb_ictx, tdbp->tdb_amxkey, tdbp->tdb_amxkeylen);
- thash->Final(NULL, tdbp->tdb_ictx);
-
- bzero(ipseczeroes, IPSEC_ZEROES_SIZE); /* paranoid */
-
- return 0;
-}
-
-/*
- * Free memory
- */
-
-int
-ah_old_zeroize(struct tdb *tdbp)
-{
- if (tdbp->tdb_amxkey)
- {
- bzero(tdbp->tdb_amxkey, tdbp->tdb_amxkeylen);
- FREE(tdbp->tdb_amxkey, M_XDATA);
- tdbp->tdb_amxkey = NULL;
- }
-
- if (tdbp->tdb_ictx)
- {
- if (tdbp->tdb_authalgxform)
- bzero(tdbp->tdb_ictx, tdbp->tdb_authalgxform->ctxsize);
-
- FREE(tdbp->tdb_ictx, M_XDATA);
- tdbp->tdb_ictx = NULL;
- }
-
- return 0;
-}
-
-/*
- * ah_old_input() gets called to verify that an input packet
- * passes authentication.
- */
-
-struct mbuf *
-ah_old_input(struct mbuf *m, struct tdb *tdb, int skip, int protoff)
-{
- struct auth_hash *ahx = (struct auth_hash *) tdb->tdb_authalgxform;
- struct ip *ip, ipo;
- struct ah_old *ah, *aho;
- int ohlen, len, count, off, alen;
- struct mbuf *m0;
- union authctx_old ctx;
- u_int8_t optval;
- u_char buffer[40];
-
- aho = (struct ah_old *) buffer;
- alen = ahx->hashsize;
- ohlen = sizeof(struct ip) + AH_OLD_FLENGTH + alen;
-
- if (m->m_len < ohlen)
- {
- if ((m = m_pullup(m, ohlen)) == NULL)
- {
- DPRINTF(("ah_old_input(): m_pullup() failed\n"));
- ahstat.ahs_hdrops++;
- return NULL;
- }
- }
-
- ip = mtod(m, struct ip *);
-
- if ((ip->ip_hl << 2) > sizeof(struct ip))
- {
- if ((m = m_pullup(m, ohlen - sizeof (struct ip) +
- (ip->ip_hl << 2))) == NULL)
- {
- DPRINTF(("ah_old_input(): m_pullup() failed\n"));
- ahstat.ahs_hdrops++;
- return NULL;
- }
-
- ip = mtod(m, struct ip *);
- ah = (struct ah_old *)((u_int8_t *) ip + (ip->ip_hl << 2));
- ohlen += ((ip->ip_hl << 2) - sizeof(struct ip));
- }
- else
- ah = (struct ah_old *) (ip + 1);
-
- /* Update the counters */
- tdb->tdb_cur_bytes += ip->ip_len - (ip->ip_hl << 2);
- ahstat.ahs_ibytes += ip->ip_len - (ip->ip_hl << 2);
-
- /* Hard expiration */
- if ((tdb->tdb_flags & TDBF_BYTES) &&
- (tdb->tdb_cur_bytes >= tdb->tdb_exp_bytes))
- {
- pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_HARD);
- m_freem(m);
- tdb_delete(tdb, 0, TDBEXP_TIMEOUT);
- return NULL;
- }
-
- /* Notify on expiration */
- if ((tdb->tdb_flags & TDBF_SOFT_BYTES) &&
- (tdb->tdb_cur_bytes >= tdb->tdb_soft_bytes))
- {
- pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_SOFT);
- tdb->tdb_flags &= ~TDBF_SOFT_BYTES; /* Turn off checking */
- }
-
- ipo = *ip;
- ipo.ip_tos = 0;
- ipo.ip_len += (ip->ip_hl << 2); /* adjusted in ip_intr() */
- HTONS(ipo.ip_len);
- HTONS(ipo.ip_id);
- ipo.ip_off = htons(ipo.ip_off & IP_DF); /* XXX -- and the C bit? */
- ipo.ip_ttl = 0;
- ipo.ip_sum = 0;
-
- bcopy(tdb->tdb_ictx, &ctx, ahx->ctxsize);
- ahx->Update(&ctx, (unsigned char *) &ipo, sizeof(struct ip));
-
- /* Options */
- if ((ip->ip_hl << 2) > sizeof(struct ip))
- for (off = sizeof(struct ip); off < (ip->ip_hl << 2);)
- {
- optval = ((u_int8_t *) ip)[off];
- switch (optval)
- {
- case IPOPT_EOL:
- ahx->Update(&ctx, ipseczeroes, 1);
-
- off = ip->ip_hl << 2;
- break;
-
- case IPOPT_NOP:
- ahx->Update(&ctx, ipseczeroes, 1);
-
- off++;
- break;
-
- case IPOPT_SECURITY:
- case 133:
- case 134:
- optval = ((u_int8_t *) ip)[off + 1];
-
- ahx->Update(&ctx, (u_int8_t *) ip + off, optval);
-
- off += optval;
- break;
-
- default:
- optval = ((u_int8_t *) ip)[off + 1];
-
- ahx->Update(&ctx, ipseczeroes, optval);
-
- off += optval;
- break;
- }
- }
-
-
- ahx->Update(&ctx, (unsigned char *) ah, AH_OLD_FLENGTH);
- ahx->Update(&ctx, ipseczeroes, alen);
-
- /*
- * Code shamelessly stolen from m_copydata
- */
- off = ohlen;
- len = m->m_pkthdr.len - off;
- m0 = m;
-
- while (off > 0)
- {
- if (m0 == 0)
- {
- DPRINTF(("ah_old_input(): bad mbuf chain for packet from %s to %s, spi %08x\n", inet_ntoa4(ipo.ip_src), inet_ntoa4(ipo.ip_dst), ntohl(tdb->tdb_spi)));
- ahstat.ahs_hdrops++;
- m_freem(m);
- return NULL;
- }
-
- if (off < m0->m_len)
- break;
-
- off -= m0->m_len;
- m0 = m0->m_next;
- }
-
- while (len > 0)
- {
- if (m0 == 0)
- {
- DPRINTF(("ah_old_input(): bad mbuf chain for packet from %s to %s, spi %08x\n", inet_ntoa4(ipo.ip_src), inet_ntoa4(ipo.ip_dst), ntohl(tdb->tdb_spi)));
- ahstat.ahs_hdrops++;
- m_freem(m);
- return NULL;
- }
-
- count = min(m0->m_len - off, len);
-
- ahx->Update(&ctx, mtod(m0, unsigned char *) + off, count);
-
- len -= count;
- off = 0;
- m0 = m0->m_next;
- }
-
- ahx->Update(&ctx, (unsigned char *) tdb->tdb_amxkey, tdb->tdb_amxkeylen);
- ahx->Final((unsigned char *) (aho->ah_data), &ctx);
-
- if (bcmp(aho->ah_data, ah->ah_data, alen))
- {
- ahstat.ahs_badauth++;
- m_freem(m);
- return NULL;
- }
-
- ipo = *ip;
- ipo.ip_p = ah->ah_nh;
-
- /* Save options */
- m_copydata(m, sizeof(struct ip), (ip->ip_hl << 2) - sizeof(struct ip),
- (caddr_t) buffer);
-
- m->m_len -= (AH_OLD_FLENGTH + alen);
- m->m_data += (AH_OLD_FLENGTH + alen);
- m->m_pkthdr.len -= (AH_OLD_FLENGTH + alen);
-
- ip = mtod(m, struct ip *);
- *ip = ipo;
- ip->ip_len = htons(ip->ip_len - AH_OLD_FLENGTH - alen + (ip->ip_hl << 2));
- HTONS(ip->ip_id);
- HTONS(ip->ip_off);
- ip->ip_sum = 0;
-
- /* Copy the options back */
- m_copyback(m, sizeof(struct ip), (ip->ip_hl << 2) - sizeof(struct ip),
- (caddr_t) buffer);
-
- ip->ip_sum = in_cksum(m, (ip->ip_hl << 2));
-
- return m;
-}
-
-int
-ah_old_output(struct mbuf *m, struct tdb *tdb, struct mbuf **mp, int skip,
- int protoff)
-{
- struct auth_hash *ahx = (struct auth_hash *) tdb->tdb_authalgxform;
- struct ip *ip, ipo;
- struct ah_old *ah, aho;
- register int len, off, count;
- register struct mbuf *m0;
- union authctx_old ctx;
- int ilen, ohlen, alen;
- u_int8_t optval;
- u_char opts[40];
-
- alen = ahx->hashsize;
-
- ahstat.ahs_output++;
- m = m_pullup(m, sizeof(struct ip));
- if (m == NULL)
- {
- DPRINTF(("ah_old_output(): m_pullup() failed, SA %s/%08x\n",
- ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
- ahstat.ahs_hdrops++;
- return ENOBUFS;
- }
-
- ip = mtod(m, struct ip *);
-
- /* Update the counters */
- tdb->tdb_cur_bytes += ntohs(ip->ip_len) - (ip->ip_hl << 2) -
- AH_OLD_FLENGTH - alen;
- ahstat.ahs_obytes += ntohs(ip->ip_len) - (ip->ip_hl << 2) -
- AH_OLD_FLENGTH - alen;
-
- /* Hard expiration */
- if ((tdb->tdb_flags & TDBF_BYTES) &&
- (tdb->tdb_cur_bytes >= tdb->tdb_exp_bytes))
- {
- pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_HARD);
- tdb_delete(tdb, 0, TDBEXP_TIMEOUT);
- m_freem(m);
- return EINVAL;
- }
-
- /* Notify on expiration */
- if ((tdb->tdb_flags & TDBF_SOFT_BYTES) &&
- (tdb->tdb_cur_bytes >= tdb->tdb_soft_bytes))
- {
- pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_SOFT);
- tdb->tdb_flags &= ~TDBF_SOFT_BYTES; /* Turn off checking */
- }
-
- if ((ip->ip_hl << 2) > sizeof(struct ip))
- {
- if ((m = m_pullup(m, ip->ip_hl << 2)) == NULL)
- {
- DPRINTF(("ah_old_output(): m_pullup() failed, SA %s/%08x\n",
- ipsp_address(tdb->tdb_dst),
- ntohl(tdb->tdb_spi)));
- ahstat.ahs_hdrops++;
- return ENOBUFS;
- }
-
- ip = mtod(m, struct ip *);
- }
-
- /* Save the options */
- m_copydata(m, sizeof(struct ip), (ip->ip_hl << 2) - sizeof(struct ip),
- (caddr_t) opts);
-
- ilen = ntohs(ip->ip_len);
-
- ohlen = AH_OLD_FLENGTH + alen;
- if (ohlen + ilen > IP_MAXPACKET)
- {
- DPRINTF(("ah_old_output(): packet in SA %s/%0x8 got too big\n",
- ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
- m_freem(m);
- ahstat.ahs_toobig++;
- return EMSGSIZE;
- }
-
- ipo.ip_v = IPVERSION;
- ipo.ip_hl = ip->ip_hl;
- ipo.ip_tos = 0;
- ipo.ip_len = htons(ohlen + ilen);
- ipo.ip_id = ip->ip_id;
- ipo.ip_off = htons(ntohs(ip->ip_off) & IP_DF);
- ipo.ip_ttl = 0;
- ipo.ip_p = IPPROTO_AH;
- ipo.ip_sum = 0;
- ipo.ip_src = ip->ip_src;
- ipo.ip_dst = ip->ip_dst;
-
- aho.ah_nh = ip->ip_p;
- aho.ah_hl = alen >> 2;
- aho.ah_rv = 0;
- aho.ah_spi = tdb->tdb_spi;
-
- bcopy(tdb->tdb_ictx, &ctx, ahx->ctxsize);
- ahx->Update(&ctx, (unsigned char *) &ipo, sizeof(struct ip));
-
- /* Options */
- if ((ip->ip_hl << 2) > sizeof(struct ip))
- for (off = sizeof(struct ip); off < (ip->ip_hl << 2);)
- {
- optval = ((u_int8_t *) ip)[off];
- switch (optval)
- {
- case IPOPT_EOL:
- ahx->Update(&ctx, ipseczeroes, 1);
-
- off = ip->ip_hl << 2;
- break;
-
- case IPOPT_NOP:
- ahx->Update(&ctx, ipseczeroes, 1);
-
- off++;
- break;
-
- case IPOPT_SECURITY:
- case 133:
- case 134:
- optval = ((u_int8_t *) ip)[off + 1];
-
- ahx->Update(&ctx, (u_int8_t *) ip + off, optval);
-
- off += optval;
- break;
-
- default:
- optval = ((u_int8_t *) ip)[off + 1];
-
- ahx->Update(&ctx, ipseczeroes, optval);
-
- off += optval;
- break;
- }
- }
-
- ahx->Update(&ctx, (unsigned char *) &aho, AH_OLD_FLENGTH);
- ahx->Update(&ctx, ipseczeroes, alen);
-
- /* Skip the IP header and any options */
- off = ip->ip_hl << 2;
-
- /*
- * Code shamelessly stolen from m_copydata
- */
- len = m->m_pkthdr.len - off;
-
- m0 = m;
-
- while (len > 0)
- {
- if (m0 == 0)
- {
- DPRINTF(("ah_old_output(): M_PREPEND() failed for packet from %s to %s, spi %08x\n", inet_ntoa4(ipo.ip_src), inet_ntoa4(ipo.ip_dst), ntohl(tdb->tdb_spi)));
- m_freem(m);
- return NULL;
- }
-
- count = min(m0->m_len - off, len);
-
- ahx->Update(&ctx, mtod(m0, unsigned char *) + off, count);
-
- len -= count;
- off = 0;
- m0 = m0->m_next;
- }
-
- ahx->Update(&ctx, (unsigned char *) tdb->tdb_amxkey, tdb->tdb_amxkeylen);
-
- ipo.ip_tos = ip->ip_tos;
- ipo.ip_id = ip->ip_id;
- ipo.ip_off = ip->ip_off;
- ipo.ip_ttl = ip->ip_ttl;
-/* ipo.ip_len = ntohs(ipo.ip_len); */
-
- M_PREPEND(m, ohlen, M_DONTWAIT);
- if (m == NULL)
- {
- DPRINTF(("ah_old_output(): M_PREPEND() failed for packet from %s to %s, spi %08x\n", inet_ntoa4(ipo.ip_src), inet_ntoa4(ipo.ip_dst), ntohl(tdb->tdb_spi)));
- return ENOBUFS;
- }
-
- m = m_pullup(m, ohlen + (ipo.ip_hl << 2));
- if (m == NULL)
- {
- DPRINTF(("ah_old_output(): m_pullup() failed for packet from %s to %s, spi %08x\n", inet_ntoa4(ipo.ip_src), inet_ntoa4(ipo.ip_dst), ntohl(tdb->tdb_spi)));
- ahstat.ahs_hdrops++;
- return ENOBUFS;
- }
-
- ip = mtod(m, struct ip *);
- ah = (struct ah_old *) ((u_int8_t *) ip + (ipo.ip_hl << 2));
- *ip = ipo;
- ah->ah_nh = aho.ah_nh;
- ah->ah_hl = aho.ah_hl;
- ah->ah_rv = aho.ah_rv;
- ah->ah_spi = aho.ah_spi;
-
- /* Restore the options */
- m_copyback(m, sizeof(struct ip), (ip->ip_hl << 2) - sizeof(struct ip),
- (caddr_t) opts);
-
- ahx->Final(ah->ah_data, &ctx);
-
- *mp = m;
-
- return 0;
-}
diff --git a/sys/netinet/ip_esp_new.c b/sys/netinet/ip_esp.c
index 7c0d9d7e570..e9cc0356dae 100644
--- a/sys/netinet/ip_esp_new.c
+++ b/sys/netinet/ip_esp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_esp_new.c,v 1.56 1999/12/26 20:46:13 angelos Exp $ */
+/* $OpenBSD: ip_esp.c,v 1.31 2000/01/27 08:09:09 angelos Exp $ */
/*
* The authors of this code are John Ioannidis (ji@tla.org),
@@ -35,10 +35,6 @@
* PURPOSE.
*/
-/*
- * RFC 2406.
- */
-
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/malloc.h>
@@ -54,21 +50,28 @@
#include <net/if.h>
#include <net/route.h>
#include <net/netisr.h>
+#include <net/bpf.h>
+
+#include <sys/socketvar.h>
+#include <net/raw_cb.h>
+#ifdef INET
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
-
-#include <sys/socketvar.h>
-#include <net/raw_cb.h>
+#endif /* INET */
#ifdef INET6
#include <netinet6/in6.h>
+#include <netinet6/ip6.h>
#endif /* INET6 */
#include <netinet/ip_ipsp.h>
#include <netinet/ip_esp.h>
#include <net/pfkeyv2.h>
+#include <net/if_enc.h>
+
+#include "bpfilter.h"
#ifdef ENCDEBUG
#define DPRINTF(x) if (encdebug) printf x
@@ -84,7 +87,7 @@ extern struct auth_hash auth_hash_hmac_md5_96;
extern struct auth_hash auth_hash_hmac_sha1_96;
extern struct auth_hash auth_hash_hmac_ripemd_160_96;
-struct auth_hash *esp_new_hash[] = {
+struct auth_hash *esp_hash[] = {
&auth_hash_hmac_md5_96,
&auth_hash_hmac_sha1_96,
&auth_hash_hmac_ripemd_160_96
@@ -96,7 +99,7 @@ extern struct enc_xform enc_xform_blf;
extern struct enc_xform enc_xform_cast5;
extern struct enc_xform enc_xform_skipjack;
-struct enc_xform *esp_new_xform[] = {
+struct enc_xform *esp_xform[] = {
&enc_xform_des,
&enc_xform_3des,
&enc_xform_blf,
@@ -105,76 +108,76 @@ struct enc_xform *esp_new_xform[] = {
};
/*
- * esp_new_attach() is called from the transformation initialization code.
+ * esp_attach() is called from the transformation initialization code.
*/
int
-esp_new_attach()
+esp_attach()
{
return 0;
}
/*
- * esp_new_init() is called when an SPI is being set up.
+ * esp_init() is called when an SPI is being set up.
*/
int
-esp_new_init(struct tdb *tdbp, struct xformsw *xsp, struct ipsecinit *ii)
+esp_init(struct tdb *tdbp, struct xformsw *xsp, struct ipsecinit *ii)
{
struct enc_xform *txform = NULL;
struct auth_hash *thash = NULL;
int i;
/* Check whether the encryption algorithm is supported */
- for (i = sizeof(esp_new_xform) / sizeof(esp_new_xform[0]) - 1;
+ for (i = sizeof(esp_xform) / sizeof(esp_xform[0]) - 1;
i >= 0; i--)
- if (ii->ii_encalg == esp_new_xform[i]->type)
+ if (ii->ii_encalg == esp_xform[i]->type)
break;
if (i < 0)
{
- DPRINTF(("esp_new_init(): unsupported encryption algorithm %d specified\n", ii->ii_encalg));
+ DPRINTF(("esp_init(): unsupported encryption algorithm %d specified\n", ii->ii_encalg));
return EINVAL;
}
- txform = esp_new_xform[i];
+ txform = esp_xform[i];
if (ii->ii_enckeylen < txform->minkey)
{
- DPRINTF(("esp_new_init(): keylength %d too small (min length is %d) for algorithm %s\n", ii->ii_enckeylen, txform->minkey, txform->name));
+ DPRINTF(("esp_init(): keylength %d too small (min length is %d) for algorithm %s\n", ii->ii_enckeylen, txform->minkey, txform->name));
return EINVAL;
}
if (ii->ii_enckeylen > txform->maxkey)
{
- DPRINTF(("esp_new_init(): keylength %d too large (max length is %d) for algorithm %s\n", ii->ii_enckeylen, txform->maxkey, txform->name));
+ DPRINTF(("esp_init(): keylength %d too large (max length is %d) for algorithm %s\n", ii->ii_enckeylen, txform->maxkey, txform->name));
return EINVAL;
}
if (ii->ii_authalg)
{
- for (i = sizeof(esp_new_hash) / sizeof(esp_new_hash[0]) - 1;
+ for (i = sizeof(esp_hash) / sizeof(esp_hash[0]) - 1;
i >= 0; i--)
- if (ii->ii_authalg == esp_new_hash[i]->type)
+ if (ii->ii_authalg == esp_hash[i]->type)
break;
if (i < 0)
{
- DPRINTF(("esp_new_init(): unsupported authentication algorithm %d specified\n", ii->ii_authalg));
+ DPRINTF(("esp_init(): unsupported authentication algorithm %d specified\n", ii->ii_authalg));
return EINVAL;
}
- thash = esp_new_hash[i];
+ thash = esp_hash[i];
if (ii->ii_authkeylen != thash->keysize)
{
- DPRINTF(("esp_new_init(): keylength %d doesn't match algorithm %s keysize (%d)\n", ii->ii_authkeylen, thash->name, thash->keysize));
+ DPRINTF(("esp_init(): keylength %d doesn't match algorithm %s keysize (%d)\n", ii->ii_authkeylen, thash->name, thash->keysize));
return EINVAL;
}
tdbp->tdb_authalgxform = thash;
- DPRINTF(("esp_new_init(): initialized TDB with hash algorithm %s\n",
+ DPRINTF(("esp_init(): initialized TDB with hash algorithm %s\n",
thash->name));
}
@@ -183,14 +186,27 @@ esp_new_init(struct tdb *tdbp, struct xformsw *xsp, struct ipsecinit *ii)
tdbp->tdb_bitmap = 0;
tdbp->tdb_rpl = AH_HMAC_INITIAL_RPL;
- DPRINTF(("esp_new_init(): initialized TDB with enc algorithm %s\n",
+ DPRINTF(("esp_init(): initialized TDB with enc algorithm %s\n",
txform->name));
tdbp->tdb_ivlen = txform->ivmask;
+ if (tdbp->tdb_flags & TDBF_HALFIV)
+ tdbp->tdb_ivlen /= 2;
/* Initialize the IV */
get_random_bytes(tdbp->tdb_iv, tdbp->tdb_ivlen);
+ /* Save the raw keys */
+ tdbp->tdb_amxkeylen = ii->ii_authkeylen;
+ MALLOC(tdbp->tdb_amxkey, u_int8_t *, tdbp->tdb_amxkeylen, M_XDATA,
+ M_WAITOK);
+ bcopy(ii->ii_authkey, tdbp->tdb_amxkey, tdbp->tdb_amxkeylen);
+
+ tdbp->tdb_emxkeylen = ii->ii_enckeylen;
+ MALLOC(tdbp->tdb_emxkey, u_int8_t *, tdbp->tdb_emxkeylen, M_XDATA,
+ M_WAITOK);
+ bcopy(ii->ii_enckey, tdbp->tdb_emxkey, tdbp->tdb_emxkeylen);
+
if (txform->setkey)
txform->setkey(&tdbp->tdb_key, ii->ii_enckey, ii->ii_enckeylen);
@@ -222,8 +238,22 @@ esp_new_init(struct tdb *tdbp, struct xformsw *xsp, struct ipsecinit *ii)
}
int
-esp_new_zeroize(struct tdb *tdbp)
+esp_zeroize(struct tdb *tdbp)
{
+ if (tdbp->tdb_amxkey)
+ {
+ bzero(tdbp->tdb_amxkey, tdbp->tdb_amxkeylen);
+ FREE(tdbp->tdb_amxkey, M_XDATA);
+ tdbp->tdb_amxkey = NULL;
+ }
+
+ if (tdbp->tdb_emxkey)
+ {
+ bzero(tdbp->tdb_emxkey, tdbp->tdb_emxkeylen);
+ FREE(tdbp->tdb_emxkey, M_XDATA);
+ tdbp->tdb_emxkey = NULL;
+ }
+
if (tdbp->tdb_key && tdbp->tdb_encalgxform &&
tdbp->tdb_encalgxform->zerokey)
tdbp->tdb_encalgxform->zerokey(&tdbp->tdb_key);
@@ -250,18 +280,23 @@ esp_new_zeroize(struct tdb *tdbp)
#define MAXBUFSIZ (AH_ALEN_MAX > ESP_MAX_IVS ? AH_ALEN_MAX : ESP_MAX_IVS)
struct mbuf *
-esp_new_input(struct mbuf *m, struct tdb *tdb, int skip, int protoff)
+esp_input(struct mbuf *m, struct tdb *tdb, int skip, int protoff)
{
struct auth_hash *esph = (struct auth_hash *) tdb->tdb_authalgxform;
struct enc_xform *espx = (struct enc_xform *) tdb->tdb_encalgxform;
- int ohlen, oplen, plen, alen, ilen, i, blks, rest, count, off, roff;
+ int oplen, plen, alen, ilen, i, blks, rest, count, off, roff, hlen;
u_char iv[MAXBUFSIZ], niv[MAXBUFSIZ], blk[ESP_MAX_BLKS], *lblk;
u_char *idat, *odat, *ivp, *ivn;
struct mbuf *mi, *mo, *m1;
union authctx ctx;
u_int32_t btsx;
- ohlen = skip + ESP_NEW_FLENGTH;
+ /* Determine the ESP header length */
+ if (tdb->tdb_flags & TDBF_NOREPLAY)
+ hlen = sizeof(u_int32_t) + tdb->tdb_ivlen; /* "old" ESP */
+ else
+ hlen = 2 * sizeof(u_int32_t) + tdb->tdb_ivlen; /* "new" ESP */
+
blks = espx->blocksize;
if (esph)
@@ -269,25 +304,24 @@ esp_new_input(struct mbuf *m, struct tdb *tdb, int skip, int protoff)
else
alen = 0;
- /* Skip the IP header, IP options, SPI, Replay, IV, and any Auth Data */
- plen = m->m_pkthdr.len - (skip + 2 * sizeof(u_int32_t) + tdb->tdb_ivlen +
- alen);
+ /* Skip the IP header, IP options, SPI, IV, and any Replay and Auth Data */
+ plen = m->m_pkthdr.len - (skip + hlen + alen);
if ((plen & (blks - 1)) || (plen <= 0))
{
- DPRINTF(("esp_new_input(): payload not a multiple of %d octets, SA %s/%08x\n", blks, ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
+ DPRINTF(("esp_input(): payload not a multiple of %d octets, SA %s/%08x\n", blks, ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
espstat.esps_badilen++;
m_freem(m);
return NULL;
}
/* Auth covers SPI + SN + IV */
- oplen = plen + 2 * sizeof(u_int32_t) + tdb->tdb_ivlen;
+ oplen = plen + hlen;
- /* Replay window checking */
- if (tdb->tdb_wnd > 0)
+ /* Replay window checking, if appropriate */
+ if ((tdb->tdb_wnd > 0) && (!(tdb->tdb_flags & TDBF_NOREPLAY)))
{
- m_copydata(m, skip + offsetof(struct esp_new, esp_rpl),
- sizeof(u_int32_t), (unsigned char *) &btsx);
+ m_copydata(m, skip + sizeof(u_int32_t), sizeof(u_int32_t),
+ (unsigned char *) &btsx);
btsx = ntohl(btsx);
switch (checkreplaywindow32(btsx, 0, &(tdb->tdb_rpl), tdb->tdb_wnd,
@@ -297,20 +331,20 @@ esp_new_input(struct mbuf *m, struct tdb *tdb, int skip, int protoff)
break;
case 1:
- DPRINTF(("esp_new_input(): replay counter wrapped for SA %s/%08x\n", ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
+ DPRINTF(("esp_input(): replay counter wrapped for SA %s/%08x\n", ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
espstat.esps_wrap++;
m_freem(m);
return NULL;
case 2:
case 3:
- DPRINTF(("esp_new_input(): duplicate packet received in SA %s/%08x\n", ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
+ DPRINTF(("esp_input(): duplicate packet received in SA %s/%08x\n", ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
espstat.esps_replay++;
m_freem(m);
return NULL;
default:
- DPRINTF(("esp_new_input(): bogus value from checkreplaywindow32() in SA %s/%08x\n", ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
+ DPRINTF(("esp_input(): bogus value from checkreplaywindow32() in SA %s/%08x\n", ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
espstat.esps_replay++;
m_freem(m);
return NULL;
@@ -318,8 +352,8 @@ esp_new_input(struct mbuf *m, struct tdb *tdb, int skip, int protoff)
}
/* Update the counters */
- tdb->tdb_cur_bytes += m->m_pkthdr.len - ohlen - alen;
- espstat.esps_ibytes += m->m_pkthdr.len - ohlen - alen;
+ tdb->tdb_cur_bytes += m->m_pkthdr.len - skip - hlen - alen;
+ espstat.esps_ibytes += m->m_pkthdr.len - skip - hlen - alen;
/* Hard expiration */
if ((tdb->tdb_flags & TDBF_BYTES) &&
@@ -353,7 +387,7 @@ esp_new_input(struct mbuf *m, struct tdb *tdb, int skip, int protoff)
roff = off;
m1 = mo;
- /* Verify the authenticator */
+ /* Verify the authenticator, if applicable */
if (esph)
{
bcopy(tdb->tdb_ictx, &ctx, esph->ctxsize);
@@ -361,11 +395,12 @@ esp_new_input(struct mbuf *m, struct tdb *tdb, int skip, int protoff)
/* Copy the authentication data */
m_copydata(m, m->m_pkthdr.len - alen, alen, iv);
+ /* Compute authenticator over the mbuf chain */
while (oplen > 0)
{
if (mo == NULL)
{
- DPRINTF(("esp_new_input(): bad mbuf chain, SA %s/%08x\n",
+ DPRINTF(("esp_input(): bad mbuf chain, SA %s/%08x\n",
ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
espstat.esps_hdrops++;
m_freem(m);
@@ -384,9 +419,10 @@ esp_new_input(struct mbuf *m, struct tdb *tdb, int skip, int protoff)
esph->Update(&ctx, niv, esph->hashsize);
esph->Final(niv, &ctx);
+ /* Verify */
if (bcmp(niv, iv, AH_HMAC_HASHLEN))
{
- DPRINTF(("esp_new_input(): authentication failed for packet in SA %s/%08x\n", ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
+ DPRINTF(("esp_input(): authentication failed for packet in SA %s/%08x\n", ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
espstat.esps_badauth++;
m_freem(m);
return NULL;
@@ -397,13 +433,15 @@ esp_new_input(struct mbuf *m, struct tdb *tdb, int skip, int protoff)
/* Find beginning of encrypted data (actually, the IV) */
mi = m1;
- ilen = mi->m_len - roff - 2 * sizeof(u_int32_t);
+ ilen = mi->m_len - roff - sizeof(u_int32_t);
+ if (!(tdb->tdb_flags & TDBF_NOREPLAY))
+ ilen -= sizeof(u_int32_t);
while (ilen <= 0)
{
mi = mi->m_next;
if (mi == NULL)
{
- DPRINTF(("esp_new_input(): bad mbuf chain, SA %s/%08x\n",
+ DPRINTF(("esp_input(): bad mbuf chain, SA %s/%08x\n",
ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
espstat.esps_hdrops++;
m_freem(m);
@@ -416,6 +454,13 @@ esp_new_input(struct mbuf *m, struct tdb *tdb, int skip, int protoff)
idat = mtod(mi, unsigned char *) + (mi->m_len - ilen);
m_copydata(mi, mi->m_len - ilen, tdb->tdb_ivlen, iv);
+ /* If we're doing half-IV, generate full IV */
+ if (tdb->tdb_flags & TDBF_HALFIV)
+ {
+ for (i = 0; i < tdb->tdb_ivlen; i++)
+ iv[tdb->tdb_ivlen + i] = ~iv[i];
+ }
+
/* Now skip over the IV */
ilen -= tdb->tdb_ivlen;
while (ilen <= 0)
@@ -423,7 +468,7 @@ esp_new_input(struct mbuf *m, struct tdb *tdb, int skip, int protoff)
mi = mi->m_next;
if (mi == NULL)
{
- DPRINTF(("esp_new_input(): bad mbuf chain, SA %s/%08x\n",
+ DPRINTF(("esp_input(): bad mbuf chain, SA %s/%08x\n",
ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
espstat.esps_hdrops++;
m_freem(m);
@@ -439,27 +484,25 @@ esp_new_input(struct mbuf *m, struct tdb *tdb, int skip, int protoff)
if (roff == 0)
{
/* The ESP header was conveniently at the beginning of the mbuf */
- m_adj(m1, 2 * sizeof(u_int32_t) + tdb->tdb_ivlen);
+ m_adj(m1, hlen);
if (!(m1->m_flags & M_PKTHDR))
- m->m_pkthdr.len -= (2 * sizeof(u_int32_t) + tdb->tdb_ivlen);
+ m->m_pkthdr.len -= hlen;
}
else
- if (roff + 2 * sizeof(u_int32_t) + tdb->tdb_ivlen >= m1->m_len)
+ if (roff + hlen >= m1->m_len)
{
/*
* Part or all of the ESP header is at the end of this mbuf, so first
* let's remove the remainder of the ESP header from the
* beginning of the remainder of the mbuf chain, if any.
*/
- if (roff + 2 * sizeof(u_int32_t) + tdb->tdb_ivlen > m1->m_len)
+ if (roff + hlen > m1->m_len)
{
/* Adjust the next mbuf by the remainder */
- m_adj(m1->m_next, roff + 2 * sizeof(u_int32_t) +
- tdb->tdb_ivlen - m1->m_len);
+ m_adj(m1->m_next, roff + hlen - m1->m_len);
/* The second mbuf is guaranteed not to have a pkthdr... */
- m->m_pkthdr.len -= (roff + 2 * sizeof(u_int32_t) +
- tdb->tdb_ivlen - m1->m_len);
+ m->m_pkthdr.len -= (roff + hlen - m1->m_len);
}
/* Now, let's unlink the mbuf chain for a second...*/
@@ -481,12 +524,10 @@ esp_new_input(struct mbuf *m, struct tdb *tdb, int skip, int protoff)
* overlapping copy of the remainder of the mbuf over the ESP
* header.
*/
- bcopy(mtod(m1, u_char *) + roff + 2 * sizeof(u_int32_t) +
- tdb->tdb_ivlen,
- mtod(m1, u_char *) + roff,
- m1->m_len - (roff + 2 * sizeof(u_int32_t) + tdb->tdb_ivlen));
- m1->m_len -= (2 * sizeof(u_int32_t) + tdb->tdb_ivlen);
- m->m_pkthdr.len -= (2 * sizeof(u_int32_t) + tdb->tdb_ivlen);
+ bcopy(mtod(m1, u_char *) + roff + hlen, mtod(m1, u_char *) + roff,
+ m1->m_len - (roff + hlen));
+ m1->m_len -= hlen;
+ m->m_pkthdr.len -= hlen;
}
/* Point to the encrypted data */
@@ -525,7 +566,7 @@ esp_new_input(struct mbuf *m, struct tdb *tdb, int skip, int protoff)
mi = (mo = mi)->m_next;
if (mi == NULL)
{
- DPRINTF(("esp_new_input(): bad mbuf chain, SA %s/%08x\n",
+ DPRINTF(("esp_input(): bad mbuf chain, SA %s/%08x\n",
ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
espstat.esps_hdrops++;
m_freem(m);
@@ -537,7 +578,7 @@ esp_new_input(struct mbuf *m, struct tdb *tdb, int skip, int protoff)
{
if ((mi = m_pullup(mi, blks - rest)) == NULL)
{
- DPRINTF(("esp_new_input(): m_pullup() failed, SA %s/%08x\n", ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
+ DPRINTF(("esp_input(): m_pullup() failed, SA %s/%08x\n", ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
m_freem(m);
espstat.esps_hdrops++;
return NULL;
@@ -607,25 +648,27 @@ esp_new_input(struct mbuf *m, struct tdb *tdb, int skip, int protoff)
* blk[blks - 1] contains the next protocol, and blk[blks - 2] contains
* the amount of padding the original chain had. Chop off the
* appropriate parts of the chain, and return.
- * Verify correct decryption by checking the last padding bytes.
*/
- if (blk[blks - 2] + 2 + alen > m->m_pkthdr.len - skip -
- 2 * sizeof(u_int32_t) - tdb->tdb_ivlen)
+ if (blk[blks - 2] + 2 + alen > m->m_pkthdr.len - skip - hlen)
{
- DPRINTF(("esp_new_input(): invalid padding length %d for packet in SA %s/%08x\n", blk[blks - 2], ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
+ DPRINTF(("esp_input(): invalid padding length %d for packet in SA %s/%08x\n", blk[blks - 2], ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
espstat.esps_badilen++;
m_freem(m);
return NULL;
}
- if ((blk[blks - 2] != blk[blks - 3]) && (blk[blks - 2] != 0))
+ /* Verify correct decryption by checking the last padding bytes. */
+ if (!(tdb->tdb_flags & TDBF_RANDOMPADDING))
{
- DPRINTF(("esp_new_input(): decryption failed for packet in SA %s/%08x\n", ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
- espstat.esps_badenc++;
- m_freem(m);
- return NULL;
- }
+ if ((blk[blks - 2] != blk[blks - 3]) && (blk[blks - 2] != 0))
+ {
+ DPRINTF(("esp_input(): decryption failed for packet in SA %s/%08x\n", ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
+ espstat.esps_badenc++;
+ m_freem(m);
+ return NULL;
+ }
+ }
/* Trim the mbuf chain to remove the trailing authenticator */
m_adj(m, - blk[blks - 2] - 2 - alen);
@@ -637,20 +680,52 @@ esp_new_input(struct mbuf *m, struct tdb *tdb, int skip, int protoff)
}
int
-esp_new_output(struct mbuf *m, struct tdb *tdb, struct mbuf **mp, int skip,
+esp_output(struct mbuf *m, struct tdb *tdb, struct mbuf **mp, int skip,
int protoff)
{
struct enc_xform *espx = (struct enc_xform *) tdb->tdb_encalgxform;
struct auth_hash *esph = (struct auth_hash *) tdb->tdb_authalgxform;
u_char iv[ESP_MAX_IVS], blk[ESP_MAX_BLKS], auth[AH_ALEN_MAX];
- int i, ilen, ohlen, rlen, plen, padding, rest, blks, alen;
+ int i, ilen, hlen, rlen, plen, padding, rest, blks, alen;
struct mbuf *mi, *mo = (struct mbuf *) NULL;
u_char *pad, *idat, *odat, *ivp;
- struct esp_new *esp;
union authctx ctx;
+#if NBPFILTER > 0
+ {
+ struct ifnet *ifn;
+ struct enchdr hdr;
+ struct mbuf m1;
+
+ bzero (&hdr, sizeof(hdr));
+
+ hdr.af = tdb->tdb_dst.sa.sa_family;
+ hdr.spi = tdb->tdb_spi;
+ if (espx)
+ hdr.flags |= M_CONF;
+ if (esph)
+ hdr.flags |= M_AUTH;
+
+ m1.m_next = m;
+ m1.m_len = ENC_HDRLEN;
+ m1.m_data = (char *) &hdr;
+
+ if (tdb->tdb_interface)
+ ifn = (struct ifnet *) tdb->tdb_interface;
+ else
+ ifn = &(encif[0].sc_if);
+
+ if (ifn->if_bpf)
+ bpf_mtap(ifn->if_bpf, &m1);
+ }
+#endif
+
+ if (tdb->tdb_flags & TDBF_NOREPLAY)
+ hlen = sizeof(u_int32_t) + tdb->tdb_ivlen;
+ else
+ hlen = 2 * sizeof(u_int32_t) + tdb->tdb_ivlen;
+
blks = espx->blocksize;
- ohlen = 2 * sizeof(u_int32_t) + tdb->tdb_ivlen;
rlen = m->m_pkthdr.len - skip; /* Raw payload length */
padding = ((blks - ((rlen + 2) % blks)) % blks) + 2;
plen = rlen + padding; /* Padded payload length */
@@ -663,9 +738,10 @@ esp_new_output(struct mbuf *m, struct tdb *tdb, struct mbuf **mp, int skip,
espstat.esps_output++;
/* Check for replay counter wrap-around in automatic (not manual) keying */
- if ((tdb->tdb_rpl == 0) && (tdb->tdb_wnd > 0))
+ if ((!(tdb->tdb_flags & TDBF_NOREPLAY)) &&
+ (tdb->tdb_rpl == 0) && (tdb->tdb_wnd > 0))
{
- DPRINTF(("esp_new_output(): SA %s/%0x8 should have expired\n",
+ DPRINTF(("esp_output(): SA %s/%0x8 should have expired\n",
ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
m_freem(m);
espstat.esps_wrap++;
@@ -673,11 +749,11 @@ esp_new_output(struct mbuf *m, struct tdb *tdb, struct mbuf **mp, int skip,
}
#ifdef INET
- /* In IPv4, check for max packet size violations. Not needed in IPv6. */
+ /* Check for IPv6 maximum packet size violations */
if (tdb->tdb_dst.sa.sa_family == AF_INET)
- if (skip + ohlen + rlen + padding + alen > IP_MAXPACKET)
+ if (skip + hlen + rlen + padding + alen > IP_MAXPACKET)
{
- DPRINTF(("esp_new_output(): packet in SA %s/%0x8 got too big\n",
+ DPRINTF(("esp_output(): packet in SA %s/%0x8 got too big\n",
ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
m_freem(m);
espstat.esps_toobig++;
@@ -685,6 +761,19 @@ esp_new_output(struct mbuf *m, struct tdb *tdb, struct mbuf **mp, int skip,
}
#endif /* INET */
+#ifdef INET6
+ /* Check for IPv6 maximum packet size violations */
+ if (tdb->tdb_dst.sa.sa_family == AF_INET6)
+ if (skip + hlen + rlen + padding + alen > IPV6_MAXPACKET)
+ {
+ DPRINTF(("esp_output(): packet in SA %s/%0x8 got too big\n",
+ ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
+ m_freem(m);
+ espstat.esps_toobig++;
+ return EMSGSIZE;
+ }
+#endif /* INET6 */
+
/* Update the counters */
tdb->tdb_cur_bytes += m->m_pkthdr.len - skip;
espstat.esps_obytes += m->m_pkthdr.len - skip;
@@ -742,40 +831,52 @@ esp_new_output(struct mbuf *m, struct tdb *tdb, struct mbuf **mp, int skip,
}
/* Inject ESP header */
- mo = m_inject(m, skip, ohlen, M_WAITOK);
+ mo = m_inject(m, skip, hlen, M_WAITOK);
if (mo == NULL)
{
- DPRINTF(("esp_new_output(): failed to inject ESP header for SA %s/%08x\n", ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
+ DPRINTF(("esp_output(): failed to inject ESP header for SA %s/%08x\n", ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
m_freem(m);
espstat.esps_wrap++;
return ENOBUFS;
}
/* Initialize ESP header */
- esp = mtod(mo, struct esp_new *);
- esp->esp_spi = tdb->tdb_spi;
- esp->esp_rpl = htonl(tdb->tdb_rpl++);
+ m_copyback(mo, 0, sizeof(u_int32_t), (caddr_t) &tdb->tdb_spi);
+ if (!(tdb->tdb_flags & TDBF_NOREPLAY))
+ {
+ u_int32_t replay = htonl(tdb->tdb_rpl++);
+ m_copyback(mo, sizeof(u_int32_t), sizeof(u_int32_t),
+ (caddr_t) &replay);
+ }
- /*
- * We can cheat and use bcopy() instead of m_copyback() for the
- * second copy below, because m_inject() is guaranteed to fit the
- * ESP header in one mbuf.
- */
+ /* Initialize IV (cook the half-IV if applicable) */
bcopy(tdb->tdb_iv, iv, tdb->tdb_ivlen);
- bcopy(iv, esp->esp_iv, tdb->tdb_ivlen);
+ if (tdb->tdb_flags & TDBF_HALFIV)
+ {
+ for (i = 0; i < tdb->tdb_ivlen; i++)
+ iv[i + tdb->tdb_ivlen] = ~iv[i];
+ }
+
+ /* Copy IV in ESP header */
+ m_copyback(mo, hlen - tdb->tdb_ivlen, tdb->tdb_ivlen,
+ (caddr_t) &tdb->tdb_iv);
/* Add padding */
- pad = (u_char *) m_pad(m, padding + alen, 0);
+ pad = (u_char *) m_pad(m, padding + alen,
+ tdb->tdb_flags & TDBF_RANDOMPADDING);
if (pad == NULL)
{
- DPRINTF(("esp_new_output(): m_pad() failed for SA %s/%08x\n",
+ DPRINTF(("esp_output(): m_pad() failed for SA %s/%08x\n",
ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
return ENOBUFS;
}
- /* Self-describing padding */
- for (ilen = 0; ilen < padding - 2; ilen++)
- pad[ilen] = ilen + 1;
+ /* Self-describing padding ? */
+ if (!(tdb->tdb_flags & TDBF_RANDOMPADDING))
+ {
+ for (ilen = 0; ilen < padding - 2; ilen++)
+ pad[ilen] = ilen + 1;
+ }
/* Fix padding length and Next Protocol in padding itself */
pad[padding - 2] = padding - 2;
@@ -783,12 +884,12 @@ esp_new_output(struct mbuf *m, struct tdb *tdb, struct mbuf **mp, int skip,
/* Fix Next Protocol in IPv4/IPv6 header */
ilen = IPPROTO_ESP;
- m_copyback(m, protoff, 1, (u_char *) &ilen);
+ m_copyback(m, protoff, sizeof(u_int8_t), (u_char *) &ilen);
mi = mo;
/* If it's just the ESP header, just skip to the next mbuf */
- if (mi->m_len == ohlen)
+ if (mi->m_len == hlen)
{
mi = mi->m_next;
ilen = mi->m_len;
@@ -796,16 +897,15 @@ esp_new_output(struct mbuf *m, struct tdb *tdb, struct mbuf **mp, int skip,
}
else
{ /* There's data at the end of this mbuf, skip over ESP header */
- ilen = mi->m_len - ohlen;
- idat = mtod(mi, u_char *) + ohlen;
+ ilen = mi->m_len - hlen;
+ idat = mtod(mi, u_char *) + hlen;
}
- /* Authenticate the ESP header */
+ /* Authenticate the ESP header if applicable */
if (esph)
{
bcopy(tdb->tdb_ictx, &ctx, esph->ctxsize);
- esph->Update(&ctx, (unsigned char *) esp,
- 2 * sizeof(u_int32_t) + tdb->tdb_ivlen);
+ esph->Update(&ctx, mtod(mo, unsigned char *), hlen);
}
/* Encrypt the payload */
@@ -831,7 +931,7 @@ esp_new_output(struct mbuf *m, struct tdb *tdb, struct mbuf **mp, int skip,
mi = (mo = mi)->m_next;
if (mi == NULL)
{
- DPRINTF(("esp_new_output(): bad mbuf chain, SA %s/%08x\n",
+ DPRINTF(("esp_output(): bad mbuf chain, SA %s/%08x\n",
ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
espstat.esps_hdrops++;
m_freem(m);
@@ -843,7 +943,7 @@ esp_new_output(struct mbuf *m, struct tdb *tdb, struct mbuf **mp, int skip,
{
if ((mi = m_pullup(mi, blks - rest)) == NULL)
{
- DPRINTF(("esp_new_output(): m_pullup() failed, SA %s/%08x\n", ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
+ DPRINTF(("esp_output(): m_pullup() failed, SA %s/%08x\n", ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
m_freem(m);
espstat.esps_hdrops++;
return ENOBUFS;
@@ -965,3 +1065,79 @@ checkreplaywindow32(u_int32_t seq, u_int32_t initial, u_int32_t *lastseq,
return 0;
}
+/*
+ *
+ *
+ * m_pad(m, n) pads <m> with <n> bytes at the end. The packet header
+ * length is updated, and a pointer to the first byte of the padding
+ * (which is guaranteed to be all in one mbuf) is returned. The third
+ * argument specifies whether we need randompadding or not.
+ *
+ */
+
+caddr_t
+m_pad(struct mbuf *m, int n, int randompadding)
+{
+ register struct mbuf *m0, *m1;
+ register int len, pad;
+ caddr_t retval;
+ u_int8_t dat;
+
+ if (n <= 0) /* no stupid arguments */
+ {
+ DPRINTF(("m_pad(): pad length invalid (%d)\n", n));
+ return NULL;
+ }
+
+ len = m->m_pkthdr.len;
+ pad = n;
+
+ m0 = m;
+
+ while (m0->m_len < len)
+ {
+ len -= m0->m_len;
+ m0 = m0->m_next;
+ }
+
+ if (m0->m_len != len)
+ {
+ DPRINTF(("m_pad(): length mismatch (should be %d instead of %d)\n",
+ m->m_pkthdr.len, m->m_pkthdr.len + m0->m_len - len));
+ m_freem(m);
+ return NULL;
+ }
+
+ if ((m0->m_flags & M_EXT) ||
+ (m0->m_data + m0->m_len + pad >= &(m0->m_dat[MLEN])))
+ {
+ /*
+ * Add an mbuf to the chain
+ */
+
+ MGET(m1, M_DONTWAIT, MT_DATA);
+ if (m1 == 0)
+ {
+ m_freem(m0);
+ DPRINTF(("m_pad(): cannot append\n"));
+ return NULL;
+ }
+
+ m0->m_next = m1;
+ m0 = m1;
+ m0->m_len = 0;
+ }
+
+ retval = m0->m_data + m0->m_len;
+ m0->m_len += pad;
+ m->m_pkthdr.len += pad;
+
+ if (randompadding)
+ for (len = 0; len < n; len++)
+ {
+ get_random_bytes((void *) &dat, sizeof(u_int8_t));
+ retval[len] = len + dat;
+ }
+
+ return retval;
+}
diff --git a/sys/netinet/ip_esp.h b/sys/netinet/ip_esp.h
index 3146ebaf1ef..2438f1a8c8d 100644
--- a/sys/netinet/ip_esp.h
+++ b/sys/netinet/ip_esp.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_esp.h,v 1.30 2000/01/13 05:03:45 angelos Exp $ */
+/* $OpenBSD: ip_esp.h,v 1.31 2000/01/27 08:09:10 angelos Exp $ */
/*
* The authors of this code are John Ioannidis (ji@tla.org),
@@ -35,32 +35,10 @@
* PURPOSE.
*/
-/*
- * Encapsulation Security Payload Processing
- * Per RFC1827 (Atkinson, 1995)
- */
-
#ifndef _NETINET_ESP_H_
#define _NETINET_ESP_H_
-/* Various defines for the "new" ESP */
-#define ESP_NEW_ALEN 12 /* 96bits authenticator */
-
-struct esp_old
-{
- u_int32_t esp_spi; /* Security Parameters Index */
- u_int8_t esp_iv[8]; /* iv[4] may actually be data! */
-};
-
-#define ESP_OLD_FLENGTH 12
-#define ESP_NEW_FLENGTH 16
-
-struct esp_new
-{
- u_int32_t esp_spi; /* Security Parameter Index */
- u_int32_t esp_rpl; /* Sequence Number, Replay Counter */
- u_int8_t esp_iv[8]; /* Data may start already at iv[0]! */
-};
+#define ESP_ALEN 12 /* 96-bit authenticator */
struct espstat
{
@@ -96,14 +74,6 @@ struct espstat
}
#ifdef _KERNEL
-void esp_input __P((struct mbuf *, ...));
-int esp_output __P((struct mbuf *, struct tdb *, struct mbuf **));
-int esp_sysctl __P((int *, u_int, void *, size_t *, void *, size_t));
-
-#ifdef INET6
-int esp6_input __P((struct mbuf **, int *, int));
-#endif /* INET6 */
-
extern int esp_enable;
struct espstat espstat;
#endif /* _KERNEL */
diff --git a/sys/netinet/ip_esp_old.c b/sys/netinet/ip_esp_old.c
deleted file mode 100644
index 309fddc4118..00000000000
--- a/sys/netinet/ip_esp_old.c
+++ /dev/null
@@ -1,811 +0,0 @@
-/* $OpenBSD: ip_esp_old.c,v 1.38 1999/12/06 07:14:35 angelos Exp $ */
-
-/*
- * The authors of this code are John Ioannidis (ji@tla.org),
- * Angelos D. Keromytis (kermit@csd.uch.gr) and
- * Niels Provos (provos@physnet.uni-hamburg.de).
- *
- * This code was written by John Ioannidis for BSD/OS in Athens, Greece,
- * in November 1995.
- *
- * Ported to OpenBSD and NetBSD, with additional transforms, in December 1996,
- * by Angelos D. Keromytis.
- *
- * Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis
- * and Niels Provos.
- *
- * Additional features in 1999 by Angelos D. Keromytis.
- *
- * Copyright (C) 1995, 1996, 1997, 1998, 1999 by John Ioannidis,
- * Angelos D. Keromytis and Niels Provos.
- *
- * Permission to use, copy, and modify this software without fee
- * is hereby granted, provided that this entire notice is included in
- * all copies of any software which is or includes a copy or
- * modification of this software.
- * You may use this code under the GNU public license if you so wish. Please
- * contribute changes back to the authors under this freer than GPL license
- * so that we may further the use of strong encryption without limitations to
- * all.
- *
- * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY
- * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE
- * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
- * PURPOSE.
- */
-
-/*
- * DES-CBC
- * Per RFCs 1829/1851 (Metzger & Simpson)
- */
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/malloc.h>
-#include <sys/mbuf.h>
-#include <sys/domain.h>
-#include <sys/protosw.h>
-#include <sys/socket.h>
-#include <sys/errno.h>
-#include <sys/time.h>
-#include <sys/kernel.h>
-#include <machine/cpu.h>
-
-#include <net/if.h>
-#include <net/route.h>
-#include <net/netisr.h>
-
-#include <netinet/in.h>
-#include <netinet/in_systm.h>
-#include <netinet/ip.h>
-#include <netinet/in_pcb.h>
-#include <netinet/in_var.h>
-#include <netinet/ip_var.h>
-
-#include <sys/socketvar.h>
-#include <net/raw_cb.h>
-
-#include <netinet/ip_icmp.h>
-#include <netinet/ip_ipsp.h>
-#include <netinet/ip_esp.h>
-#include <net/pfkeyv2.h>
-#include <dev/rndvar.h>
-
-#ifdef ENCDEBUG
-#define DPRINTF(x) if (encdebug) printf x
-#else
-#define DPRINTF(x)
-#endif
-
-extern struct enc_xform enc_xform_des;
-extern struct enc_xform enc_xform_3des;
-
-struct enc_xform *esp_old_xform[] = {
- &enc_xform_des,
- &enc_xform_3des
-};
-
-int
-esp_old_attach()
-{
- return 0;
-}
-
-/*
- * esp_old_init() is called when an SPI is being set up.
- */
-
-int
-esp_old_init(struct tdb *tdbp, struct xformsw *xsp, struct ipsecinit *ii)
-{
- struct enc_xform *txform = NULL;
- int i;
-
- /* Check whether the encryption algorithm is supported */
- for (i = sizeof(esp_old_xform) / sizeof(esp_old_xform[0]) - 1;
- i >= 0; i--)
- if (ii->ii_encalg == esp_old_xform[i]->type)
- break;
-
- if (i < 0)
- {
- DPRINTF(("esp_old_init(): unsupported encryption algorithm %d specified\n", ii->ii_encalg));
- return EINVAL;
- }
-
- txform = esp_old_xform[i];
-
- if (ii->ii_enckeylen < txform->minkey)
- {
- DPRINTF(("esp_old_init(): keylength %d too small (min length is %d) for algorithm %s\n", ii->ii_enckeylen, txform->minkey, txform->name));
- return EINVAL;
- }
-
- if (ii->ii_enckeylen > txform->maxkey)
- {
- DPRINTF(("esp_old_init(): keylength %d too large (max length is %d) for algorithm %s\n", ii->ii_enckeylen, txform->maxkey, txform->name));
- return EINVAL;
- }
-
- tdbp->tdb_xform = xsp;
- tdbp->tdb_encalgxform = txform;
-
- DPRINTF(("esp_old_init(): initialized TDB with enc algorithm %s\n",
- txform->name));
-
- tdbp->tdb_ivlen = txform->ivmask;
- if (tdbp->tdb_flags & TDBF_HALFIV)
- tdbp->tdb_ivlen /= 2;
-
- get_random_bytes(tdbp->tdb_iv, tdbp->tdb_ivlen);
-
- if (txform->setkey)
- txform->setkey(&tdbp->tdb_key, ii->ii_enckey, ii->ii_enckeylen);
-
- return 0;
-}
-
-/* Free the memory */
-int
-esp_old_zeroize(struct tdb *tdbp)
-{
- if (tdbp->tdb_key && tdbp->tdb_encalgxform &&
- tdbp->tdb_encalgxform->zerokey)
- tdbp->tdb_encalgxform->zerokey(&tdbp->tdb_key);
-
- return 0;
-}
-
-/*
- * esp_old_input() gets called to decrypt an input packet
- */
-struct mbuf *
-esp_old_input(struct mbuf *m, struct tdb *tdb, int skip, int protoff)
-{
- struct enc_xform *espx = (struct enc_xform *) tdb->tdb_encalgxform;
- struct ip *ip, ipo;
- u_char iv[ESP_3DES_IVS], niv[ESP_3DES_IVS], blk[ESP_3DES_BLKS], opts[40];
- u_char *idat, *odat, *ivp, *ivn, *lblk;
- struct esp_old *esp;
- int ohlen, plen, ilen, i, blks, rest;
- struct mbuf *mi, *mo;
-
- blks = espx->blocksize;
-
- if (m->m_len < sizeof(struct ip))
- {
- if ((m = m_pullup(m, sizeof(struct ip))) == NULL)
- {
- DPRINTF(("esp_old_input(): m_pullup() failed\n"));
- espstat.esps_hdrops++;
- return NULL;
- }
- }
-
- ip = mtod(m, struct ip *);
- ohlen = (ip->ip_hl << 2) + ESP_OLD_FLENGTH;
-
- /* Make sure the IP header, any IP options, and the ESP header are here */
- if (m->m_len < ohlen + blks)
- {
- if ((m = m_pullup(m, ohlen + blks)) == NULL)
- {
- DPRINTF(("esp_old_input(): m_pullup() failed\n"));
- espstat.esps_hdrops++;
- return NULL;
- }
-
- ip = mtod(m, struct ip *);
- }
-
- esp = (struct esp_old *) ((u_int8_t *) ip + (ip->ip_hl << 2));
- ipo = *ip;
-
- /* Skip the IP header, IP options, SPI and IV */
- plen = m->m_pkthdr.len - (ip->ip_hl << 2) - sizeof(u_int32_t) -
- tdb->tdb_ivlen;
- if ((plen & (blks - 1)) || (plen <= 0))
- {
- DPRINTF(("esp_old_input(): payload not a multiple of %d octets for packet from %s to %s, spi %08x\n", blks, inet_ntoa4(ipo.ip_src), inet_ntoa4(ipo.ip_dst), ntohl(tdb->tdb_spi)));
- espstat.esps_badilen++;
- m_freem(m);
- return NULL;
- }
-
- /* Update the counters */
- tdb->tdb_cur_bytes += plen;
- espstat.esps_ibytes += plen;
-
- /* Hard expiration */
- if ((tdb->tdb_flags & TDBF_BYTES) &&
- (tdb->tdb_cur_bytes >= tdb->tdb_exp_bytes))
- {
- pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_HARD);
- tdb_delete(tdb, 0, TDBEXP_TIMEOUT);
- m_freem(m);
- return NULL;
- }
-
- /* Notify on expiration */
- if ((tdb->tdb_flags & TDBF_SOFT_BYTES) &&
- (tdb->tdb_cur_bytes >= tdb->tdb_soft_bytes))
- {
- pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_SOFT);
- tdb->tdb_flags &= ~TDBF_SOFT_BYTES; /* Turn off checking */
- }
-
- ilen = m->m_len - (ip->ip_hl << 2) - sizeof(u_int32_t) - 4;
- idat = mtod(m, unsigned char *) + (ip->ip_hl << 2) + sizeof(u_int32_t) + 4;
-
- /* Get the IV */
- iv[0] = esp->esp_iv[0];
- iv[1] = esp->esp_iv[1];
- iv[2] = esp->esp_iv[2];
- iv[3] = esp->esp_iv[3];
- if (tdb->tdb_ivlen == 4) /* Half-IV */
- {
- iv[4] = ~esp->esp_iv[0];
- iv[5] = ~esp->esp_iv[1];
- iv[6] = ~esp->esp_iv[2];
- iv[7] = ~esp->esp_iv[3];
- }
- else
- {
- iv[4] = esp->esp_iv[4];
- iv[5] = esp->esp_iv[5];
- iv[6] = esp->esp_iv[6];
- iv[7] = esp->esp_iv[7];
-
- /* Adjust the lengths accordingly */
- ilen -= 4;
- idat += 4;
- }
-
- mi = m;
-
- /*
- * At this point:
- * plen is # of encapsulated payload octets
- * ilen is # of octets left in this mbuf
- * idat is first encapsulated payload octed in this mbuf
- * same for olen and odat
- * ivp points to the IV, ivn buffers the next IV.
- * mi points to the first mbuf
- *
- * From now on until the end of the mbuf chain:
- * . move the next eight octets of the chain into ivn
- * . decrypt idat and xor with ivp
- * . swap ivp and ivn.
- * . repeat
- */
-
- ivp = iv;
- ivn = niv;
- rest = ilen % blks;
- while (plen > 0) /* while not done */
- {
- if (ilen < blks)
- {
- if (rest)
- {
- bcopy(idat, blk, rest);
- odat = idat;
- }
-
- do {
- mi = (mo = mi)->m_next;
- if (mi == NULL)
- {
- DPRINTF(("esp_old_input(): bad mbuf chain, SA %s/%08x\n",
- ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
- m_freem(m);
- espstat.esps_hdrops++;
- return NULL;
- }
- } while (mi->m_len == 0);
-
- if (mi->m_len < blks - rest)
- {
- if ((mi = m_pullup(mi, blks - rest)) == NULL)
- {
- DPRINTF(("esp_old_input(): m_pullup() failed, SA %s/%08x\n", ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
- espstat.esps_hdrops++;
- return NULL;
- }
- /*
- * m_pullup was not called at the beginning of the chain
- * but might return a new mbuf, link it into the chain.
- */
- mo->m_next = mi;
- }
-
- ilen = mi->m_len;
- idat = mtod(mi, u_char *);
-
- if (rest)
- {
- bcopy(idat, blk + rest, blks - rest);
- bcopy(blk, ivn, blks);
-
- espx->decrypt(tdb, blk);
-
- for (i=0; i < blks; i++)
- blk[i] ^= ivp[i];
-
- ivp = ivn;
- ivn = (ivp == iv) ? niv : iv;
-
- bcopy(blk, odat, rest);
- bcopy(blk + rest, idat, blks - rest);
-
- lblk = blk; /* last block touched */
-
- idat += blks - rest;
- ilen -= blks - rest;
- plen -= blks;
- }
-
- rest = ilen % blks;
- }
-
- while (ilen >= blks && plen > 0)
- {
- bcopy(idat, ivn, blks);
-
- espx->decrypt(tdb, idat);
-
- for (i = 0; i < blks; i++)
- idat[i] ^= ivp[i];
-
- ivp = ivn;
- ivn = (ivp == iv) ? niv : iv;
-
- lblk = idat; /* last block touched */
- idat += blks;
-
- ilen -= blks;
- plen -= blks;
- }
- }
-
- /* Save the options */
- m_copydata(m, sizeof(struct ip), (ipo.ip_hl << 2) - sizeof(struct ip),
- (caddr_t) opts);
-
- if (lblk != blk)
- bcopy(lblk, blk, blks);
-
- /*
- * Now, the entire chain has been decrypted. As a side effect,
- * blk[blks - 1] contains the next protocol, and blk[blks - 2] contains
- * the amount of padding the original chain had. Chop off the
- * appropriate parts of the chain, and return.
- * We cannot verify the decryption here (as in ip_esp_new.c), since
- * the padding may be random.
- */
-
- if (blk[blks - 2] + 2 > m->m_pkthdr.len - (ip->ip_hl << 2) -
- sizeof(u_int32_t) - tdb->tdb_ivlen)
- {
- DPRINTF(("esp_old_input(): invalid padding length %d for packet from %s to %s, spi %08x\n", blk[blks - 2], inet_ntoa4(ipo.ip_src), inet_ntoa4(ipo.ip_dst), ntohl(tdb->tdb_spi)));
- espstat.esps_badilen++;
- m_freem(m);
- return NULL;
- }
-
- m_adj(m, - blk[blks - 2] - 2);
- m_adj(m, sizeof(u_int32_t) + tdb->tdb_ivlen);
-
- if (m->m_len < (ipo.ip_hl << 2))
- {
- m = m_pullup(m, (ipo.ip_hl << 2));
- if (m == NULL)
- {
- DPRINTF(("esp_old_input(): m_pullup() failed for packet from %s to %s, spi %08x\n", inet_ntoa4(ipo.ip_src), inet_ntoa4(ipo.ip_dst), ntohl(tdb->tdb_spi)));
- espstat.esps_hdrops++;
- return NULL;
- }
- }
-
- ip = mtod(m, struct ip *);
- ipo.ip_p = blk[blks - 1];
- ipo.ip_id = htons(ipo.ip_id);
- ipo.ip_off = 0;
- ipo.ip_len += (ipo.ip_hl << 2) - sizeof(u_int32_t) - tdb->tdb_ivlen -
- blk[blks - 2] - 2;
- ipo.ip_len = htons(ipo.ip_len);
- ipo.ip_sum = 0;
- *ip = ipo;
-
- /* Copy the options back */
- m_copyback(m, sizeof(struct ip), (ipo.ip_hl << 2) - sizeof(struct ip),
- (caddr_t) opts);
-
- ip->ip_sum = in_cksum(m, (ip->ip_hl << 2));
-
- return m;
-}
-
-int
-esp_old_output(struct mbuf *m, struct tdb *tdb, struct mbuf **mp, int skip,
- int protoff)
-{
- struct enc_xform *espx = (struct enc_xform *) tdb->tdb_encalgxform;
- struct ip *ip, ipo;
- int i, ilen, ohlen, nh, rlen, plen, padding, rest;
- u_int32_t spi;
- struct mbuf *mi, *mo = (struct mbuf *) NULL;
- u_char *pad, *idat, *odat, *ivp;
- u_char iv[ESP_3DES_IVS], blk[ESP_3DES_IVS], opts[40];
- int iphlen, blks;
-
- blks = espx->blocksize;
-
- espstat.esps_output++;
-
- /*
- * Loop through mbuf chain; if we find an M_EXT mbuf with
- * more than one reference, replace the rest of the chain.
- */
- mi = m;
- while (mi != NULL &&
- (!(mi->m_flags & M_EXT) ||
- (mi->m_ext.ext_ref == NULL &&
- mclrefcnt[mtocl(mi->m_ext.ext_buf)] <= 1)))
- {
- mo = mi;
- mi = mi->m_next;
- }
-
- if (mi != NULL)
- {
- /* Replace the rest of the mbuf chain. */
- struct mbuf *n = m_copym2(mi, 0, M_COPYALL, M_DONTWAIT);
-
- if (n == NULL)
- {
- espstat.esps_hdrops++;
- m_freem(m);
- return ENOBUFS;
- }
-
- if (mo != NULL)
- mo->m_next = n;
- else
- m = n;
-
- m_freem(mi);
- }
-
- m = m_pullup(m, sizeof(struct ip));
- if (m == NULL)
- {
- DPRINTF(("esp_old_output(): m_pullup() failed for SA %s/%08x\n",
- ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
- espstat.esps_hdrops++;
- return ENOBUFS;
- }
-
- ip = mtod(m, struct ip *);
- spi = tdb->tdb_spi;
- iphlen = (ip->ip_hl << 2);
-
- /*
- * If options are present, pullup the IP header and the options.
- */
- if (iphlen != sizeof(struct ip))
- {
- m = m_pullup(m, iphlen);
- if (m == NULL)
- {
- DPRINTF(("esp_old_output(): m_pullup() failed for SA %s/%08x\n",
- ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
- espstat.esps_hdrops++;
- return ENOBUFS;
- }
-
- ip = mtod(m, struct ip *);
-
- /* Keep the options */
- m_copydata(m, sizeof(struct ip), iphlen - sizeof(struct ip),
- (caddr_t) opts);
- }
-
- ilen = ntohs(ip->ip_len);
- ohlen = sizeof(u_int32_t) + tdb->tdb_ivlen;
-
- ipo = *ip;
- nh = ipo.ip_p;
-
- /* Raw payload length */
- rlen = ilen - iphlen;
- padding = ((blks - ((rlen + 2) % blks)) % blks) + 2;
- if (iphlen + ohlen + rlen + padding > IP_MAXPACKET)
- {
- DPRINTF(("esp_old_output(): packet in SA %s/%0x8 got too big\n",
- ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
- m_freem(m);
- espstat.esps_toobig++;
- return EMSGSIZE;
- }
-
- /* Update the counters */
- tdb->tdb_cur_bytes += rlen;
- espstat.esps_obytes += rlen;
-
- /* Hard expiration */
- if ((tdb->tdb_flags & TDBF_BYTES) &&
- (tdb->tdb_cur_bytes >= tdb->tdb_exp_bytes))
- {
- pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_HARD);
- tdb_delete(tdb, 0, TDBEXP_TIMEOUT);
- m_freem(m);
- return EINVAL;
- }
-
- /* Notify on expiration */
- if ((tdb->tdb_flags & TDBF_SOFT_BYTES) &&
- (tdb->tdb_cur_bytes >= tdb->tdb_soft_bytes))
- {
- pfkeyv2_expire(tdb, SADB_EXT_LIFETIME_SOFT);
- tdb->tdb_flags &= ~TDBF_SOFT_BYTES; /* Turn off checking */
- }
-
- pad = (u_char *) m_pad(m, padding, 1);
- if (pad == NULL)
- {
- DPRINTF(("esp_old_output(): m_pad() failed for SA %s/%08x\n",
- ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
- return ENOBUFS;
- }
-
- pad[padding - 2] = padding - 2;
- pad[padding - 1] = nh;
-
- plen = rlen + padding;
- mi = m;
- ilen = m->m_len - iphlen;
- idat = mtod(m, u_char *) + iphlen;
-
- /*
- * We are now ready to encrypt the payload.
- */
-
- iv[0] = tdb->tdb_iv[0];
- iv[1] = tdb->tdb_iv[1];
- iv[2] = tdb->tdb_iv[2];
- iv[3] = tdb->tdb_iv[3];
-
- if (tdb->tdb_ivlen == 4) /* Half-IV */
- {
- iv[4] = ~tdb->tdb_iv[0];
- iv[5] = ~tdb->tdb_iv[1];
- iv[6] = ~tdb->tdb_iv[2];
- iv[7] = ~tdb->tdb_iv[3];
- }
- else
- {
- iv[4] = tdb->tdb_iv[4];
- iv[5] = tdb->tdb_iv[5];
- iv[6] = tdb->tdb_iv[6];
- iv[7] = tdb->tdb_iv[7];
- }
-
- ivp = iv;
- rest = ilen % blks;
- while (plen > 0) /* while not done */
- {
- if (ilen < blks) /* we exhausted previous mbuf */
- {
- if (rest)
- {
- if (ivp == blk)
- {
- bcopy(blk, iv, blks);
- ivp = iv;
- }
-
- bcopy(idat, blk, rest);
- odat = idat;
- }
-
- do {
- mi = (mo = mi)->m_next;
- if (mi == NULL)
- {
- DPRINTF(("esp_old_output(): bad mbuf chain, SA %s/%08x\n",
- ipsp_address(tdb->tdb_dst),
- ntohl(tdb->tdb_spi)));
- m_freem(m);
- return EINVAL;
- }
- } while (mi->m_len == 0);
-
- if (mi->m_len < blks - rest)
- {
- if ((mi = m_pullup(mi, blks - rest)) == NULL)
- {
- DPRINTF(("esp_old_output(): m_pullup() failed, SA %s/%08x\n", ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
- m_freem(m);
- espstat.esps_hdrops++;
- return ENOBUFS;
- }
- /*
- * m_pullup was not called at the beginning of the chain
- * but might return a new mbuf, link it into the chain.
- */
- mo->m_next = mi;
- }
-
- ilen = mi->m_len;
- idat = (u_char *) mi->m_data;
- if (rest)
- {
- bcopy(idat, blk + rest, blks - rest);
-
- for (i=0; i<blks; i++)
- blk[i] ^= ivp[i];
-
- espx->encrypt(tdb, blk);
-
- ivp = blk;
-
- bcopy(blk, odat, rest);
- bcopy(blk + rest, idat, blks - rest);
-
- idat += blks - rest;
- ilen -= blks - rest;
- plen -= blks;
- }
-
- rest = ilen % blks;
- }
-
- while (ilen >= blks && plen > 0)
- {
- for (i = 0; i < blks; i++)
- idat[i] ^= ivp[i];
-
- espx->encrypt(tdb, idat);
-
- ivp = idat;
- idat += blks;
-
- ilen -= blks;
- plen -= blks;
- }
- }
-
- /*
- * Done with encryption. Let's wedge in the ESP header
- * and send it out.
- */
-
- M_PREPEND(m, ohlen, M_DONTWAIT);
- if (m == NULL)
- {
- DPRINTF(("esp_old_output(): M_PREPEND failed, SA %s/%08x\n",
- ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
- return ENOBUFS;
- }
-
- m = m_pullup(m, iphlen + ohlen);
- if (m == NULL)
- {
- DPRINTF(("esp_old_output(): m_pullup() failed, SA %s/%08x\n",
- ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi)));
- espstat.esps_hdrops++;
- return ENOBUFS;
- }
-
- ipo.ip_len = htons(iphlen + ohlen + rlen + padding);
- ipo.ip_p = IPPROTO_ESP;
-
- iv[0] = tdb->tdb_iv[0];
- iv[1] = tdb->tdb_iv[1];
- iv[2] = tdb->tdb_iv[2];
- iv[3] = tdb->tdb_iv[3];
-
- if (tdb->tdb_ivlen == 8)
- {
- iv[4] = tdb->tdb_iv[4];
- iv[5] = tdb->tdb_iv[5];
- iv[6] = tdb->tdb_iv[6];
- iv[7] = tdb->tdb_iv[7];
- }
-
- /* Save the last encrypted block, to be used as the next IV */
- bcopy(ivp, tdb->tdb_iv, tdb->tdb_ivlen);
-
- m_copyback(m, 0, sizeof(struct ip), (caddr_t) &ipo);
-
- /* Copy options, if existing */
- if (iphlen != sizeof(struct ip))
- m_copyback(m, sizeof(struct ip), iphlen - sizeof(struct ip),
- (caddr_t) opts);
-
- m_copyback(m, iphlen, sizeof(u_int32_t), (caddr_t) &spi);
- m_copyback(m, iphlen + sizeof(u_int32_t), tdb->tdb_ivlen, (caddr_t) iv);
-
- *mp = m;
-
- return 0;
-}
-
-/*
- *
- *
- * m_pad(m, n) pads <m> with <n> bytes at the end. The packet header
- * length is updated, and a pointer to the first byte of the padding
- * (which is guaranteed to be all in one mbuf) is returned. The third
- * argument specifies whether we need randompadding or not.
- *
- */
-
-caddr_t
-m_pad(struct mbuf *m, int n, int randompadding)
-{
- register struct mbuf *m0, *m1;
- register int len, pad;
- caddr_t retval;
- u_int8_t dat;
-
- if (n <= 0) /* no stupid arguments */
- {
- DPRINTF(("m_pad(): pad length invalid (%d)\n", n));
- return NULL;
- }
-
- len = m->m_pkthdr.len;
- pad = n;
-
- m0 = m;
-
- while (m0->m_len < len)
- {
- len -= m0->m_len;
- m0 = m0->m_next;
- }
-
- if (m0->m_len != len)
- {
- DPRINTF(("m_pad(): length mismatch (should be %d instead of %d)\n",
- m->m_pkthdr.len, m->m_pkthdr.len + m0->m_len - len));
- m_freem(m);
- return NULL;
- }
-
- if ((m0->m_flags & M_EXT) ||
- (m0->m_data + m0->m_len + pad >= &(m0->m_dat[MLEN])))
- {
- /*
- * Add an mbuf to the chain
- */
-
- MGET(m1, M_DONTWAIT, MT_DATA);
- if (m1 == 0)
- {
- m_freem(m0);
- DPRINTF(("m_pad(): cannot append\n"));
- return NULL;
- }
-
- m0->m_next = m1;
- m0 = m1;
- m0->m_len = 0;
- }
-
- retval = m0->m_data + m0->m_len;
- m0->m_len += pad;
- m->m_pkthdr.len += pad;
-
- if (randompadding)
- for (len = 0; len < n; len++)
- {
- get_random_bytes((void *) &dat, sizeof(u_int8_t));
- retval[len] = len + dat;
- }
-
- return retval;
-}
diff --git a/sys/netinet/ip_ipsp.c b/sys/netinet/ip_ipsp.c
index 1cfa5c21bb4..9dc7f9c30c0 100644
--- a/sys/netinet/ip_ipsp.c
+++ b/sys/netinet/ip_ipsp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_ipsp.c,v 1.76 2000/01/21 03:15:05 angelos Exp $ */
+/* $OpenBSD: ip_ipsp.c,v 1.77 2000/01/27 08:09:12 angelos Exp $ */
/*
* The authors of this code are John Ioannidis (ji@tla.org),
@@ -140,19 +140,12 @@ struct xformsw xformsw[] = {
ipe4_attach, ipe4_init, ipe4_zeroize,
(struct mbuf * (*)(struct mbuf *, struct tdb *, int, int))ipe4_input,
ipip_output, },
- { XF_OLD_AH, XFT_AUTH, "Keyed Authentication, RFC 1828/1852",
- ah_old_attach, ah_old_init, ah_old_zeroize,
- ah_old_input, ah_old_output, },
- { XF_OLD_ESP, XFT_CONF, "Simple Encryption, RFC 1829/1851",
- esp_old_attach, esp_old_init, esp_old_zeroize,
- esp_old_input, esp_old_output, },
- { XF_NEW_AH, XFT_AUTH, "HMAC Authentication",
- ah_new_attach, ah_new_init, ah_new_zeroize,
- ah_new_input, ah_new_output, },
- { XF_NEW_ESP, XFT_CONF|XFT_AUTH,
- "Encryption + Authentication + Replay Protection",
- esp_new_attach, esp_new_init, esp_new_zeroize,
- esp_new_input, esp_new_output, },
+ { XF_AH, XFT_AUTH, "IPsec AH",
+ ah_attach, ah_init, ah_zeroize,
+ ah_input, ah_output, },
+ { XF_ESP, XFT_CONF|XFT_AUTH, "IPsec ESP",
+ esp_attach, esp_init, esp_zeroize,
+ esp_input, esp_output, },
#ifdef TCP_SIGNATURE
{ XF_TCPSIGNATURE, XFT_AUTH, "TCP MD5 Signature Option, RFC 2385",
tcp_signature_tdb_attach, tcp_signature_tdb_init,
@@ -1503,6 +1496,26 @@ ipsp_kern(int off, char **bufp, int len)
l += sprintf(buffer + l, "tunneling");
}
+ if (tdb->tdb_flags & TDBF_NOREPLAY)
+ {
+ if (i)
+ l += sprintf(buffer + l, ", ");
+ else
+ i = 1;
+
+ l += sprintf(buffer + l, "noreplay");
+ }
+
+ if (tdb->tdb_flags & TDBF_RANDOMPADDING)
+ {
+ if (i)
+ l += sprintf(buffer + l, ", ");
+ else
+ i = 1;
+
+ l += sprintf(buffer + l, "random padding");
+ }
+
l += sprintf(buffer + l, ">\n");
}
diff --git a/sys/netinet/ip_ipsp.h b/sys/netinet/ip_ipsp.h
index 417b08970ef..2efa37b7c3d 100644
--- a/sys/netinet/ip_ipsp.h
+++ b/sys/netinet/ip_ipsp.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_ipsp.h,v 1.59 2000/01/21 03:15:05 angelos Exp $ */
+/* $OpenBSD: ip_ipsp.h,v 1.60 2000/01/27 08:09:12 angelos Exp $ */
/*
* The authors of this code are John Ioannidis (ji@tla.org),
@@ -273,6 +273,9 @@ struct tdb /* tunnel descriptor block */
#define TDBF_SOFT_FIRSTUSE 0x00400 /* Soft expiration */
#define TDBF_PFS 0x00800 /* Ask for PFS from Key Mgmt. */
#define TDBF_TUNNELING 0x01000 /* Force IP-IP encapsulation */
+#define TDBF_NOREPLAY 0x02000 /* No replay counter present */
+#define TDBF_RANDOMPADDING 0x04000 /* Random data in the ESP padding */
+
u_int32_t tdb_flags; /* Flags related to this TDB */
TAILQ_ENTRY(tdb) tdb_expnext; /* Expiration cluster list link */
@@ -297,12 +300,12 @@ struct tdb /* tunnel descriptor block */
* tdb_exp_first_use <= curtime */
u_int32_t tdb_spi; /* SPI */
- u_int16_t tdb_amxkeylen; /* AH-old only */
+ u_int16_t tdb_amxkeylen; /* Raw authentication key length */
+ u_int16_t tdb_emxkeylen; /* Raw encryption key length */
u_int16_t tdb_ivlen; /* IV length */
u_int8_t tdb_sproto; /* IPsec protocol */
u_int8_t tdb_wnd; /* Replay window */
u_int8_t tdb_satype; /* SA type (RFC2367, PF_KEY) */
- u_int8_t tdb_FILLER; /* Padding */
union sockaddr_union tdb_dst; /* Destination address for this SA */
union sockaddr_union tdb_src; /* Source address for this SA */
@@ -313,7 +316,8 @@ struct tdb /* tunnel descriptor block */
u_int8_t *tdb_octx;
u_int8_t *tdb_srcid; /* Source ID for this SA */
u_int8_t *tdb_dstid; /* Destination ID for this SA */
- u_int8_t *tdb_amxkey; /* AH-old only */
+ u_int8_t *tdb_amxkey; /* Raw authentication key */
+ u_int8_t *tdb_emxkey; /* Raw encryption key */
union
{
@@ -367,6 +371,7 @@ struct auth_hash {
char *name;
u_int16_t keysize;
u_int16_t hashsize;
+ u_int16_t authsize;
u_int16_t ctxsize;
void (*Init)(void *);
void (*Update)(void *, u_int8_t *, u_int16_t);
@@ -409,11 +414,9 @@ struct xformsw
/* xform IDs */
#define XF_IP4 1 /* IP inside IP */
-#define XF_OLD_AH 2 /* RFCs 1828 & 1852 */
-#define XF_OLD_ESP 3 /* RFCs 1829 & 1851 */
-#define XF_NEW_AH 4 /* AH HMAC 96bits */
-#define XF_NEW_ESP 5 /* ESP + auth 96bits + replay counter */
-#define XF_TCPSIGNATURE 6 /* TCP MD5 Signature option, RFC 2358 */
+#define XF_AH 2 /* AH */
+#define XF_ESP 3 /* ESP */
+#define XF_TCPSIGNATURE 5 /* TCP MD5 Signature option, RFC 2358 */
/* xform attributes */
#define XFT_AUTH 0x0001
@@ -564,37 +567,39 @@ extern int etherip_output(struct mbuf *, struct tdb *, struct mbuf **,
int, int);
extern void etherip_input __P((struct mbuf *, ...));
-/* XF_OLD_AH */
-extern int ah_old_attach(void);
-extern int ah_old_init(struct tdb *, struct xformsw *, struct ipsecinit *);
-extern int ah_old_zeroize(struct tdb *);
-extern int ah_old_output(struct mbuf *, struct tdb *, struct mbuf **,
+/* XF_AH */
+extern int ah_attach(void);
+extern int ah_init(struct tdb *, struct xformsw *, struct ipsecinit *);
+extern int ah_zeroize(struct tdb *);
+extern int ah_output(struct mbuf *, struct tdb *, struct mbuf **,
int, int);
-extern struct mbuf *ah_old_input(struct mbuf *, struct tdb *, int, int);
+extern struct mbuf *ah_input(struct mbuf *, struct tdb *, int, int);
+extern int ah_sysctl(int *, u_int, void *, size_t *, void *, size_t);
-/* XF_NEW_AH */
-extern int ah_new_attach(void);
-extern int ah_new_init(struct tdb *, struct xformsw *, struct ipsecinit *);
-extern int ah_new_zeroize(struct tdb *);
-extern int ah_new_output(struct mbuf *, struct tdb *, struct mbuf **,
- int, int);
-extern struct mbuf *ah_new_input(struct mbuf *, struct tdb *, int, int);
+#ifdef INET
+extern void ah4_input __P((struct mbuf *, ...));
+#endif /* INET */
-/* XF_OLD_ESP */
-extern int esp_old_attach(void);
-extern int esp_old_init(struct tdb *, struct xformsw *, struct ipsecinit *);
-extern int esp_old_zeroize(struct tdb *);
-extern int esp_old_output(struct mbuf *, struct tdb *, struct mbuf **,
- int, int);
-extern struct mbuf *esp_old_input(struct mbuf *, struct tdb *, int, int);
+#ifdef INET6
+int ah6_input __P((struct mbuf **, int *, int));
+#endif /* INET6 */
-/* XF_NEW_ESP */
-extern int esp_new_attach(void);
-extern int esp_new_init(struct tdb *, struct xformsw *, struct ipsecinit *);
-extern int esp_new_zeroize(struct tdb *);
-extern int esp_new_output(struct mbuf *, struct tdb *, struct mbuf **,
- int, int);
-extern struct mbuf *esp_new_input(struct mbuf *, struct tdb *, int, int);
+/* XF_ESP */
+extern int esp_attach(void);
+extern int esp_init(struct tdb *, struct xformsw *, struct ipsecinit *);
+extern int esp_zeroize(struct tdb *);
+extern int esp_output(struct mbuf *, struct tdb *, struct mbuf **,
+ int, int);
+extern struct mbuf *esp_input(struct mbuf *, struct tdb *, int, int);
+extern int esp_sysctl(int *, u_int, void *, size_t *, void *, size_t);
+
+#ifdef INET
+extern void esp4_input __P((struct mbuf *, ...));
+#endif /* INET */
+
+#ifdef INET6
+int esp6_input __P((struct mbuf **, int *, int));
+#endif /* INET6 */
/* XF_TCPSIGNATURE */
extern int tcp_signature_tdb_attach __P((void));
diff --git a/sys/netinet/ip_xform.c b/sys/netinet/ip_xform.c
index ef678278e62..066992e2eb6 100644
--- a/sys/netinet/ip_xform.c
+++ b/sys/netinet/ip_xform.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_xform.c,v 1.4 1999/10/29 05:20:46 angelos Exp $ */
+/* $OpenBSD: ip_xform.c,v 1.5 2000/01/27 08:09:12 angelos Exp $ */
/*
* The authors of this code are John Ioannidis (ji@tla.org),
@@ -297,7 +297,7 @@ struct enc_xform enc_xform_skipjack = {
struct auth_hash auth_hash_hmac_md5_96 = {
SADB_AALG_MD5HMAC96, "HMAC-MD5-96",
- MD5HMAC96_KEYSIZE, AH_MD5_ALEN,
+ MD5HMAC96_KEYSIZE, AH_MD5_ALEN, AH_HMAC_HASHLEN,
sizeof(MD5_CTX),
(void (*) (void *)) MD5Init,
(void (*) (void *, u_int8_t *, u_int16_t)) MD5Update,
@@ -306,7 +306,7 @@ struct auth_hash auth_hash_hmac_md5_96 = {
struct auth_hash auth_hash_hmac_sha1_96 = {
SADB_AALG_SHA1HMAC96, "HMAC-SHA1-96",
- SHA1HMAC96_KEYSIZE, AH_SHA1_ALEN,
+ SHA1HMAC96_KEYSIZE, AH_SHA1_ALEN, AH_HMAC_HASHLEN,
sizeof(SHA1_CTX),
(void (*) (void *)) SHA1Init,
(void (*) (void *, u_int8_t *, u_int16_t)) SHA1Update,
@@ -315,7 +315,7 @@ struct auth_hash auth_hash_hmac_sha1_96 = {
struct auth_hash auth_hash_hmac_ripemd_160_96 = {
SADB_X_AALG_RIPEMD160HMAC96, "HMAC-RIPEMD-160-96",
- RIPEMD160HMAC96_KEYSIZE, AH_RMD160_ALEN,
+ RIPEMD160HMAC96_KEYSIZE, AH_RMD160_ALEN, AH_HMAC_HASHLEN,
sizeof(RMD160_CTX),
(void (*)(void *)) RMD160Init,
(void (*)(void *, u_int8_t *, u_int16_t)) RMD160Update,
@@ -324,7 +324,7 @@ struct auth_hash auth_hash_hmac_ripemd_160_96 = {
struct auth_hash auth_hash_key_md5 = {
SADB_X_AALG_MD5, "Keyed MD5",
- 0, AH_MD5_ALEN,
+ 0, AH_MD5_ALEN, AH_MD5_ALEN,
sizeof(MD5_CTX),
(void (*)(void *))MD5Init,
(void (*)(void *, u_int8_t *, u_int16_t))MD5Update,
@@ -333,7 +333,7 @@ struct auth_hash auth_hash_key_md5 = {
struct auth_hash auth_hash_key_sha1 = {
SADB_X_AALG_SHA1, "Keyed SHA1",
- 0, AH_SHA1_ALEN,
+ 0, AH_SHA1_ALEN, AH_SHA1_ALEN,
sizeof(SHA1_CTX),
(void (*)(void *))SHA1Init,
(void (*)(void *, u_int8_t *, u_int16_t))SHA1Update,
diff --git a/sys/netinet/ipsec_input.c b/sys/netinet/ipsec_input.c
index 0f6c75e0bd8..7249fbe5887 100644
--- a/sys/netinet/ipsec_input.c
+++ b/sys/netinet/ipsec_input.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ipsec_input.c,v 1.17 2000/01/25 17:18:59 espie Exp $ */
+/* $OpenBSD: ipsec_input.c,v 1.18 2000/01/27 08:09:12 angelos Exp $ */
/*
* The authors of this code are John Ioannidis (ji@tla.org),
@@ -106,9 +106,9 @@ int
ipsec_common_input(struct mbuf **m0, int skip, int protoff, int af, int sproto)
{
#define IPSEC_ISTAT(y,z) (sproto == IPPROTO_ESP ? (y)++ : (z)++)
-#define IPSEC_NAME (sproto == IPPROTO_ESP ? (af == AF_INET ? "esp_input()" :\
+#define IPSEC_NAME (sproto == IPPROTO_ESP ? (af == AF_INET ? "esp4_input()" :\
"esp6_input()") :\
- (af == AF_INET ? "ah_input()" :\
+ (af == AF_INET ? "ah4_input()" :\
"ah6_input()"))
union sockaddr_union src_address, dst_address, src2, dst2;
caddr_t sport = 0, dport = 0;
@@ -633,7 +633,7 @@ ah_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlen, void *newp,
#ifdef INET
/* IPv4 AH wrapper */
void
-ah_input(struct mbuf *m, ...)
+ah4_input(struct mbuf *m, ...)
{
struct ifqueue *ifq = &ipintrq;
struct mbuf *mp = m;
@@ -662,7 +662,7 @@ ah_input(struct mbuf *m, ...)
m_freem(mp);
ahstat.ahs_qfull++;
splx(s);
- DPRINTF(("ah_input(): dropped packet because of full IP queue\n"));
+ DPRINTF(("ah4_input(): dropped packet because of full IP queue\n"));
return;
}
@@ -673,7 +673,7 @@ ah_input(struct mbuf *m, ...)
/* IPv4 ESP wrapper */
void
-esp_input(struct mbuf *m, ...)
+esp4_input(struct mbuf *m, ...)
{
struct ifqueue *ifq = &ipintrq;
struct mbuf *mp = m;
@@ -702,7 +702,7 @@ esp_input(struct mbuf *m, ...)
m_freem(mp);
espstat.esps_qfull++;
splx(s);
- DPRINTF(("esp_input(): dropped packet because of full IP queue\n"));
+ DPRINTF(("esp4_input(): dropped packet because of full IP queue\n"));
return;
}