diff options
-rw-r--r-- | sys/conf/files | 8 | ||||
-rw-r--r-- | sys/net/pfkeyv2.c | 45 | ||||
-rw-r--r-- | sys/net/pfkeyv2.h | 26 | ||||
-rw-r--r-- | sys/netinet/in_proto.c | 8 | ||||
-rw-r--r-- | sys/netinet/ip_ah.c (renamed from sys/netinet/ip_ah_new.c) | 357 | ||||
-rw-r--r-- | sys/netinet/ip_ah.h | 42 | ||||
-rw-r--r-- | sys/netinet/ip_ah_old.c | 589 | ||||
-rw-r--r-- | sys/netinet/ip_esp.c (renamed from sys/netinet/ip_esp_new.c) | 398 | ||||
-rw-r--r-- | sys/netinet/ip_esp.h | 34 | ||||
-rw-r--r-- | sys/netinet/ip_esp_old.c | 811 | ||||
-rw-r--r-- | sys/netinet/ip_ipsp.c | 41 | ||||
-rw-r--r-- | sys/netinet/ip_ipsp.h | 77 | ||||
-rw-r--r-- | sys/netinet/ip_xform.c | 12 | ||||
-rw-r--r-- | sys/netinet/ipsec_input.c | 14 |
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; } |