diff options
author | Angelos D. Keromytis <angelos@cvs.openbsd.org> | 1999-02-24 22:33:08 +0000 |
---|---|---|
committer | Angelos D. Keromytis <angelos@cvs.openbsd.org> | 1999-02-24 22:33:08 +0000 |
commit | bc6ad109752ee01f946571f9488d7335d751b7fe (patch) | |
tree | 51a5f44fa5bf81542dfc5c8ad510f1f8cf4a6691 /sys/netinet | |
parent | 689ba6c5dcae1e6d1086d01cfc27fd19a8e11b03 (diff) |
Remove encap.h include; saner debugging printfs; fix buglets; work with
pfkeyv2.
Diffstat (limited to 'sys/netinet')
-rw-r--r-- | sys/netinet/in_pcb.c | 3 | ||||
-rw-r--r-- | sys/netinet/in_proto.c | 3 | ||||
-rw-r--r-- | sys/netinet/ip_ah.c | 134 | ||||
-rw-r--r-- | sys/netinet/ip_ah.h | 99 | ||||
-rw-r--r-- | sys/netinet/ip_ah_new.c | 455 | ||||
-rw-r--r-- | sys/netinet/ip_ah_old.c | 328 | ||||
-rw-r--r-- | sys/netinet/ip_esp.c | 128 | ||||
-rw-r--r-- | sys/netinet/ip_esp.h | 197 | ||||
-rw-r--r-- | sys/netinet/ip_esp_new.c | 787 | ||||
-rw-r--r-- | sys/netinet/ip_esp_old.c | 442 | ||||
-rw-r--r-- | sys/netinet/ip_ip4.c | 103 | ||||
-rw-r--r-- | sys/netinet/ip_ip4.h | 21 | ||||
-rw-r--r-- | sys/netinet/ip_ipsp.c | 747 | ||||
-rw-r--r-- | sys/netinet/ip_ipsp.h | 444 | ||||
-rw-r--r-- | sys/netinet/ip_output.c | 117 |
15 files changed, 1772 insertions, 2236 deletions
diff --git a/sys/netinet/in_pcb.c b/sys/netinet/in_pcb.c index b36fe6b55d3..24ec420bdd2 100644 --- a/sys/netinet/in_pcb.c +++ b/sys/netinet/in_pcb.c @@ -1,4 +1,4 @@ -/* $OpenBSD: in_pcb.c,v 1.29 1999/01/11 02:01:34 deraadt Exp $ */ +/* $OpenBSD: in_pcb.c,v 1.30 1999/02/24 22:32:57 angelos Exp $ */ /* $NetBSD: in_pcb.c,v 1.25 1996/02/13 23:41:53 christos Exp $ */ /* @@ -77,7 +77,6 @@ didn't get a copy, you may request one from <license@ipv6.nrl.navy.mil>. #endif /* INET6 */ #ifdef IPSEC -#include <net/encap.h> #include <netinet/ip_ipsp.h> extern int check_ipsec_policy __P((struct inpcb *, u_int32_t)); diff --git a/sys/netinet/in_proto.c b/sys/netinet/in_proto.c index 8da44bb90ed..3a1b928d7f8 100644 --- a/sys/netinet/in_proto.c +++ b/sys/netinet/in_proto.c @@ -1,4 +1,4 @@ -/* $OpenBSD: in_proto.c,v 1.10 1999/01/08 01:00:34 deraadt Exp $ */ +/* $OpenBSD: in_proto.c,v 1.11 1999/02/24 22:32:58 angelos Exp $ */ /* $NetBSD: in_proto.c,v 1.14 1996/02/18 18:58:32 christos Exp $ */ /* @@ -111,7 +111,6 @@ void iplinit __P((void)); #endif /* INET6 */ #ifdef IPSEC -#include <net/encap.h> #include <netinet/ip_ipsp.h> extern void ah_input __P((struct mbuf *, ...)); diff --git a/sys/netinet/ip_ah.c b/sys/netinet/ip_ah.c index 682f4fe3d75..4ae7499c04b 100644 --- a/sys/netinet/ip_ah.c +++ b/sys/netinet/ip_ah.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_ah.c,v 1.16 1998/06/10 23:57:13 provos Exp $ */ +/* $OpenBSD: ip_ah.c,v 1.17 1999/02/24 22:32:59 angelos Exp $ */ /* * The authors of this code are John Ioannidis (ji@tla.org), @@ -66,16 +66,21 @@ #include <sys/socketvar.h> #include <net/raw_cb.h> -#include <net/encap.h> #include <netinet/ip_ipsp.h> #include <netinet/ip_ah.h> -#include <sys/syslog.h> - #include "bpfilter.h" -void ah_input __P((struct mbuf *, int)); +extern struct ifnet enc_softc; + +#ifdef ENCDEBUG +#define DPRINTF(x) if (encdebug) printf x +#else +#define DPRINTF(x) +#endif + +void ah_input __P((struct mbuf *, int)); /* * ah_input gets called when we receive an packet with an AH. @@ -84,6 +89,7 @@ void ah_input __P((struct mbuf *, int)); void ah_input(register struct mbuf *m, int iphlen) { + union sockaddr_union sunion; struct ifqueue *ifq = NULL; struct ah_old *ahp, ahn; struct expiration *exp; @@ -103,13 +109,10 @@ ah_input(register struct mbuf *m, int iphlen) { if ((m = m_pullup(m, iphlen + AH_OLD_FLENGTH)) == 0) { -#ifdef ENCDEBUG - if (encdebug) - printf("ah_input(): (possibly too short) packet from %x to %x dropped\n", ipo->ip_src, ipo->ip_dst); -#endif /* ENCDEBUG */ ahstat.ahs_hdrops++; return; } + ipo = mtod(m, struct ip *); } @@ -121,11 +124,14 @@ ah_input(register struct mbuf *m, int iphlen) * IP packet ready to go through input processing. */ - tdbp = gettdb(ahp->ah_spi, ipo->ip_dst, IPPROTO_AH); + bzero(&sunion, sizeof(sunion)); + sunion.sin.sin_family = AF_INET; + sunion.sin.sin_len = sizeof(struct sockaddr_in); + sunion.sin.sin_addr = ipo->ip_dst; + tdbp = gettdb(ahp->ah_spi, &sunion, IPPROTO_AH); if (tdbp == NULL) { - if (encdebug) - log(LOG_ERR, "ah_input(): could not find SA for AH packet from %x to %x, spi %08x\n", ipo->ip_src, ipo->ip_dst, ntohl(ahp->ah_spi)); + DPRINTF(("ah_input(): could not find SA for packet from %s to %s, spi %08x\n", inet_ntoa4(ipo->ip_src), ipsp_address(sunion), ntohl(ahp->ah_spi))); m_freem(m); ahstat.ahs_notdb++; return; @@ -133,8 +139,7 @@ ah_input(register struct mbuf *m, int iphlen) if (tdbp->tdb_flags & TDBF_INVALID) { - if (encdebug) - log(LOG_ALERT, "ah_input(): attempted to use invalid AH SA %08x, packet %x->%x\n", ntohl(ahp->ah_spi), ipo->ip_src, ipo->ip_dst); + DPRINTF(("ah_input(): attempted to use invalid SA %08x, packet from %s to %s\n", ntohl(ahp->ah_spi), inet_ntoa4(ipo->ip_src), ipsp_address(sunion))); m_freem(m); ahstat.ahs_invalid++; return; @@ -142,8 +147,7 @@ ah_input(register struct mbuf *m, int iphlen) if (tdbp->tdb_xform == NULL) { - if (encdebug) - log(LOG_ALERT, "ah_input(): attempted to use uninitialized AH SA %08x, packet from %x to %x\n", ntohl(ahp->ah_spi), ipo->ip_src, ipo->ip_dst); + DPRINTF(("ah_input(): attempted to use uninitialized SA %08x, packet from %s to %s\n", ntohl(ahp->ah_spi), inet_ntoa4(ipo->ip_src), ipsp_address(sunion))); m_freem(m); ahstat.ahs_noxform++; return; @@ -159,21 +163,10 @@ ah_input(register struct mbuf *m, int iphlen) if (tdbp->tdb_flags & TDBF_FIRSTUSE) { exp = get_expiration(); - if (exp == (struct expiration *) NULL) - { - if (encdebug) - log(LOG_WARNING, - "ah_input(): out of memory for expiration timer\n"); - ahstat.ahs_hdrops++; - m_freem(m); - return; - } - - exp->exp_dst.s_addr = tdbp->tdb_dst.s_addr; + bcopy(&tdbp->tdb_dst, &exp->exp_dst, SA_LEN(&tdbp->tdb_dst.sa)); exp->exp_spi = tdbp->tdb_spi; exp->exp_sproto = tdbp->tdb_sproto; exp->exp_timeout = tdbp->tdb_first_use + tdbp->tdb_exp_first_use; - put_expiration(exp); } @@ -181,21 +174,10 @@ ah_input(register struct mbuf *m, int iphlen) (tdbp->tdb_soft_first_use <= tdbp->tdb_exp_first_use)) { exp = get_expiration(); - if (exp == (struct expiration *) NULL) - { - if (encdebug) - log(LOG_WARNING, - "ah_input(): out of memory for expiration timer\n"); - ahstat.ahs_hdrops++; - m_freem(m); - return; - } - - exp->exp_dst.s_addr = tdbp->tdb_dst.s_addr; + bcopy(&tdbp->tdb_dst, &exp->exp_dst, SA_LEN(&tdbp->tdb_dst.sa)); exp->exp_spi = tdbp->tdb_spi; exp->exp_sproto = tdbp->tdb_sproto; exp->exp_timeout = tdbp->tdb_first_use + tdbp->tdb_soft_first_use; - put_expiration(exp); } } @@ -206,8 +188,7 @@ ah_input(register struct mbuf *m, int iphlen) m = (*(tdbp->tdb_xform->xf_input))(m, tdbp); if (m == NULL) { - if (encdebug) - log(LOG_ALERT, "ah_input(): authentication failed for AH packet from %x to %x, spi %08x\n", ipn.ip_src, ipn.ip_dst, ntohl(ahn.ah_spi)); + DPRINTF(("ah_input(): authentication failed for AH packet from %s to %s, spi %08x\n", inet_ntoa4(ipn.ip_src), ipsp_address(sunion), ntohl(ahn.ah_spi))); ahstat.ahs_badkcr++; return; } @@ -218,48 +199,42 @@ ah_input(register struct mbuf *m, int iphlen) /* ipn will now contain the inner IP header */ m_copydata(m, ipo->ip_hl << 2, sizeof(struct ip), (caddr_t) &ipn); - /* Encapsulating SPI */ - if (tdbp->tdb_osrc.s_addr && tdbp->tdb_odst.s_addr) - { - if (tdbp->tdb_flags & TDBF_UNIQUE) - if ((ipn.ip_src.s_addr != ipo->ip_src.s_addr) || - (ipn.ip_dst.s_addr != ipo->ip_dst.s_addr)) - { - if (encdebug) - log(LOG_ALERT, "ah_input(): AH-tunnel with different internal addresses %x/%x, SA %08x/%x\n", ipo->ip_src, ipo->ip_dst, tdbp->tdb_spi, tdbp->tdb_dst); - m_freem(m); - ahstat.ahs_hdrops++; - return; - } - - /* - * XXX Here we should be checking that the inner IP addresses - * XXX are acceptable/authorized. - */ - } - else /* So we're paranoid */ + if (tdbp->tdb_flags & TDBF_UNIQUE) + if ((ipn.ip_src.s_addr != ipo->ip_src.s_addr) || + (ipn.ip_dst.s_addr != ipo->ip_dst.s_addr)) + { + DPRINTF(("ah_input(): AH-tunnel with different internal addresses %s->%s (%s->%s), SA %s/%08x\n", inet_ntoa4(ipo->ip_src), inet_ntoa4(ipo->ip_dst), inet_ntoa4(ipn.ip_src), ipsp_address(sunion), ipsp_address(tdbp->tdb_dst), ntohl(tdbp->tdb_spi))); + m_freem(m); + ahstat.ahs_hdrops++; + return; + } + + /* + * Check that the inner source address is the same as + * the proxy address, if available. + */ + if ((tdbp->tdb_proxy.sin.sin_addr.s_addr != INADDR_ANY) && + (ipn.ip_src.s_addr != tdbp->tdb_proxy.sin.sin_addr.s_addr)) { - if (encdebug) - log(LOG_ALERT, "ah_input(): AH-tunnel used when expecting AH-transport, SA %08x/%x\n", tdbp->tdb_spi, tdbp->tdb_dst); - m_freem(m); + DPRINTF(("ah_input(): inner source address %s doesn't correspond to expected proxy source %s, SA %s/%08x\n", inet_ntoa4(ipo->ip_src), ipsp_address(tdbp->tdb_proxy), ipsp_address(tdbp->tdb_dst), ntohl(tdbp->tdb_spi))); + m_free(m); ahstat.ahs_hdrops++; return; } } /* - * Check that the source address is an expected one, if we know what - * it's supposed to be. This avoids source address spoofing. + * Check that the outter source address is an expected one, if we know + * what it's supposed to be. This avoids source address spoofing. */ - if (tdbp->tdb_src.s_addr != INADDR_ANY) - if (ipo->ip_src.s_addr != tdbp->tdb_src.s_addr) - { - if (encdebug) - log(LOG_ALERT, "esp_input(): source address %x doesn't correspond to expected source %x, SA %08x/%x\n", ipo->ip_src, tdbp->tdb_src, tdbp->tdb_dst, tdbp->tdb_spi); - m_free(m); - ahstat.ahs_hdrops++; - return; - } + if ((tdbp->tdb_src.sin.sin_addr.s_addr != INADDR_ANY) && + (ipo->ip_src.s_addr != tdbp->tdb_src.sin.sin_addr.s_addr)) + { + DPRINTF(("ah_input(): source address %s doesn't correspond to expected source %s, SA %s/%08x\n", inet_ntoa4(ipo->ip_src), ipsp_address(tdbp->tdb_src), ipsp_address(tdbp->tdb_dst), ntohl(tdbp->tdb_spi))); + m_free(m); + ahstat.ahs_hdrops++; + return; + } /* Packet is authentic */ m->m_flags |= M_AUTH; @@ -279,7 +254,7 @@ ah_input(register struct mbuf *m, int iphlen) hdr.af = AF_INET; hdr.spi = tdbp->tdb_spi; - hdr.flags = m->m_flags & (M_AUTH|M_CONF|M_TUNNEL); + hdr.flags = m->m_flags & (M_AUTH|M_CONF); m0.m_next = m; m0.m_len = ENC_HDRLEN; @@ -303,10 +278,7 @@ ah_input(register struct mbuf *m, int iphlen) m_freem(m); ahstat.ahs_qfull++; splx(s); -#ifdef ENCDEBUG - if (encdebug) - printf("ah_input(): dropped packet because of full IP queue\n"); -#endif /* ENCDEBUG */ + DPRINTF(("ah_input(): dropped packet because of full IP queue\n")); return; } diff --git a/sys/netinet/ip_ah.h b/sys/netinet/ip_ah.h index 1df84dbb1b5..817f4eee5ad 100644 --- a/sys/netinet/ip_ah.h +++ b/sys/netinet/ip_ah.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_ah.h,v 1.13 1998/11/25 02:01:28 niklas Exp $ */ +/* $OpenBSD: ip_ah.h,v 1.14 1999/02/24 22:32:59 angelos Exp $ */ /* * The authors of this code are John Ioannidis (ji@tla.org), @@ -38,20 +38,6 @@ * Per RFC1826 (Atkinson, 1995) */ -#include <sys/md5k.h> -#include <netinet/ip_sha1.h> -#include <netinet/ip_rmd160.h> - -struct ah_hash { - int type; - char *name; - u_int16_t hashsize; - u_int16_t ctxsize; - void (*Init)(void *); - void (*Update)(void *, u_int8_t *, u_int16_t); - void (*Final)(u_int8_t *, void *); -}; - struct ah_old { u_int8_t ah_nh; /* Next header (protocol) */ @@ -63,13 +49,6 @@ struct ah_old #define AH_OLD_FLENGTH 8 /* size of fixed part */ -/* Authenticator lengths */ -#define AH_MD5_ALEN 16 -#define AH_SHA1_ALEN 20 -#define AH_RMD160_ALEN 20 - -#define AH_ALEN_MAX AH_SHA1_ALEN /* Keep this updated */ - struct ahstat { u_int32_t ahs_hdrops; /* packet shorter than header shows */ @@ -89,14 +68,6 @@ struct ahstat u_int32_t ahs_toobig; /* packet got larger than IP_MAXPACKET */ }; -#define AH_HMAC_HASHLEN 12 /* 96 bits of authenticator */ -#define AH_HMAC_RPLENGTH 4 /* 32 bits of replay counter */ -#define AH_HMAC_INITIAL_RPL 1 /* Replay counter initial value */ - -#define HMAC_IPAD_VAL 0x36 -#define HMAC_OPAD_VAL 0x5C -#define HMAC_BLOCK_LEN 64 - struct ah_new { u_int8_t ah_nh; /* Next header (protocol) */ @@ -109,72 +80,6 @@ struct ah_new #define AH_NEW_FLENGTH (sizeof(struct ah_new)) -struct ah_new_xencap -{ - u_int32_t amx_hash_algorithm; - int32_t amx_wnd; - u_int32_t amx_keylen; - u_int8_t amx_key[1]; -}; - -#define AH_NEW_XENCAP_LEN (3 * sizeof(u_int32_t)) - -struct ah_new_xdata -{ - u_int32_t amx_hash_algorithm; - int32_t amx_wnd; - u_int32_t amx_rpl; /* Replay counter */ - u_int32_t amx_bitmap; - struct ah_hash *amx_hash; - union - { - MD5_CTX amx_MD5_ictx; /* Internal key+padding */ - SHA1_CTX amx_SHA1_ictx; - RMD160_CTX amx_RMD160_ictx; - } amx_ictx; - union - { - MD5_CTX amx_MD5_octx; /* External key+padding */ - SHA1_CTX amx_SHA1_octx; - RMD160_CTX amx_RMD160_octx; - } amx_octx; -}; - -#define amx_md5_ictx amx_ictx.amx_MD5_ictx -#define amx_md5_octx amx_octx.amx_MD5_octx -#define amx_sha1_ictx amx_ictx.amx_SHA1_ictx -#define amx_sha1_octx amx_octx.amx_SHA1_octx -#define amx_rmd160_ictx amx_ictx.amx_RMD160_ictx -#define amx_rmd160_octx amx_octx.amx_RMD160_octx - -struct ah_old_xdata -{ - u_int32_t amx_hash_algorithm; - u_int32_t amx_keylen; /* Key material length */ - struct ah_hash *amx_hash; - union - { - MD5_CTX amx_MD5_ctx; - SHA1_CTX amx_SHA1_ctx; - } amx_ctx; - u_int8_t amx_key[1]; /* Key material */ -}; - -#define amx_md5_ctx amx_ctx.amx_MD5_ctx -#define amx_sha1_ctx amx_ctx.amx_SHA1_ctx - -struct ah_old_xencap -{ - u_int32_t amx_hash_algorithm; - u_int32_t amx_keylen; - u_int8_t amx_key[1]; -}; - -#define AH_OLD_XENCAP_LEN (2 * sizeof(u_int32_t)) - -#define AH_HMAC_IPAD_VAL 0x36 -#define AH_HMAC_OPAD_VAL 0x5C - #ifdef _KERNEL struct ahstat ahstat; -#endif +#endif /* _KERNEL */ diff --git a/sys/netinet/ip_ah_new.c b/sys/netinet/ip_ah_new.c index a6061bfc4d7..ad6cfc3463e 100644 --- a/sys/netinet/ip_ah_new.c +++ b/sys/netinet/ip_ah_new.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_ah_new.c,v 1.21 1999/01/11 22:52:09 deraadt Exp $ */ +/* $OpenBSD: ip_ah_new.c,v 1.22 1999/02/24 22:32:59 angelos Exp $ */ /* * The authors of this code are John Ioannidis (ji@tla.org), @@ -65,10 +65,9 @@ #include <netinet/ip_var.h> #include <netinet/ip_icmp.h> -#include <net/encap.h> - #include <netinet/ip_ipsp.h> #include <netinet/ip_ah.h> +#include <net/pfkeyv2.h> #ifdef ENCDEBUG #define DPRINTF(x) if (encdebug) printf x @@ -76,25 +75,23 @@ #define DPRINTF(x) #endif -extern void encap_sendnotify(int, struct tdb *, void *); - -struct ah_hash ah_new_hash[] = { - { ALG_AUTH_MD5, "HMAC-MD5-96", - AH_MD5_ALEN, +struct auth_hash ah_new_hash[] = { + { SADB_AALG_MD5HMAC96, "HMAC-MD5-96", + MD5HMAC96_KEYSIZE, AH_MD5_ALEN, sizeof(MD5_CTX), (void (*)(void *)) MD5Init, (void (*)(void *, u_int8_t *, u_int16_t)) MD5Update, (void (*)(u_int8_t *, void *)) MD5Final }, - { ALG_AUTH_SHA1, "HMAC-SHA1-96", - AH_SHA1_ALEN, + { SADB_AALG_SHA1HMAC96, "HMAC-SHA1-96", + SHA1HMAC96_KEYSIZE, AH_SHA1_ALEN, sizeof(SHA1_CTX), (void (*)(void *)) SHA1Init, (void (*)(void *, u_int8_t *, u_int16_t)) SHA1Update, (void (*)(u_int8_t *, void *)) SHA1Final }, - { ALG_AUTH_RMD160, "HMAC-RIPEMD-160-96", - AH_RMD160_ALEN, + { SADB_AALG_X_RIPEMD160HMAC96, "HMAC-RIPEMD-160-96", + RIPEMD160HMAC96_KEYSIZE, AH_RMD160_ALEN, sizeof(RMD160_CTX), (void (*)(void *)) RMD160Init, (void (*)(void *, u_int8_t *, u_int16_t)) RMD160Update, @@ -110,127 +107,66 @@ struct ah_hash ah_new_hash[] = { int ah_new_attach() { - DPRINTF(("ah_new_attach(): setting up\n")); return 0; } /* - * ah_new_init() is called when an SPI is being set up. It interprets the - * encap_msghdr present in m, and sets up the transformation data. + * ah_new_init() is called when an SPI is being set up. */ int -ah_new_init(struct tdb *tdbp, struct xformsw *xsp, struct mbuf *m) +ah_new_init(struct tdb *tdbp, struct xformsw *xsp, struct ipsecinit *ii) { - struct ah_new_xdata *xd; - struct ah_new_xencap txd; - struct encap_msghdr *em; - struct ah_hash *thash; - caddr_t buffer = NULL; - int blocklen, i; - - if (m->m_len < ENCAP_MSG_FIXED_LEN) - { - if ((m = m_pullup(m, ENCAP_MSG_FIXED_LEN)) == NULL) - { - DPRINTF(("ah_new_init(): m_pullup failed\n")); - return ENOBUFS; - } - } + struct auth_hash *thash = NULL; + int i; - em = mtod(m, struct encap_msghdr *); - if (em->em_msglen - EMT_SETSPI_FLEN <= AH_NEW_XENCAP_LEN) - { - DPRINTF(("ah_new_init() initialization failed\n")); - return EINVAL; - } - - /* Just copy the standard fields */ - m_copydata(m, EMT_SETSPI_FLEN, AH_NEW_XENCAP_LEN, (caddr_t) &txd); + for (i = sizeof(ah_new_hash) / sizeof(struct auth_hash) - 1; + i >= 0; i--) + if (ii->ii_authalg == ah_new_hash[i].type) + break; - /* Check whether the hash algorithm is supported */ - for (i = sizeof(ah_new_hash) / sizeof(struct ah_hash) - 1; i >= 0; i--) - if (txd.amx_hash_algorithm == ah_new_hash[i].type) - break; if (i < 0) { - DPRINTF(("ah_new_init(): unsupported authentication algorithm %d specified\n", txd.amx_hash_algorithm)); + DPRINTF(("ah_new_init(): unsupported authentication algorithm %d specified\n", ii->ii_authalg)); return EINVAL; } - DPRINTF(("ah_new_init(): initalized TDB with hash algorithm %d: %s\n", - txd.amx_hash_algorithm, ah_new_hash[i].name)); + thash = &ah_new_hash[i]; - blocklen = HMAC_BLOCK_LEN; - if (txd.amx_keylen + EMT_SETSPI_FLEN + AH_NEW_XENCAP_LEN != em->em_msglen) + if (ii->ii_authkeylen != thash->keysize) { - DPRINTF(("ah_new_init(): message length (%d) doesn't match\n", - em->em_msglen)); + DPRINTF(("ah_new_init(): keylength %d doesn't match algorithm %s keysize (%d)\n", ii->ii_authkeylen, thash->name, thash->keysize)); return EINVAL; } - MALLOC(tdbp->tdb_xdata, caddr_t, sizeof(struct ah_new_xdata), - M_XDATA, M_WAITOK); - if (tdbp->tdb_xdata == NULL) - { - DPRINTF(("ah_new_init(): MALLOC failed\n")); - return ENOBUFS; - } - - MALLOC(buffer, caddr_t, - (txd.amx_keylen < blocklen ? blocklen : txd.amx_keylen), - M_TEMP, M_WAITOK); - if (buffer == NULL) - { - DPRINTF(("ah_new_init(): MALLOC failed\n")); - free(tdbp->tdb_xdata, M_XDATA); - return ENOBUFS; - } - - bzero(buffer, (txd.amx_keylen < blocklen ? blocklen : txd.amx_keylen)); - bzero(tdbp->tdb_xdata, sizeof(struct ah_new_xdata)); - xd = (struct ah_new_xdata *) tdbp->tdb_xdata; - - /* Copy the key to the buffer */ - m_copydata(m, EMT_SETSPI_FLEN + AH_NEW_XENCAP_LEN, txd.amx_keylen, buffer); - - xd->amx_hash = thash; - /* Shorten the key if necessary */ - if (txd.amx_keylen > blocklen) - { - xd->amx_hash->Init(&(xd->amx_ictx)); - xd->amx_hash->Update(&(xd->amx_ictx), buffer, txd.amx_keylen); - bzero(buffer, - (txd.amx_keylen < blocklen ? blocklen : txd.amx_keylen)); - xd->amx_hash->Final(buffer, &(xd->amx_ictx)); - } - - /* Pointer to the transform */ tdbp->tdb_xform = xsp; + tdbp->tdb_authalgxform = thash; + tdbp->tdb_bitmap = 0; + tdbp->tdb_rpl = AH_HMAC_INITIAL_RPL; - /* Pass name of auth algorithm for kernfs */ - tdbp->tdb_authname = xd->amx_hash->name; - - xd->amx_hash_algorithm = txd.amx_hash_algorithm; - xd->amx_rpl = AH_HMAC_INITIAL_RPL; - xd->amx_wnd = txd.amx_wnd; - xd->amx_bitmap = 0; + DPRINTF(("ah_new_init(): initialized TDB with hash algorithm %s\n", + thash->name)); /* Precompute the I and O pads of the HMAC */ - for (i = 0; i < blocklen; i++) - buffer[i] ^= HMAC_IPAD_VAL; - - xd->amx_hash->Init(&(xd->amx_ictx)); - xd->amx_hash->Update(&(xd->amx_ictx), buffer, blocklen); - - for (i = 0; i < blocklen; i++) - buffer[i] ^= (HMAC_IPAD_VAL ^ HMAC_OPAD_VAL); - - xd->amx_hash->Init(&(xd->amx_octx)); - xd->amx_hash->Update(&(xd->amx_octx), buffer, blocklen); - - bzero(buffer, blocklen); /* paranoid */ - free(buffer, M_TEMP); + 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 */ @@ -241,12 +177,18 @@ ah_new_init(struct tdb *tdbp, struct xformsw *xsp, struct mbuf *m) int ah_new_zeroize(struct tdb *tdbp) { - DPRINTF(("ah_new_zeroize(): freeing memory\n")); - if (tdbp->tdb_xdata) + if (tdbp->tdb_ictx) { - FREE(tdbp->tdb_xdata, M_XDATA); - tdbp->tdb_xdata = NULL; + FREE(tdbp->tdb_ictx, M_XDATA); + tdbp->tdb_ictx = NULL; } + + if (tdbp->tdb_octx) + { + FREE(tdbp->tdb_octx, M_XDATA); + tdbp->tdb_octx = NULL; + } + return 0; } @@ -258,7 +200,7 @@ ah_new_zeroize(struct tdb *tdbp) struct mbuf * ah_new_input(struct mbuf *m, struct tdb *tdb) { - struct ah_new_xdata *xd; + struct auth_hash *ahx = (struct auth_hash *) tdb->tdb_authalgxform; struct ip *ip, ipo; struct ah_new *aho, *ah; int ohlen, len, count, off, errc; @@ -273,9 +215,6 @@ ah_new_input(struct mbuf *m, struct tdb *tdb) u_char buffer[40]; aho = (struct ah_new *) buffer; - - xd = (struct ah_new_xdata *) tdb->tdb_xdata; - ohlen = sizeof(struct ip) + AH_NEW_FLENGTH; if (m->m_len < ohlen) @@ -310,29 +249,57 @@ ah_new_input(struct mbuf *m, struct tdb *tdb) if (ah->ah_hl * sizeof(u_int32_t) != AH_HMAC_HASHLEN + AH_HMAC_RPLENGTH) { - DPRINTF(("ah_new_input(): bad authenticator length for packet from %x to %x, spi %08x\n", ip->ip_src, ip->ip_dst, ntohl(ah->ah_spi))); + DPRINTF(("ah_new_input(): bad authenticator length for packet from %s to %s, spi %08x\n", inet_ntoa4(ip->ip_src), inet_ntoa4(ip->ip_dst), ntohl(ah->ah_spi))); ahstat.ahs_badauthl++; m_freem(m); return NULL; } + /* Update the counters */ + tdb->tdb_cur_bytes += ip->ip_len - (ip->ip_hl << 2) - + ah->ah_hl * sizeof(u_int32_t); + ahstat.ahs_ibytes += ip->ip_len - (ip->ip_hl << 2) - + ah->ah_hl * sizeof(u_int32_t); + + /* Hard expiration */ + if ((tdb->tdb_flags & TDBF_BYTES) && + (tdb->tdb_cur_bytes >= tdb->tdb_exp_bytes)) + { +/* XXX + encap_sendnotify(NOTIFY_HARD_EXPIRE, tdb, NULL); +*/ + tdb_delete(tdb, 0); + m_freem(m); + return NULL; + } + + /* Notify on expiration */ + if ((tdb->tdb_flags & TDBF_SOFT_BYTES) && + (tdb->tdb_cur_bytes >= tdb->tdb_soft_bytes)) + { +/* XXX + encap_sendnotify(NOTIFY_SOFT_EXPIRE, tdb, NULL); +*/ + tdb->tdb_flags &= ~TDBF_SOFT_BYTES; /* Turn off checking */ + } + /* Replay window checking */ - if (xd->amx_wnd >= 0) + if (tdb->tdb_wnd > 0) { btsx = ntohl(ah->ah_rpl); - if ((errc = checkreplaywindow32(btsx, 0, &(xd->amx_rpl), xd->amx_wnd, - &(xd->amx_bitmap))) != 0) + if ((errc = checkreplaywindow32(btsx, 0, &(tdb->tdb_rpl), tdb->tdb_wnd, + &(tdb->tdb_bitmap))) != 0) { switch(errc) { case 1: - DPRINTF(("ah_new_input(): replay counter wrapped for packets from %x to %x, spi %08x\n", ip->ip_src, ip->ip_dst, ntohl(ah->ah_spi))); + DPRINTF(("ah_new_input(): replay counter wrapped for packets from %s to %s, spi %08x\n", inet_ntoa4(ip->ip_src), inet_ntoa4(ip->ip_dst), ntohl(ah->ah_spi))); ahstat.ahs_wrap++; break; case 2: case 3: - DPRINTF(("ah_new_input(): duplicate packet received, %x->%x spi %08x\n", ip->ip_src, ip->ip_dst, ntohl(ah->ah_spi))); + DPRINTF(("ah_new_input(): duplicate packet received from %s to %s, spi %08x\n", inet_ntoa4(ip->ip_src), inet_ntoa4(ip->ip_dst), ntohl(ah->ah_spi))); ahstat.ahs_replay++; break; } @@ -351,8 +318,8 @@ ah_new_input(struct mbuf *m, struct tdb *tdb) ipo.ip_ttl = 0; ipo.ip_sum = 0; - bcopy(&(xd->amx_ictx), &ctx, xd->amx_hash->ctxsize); - xd->amx_hash->Update(&ctx, (unsigned char *) &ipo, sizeof(struct ip)); + 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)) @@ -362,13 +329,13 @@ ah_new_input(struct mbuf *m, struct tdb *tdb) switch (optval) { case IPOPT_EOL: - xd->amx_hash->Update(&ctx, ipseczeroes, 1); + ahx->Update(&ctx, ipseczeroes, 1); off = ip->ip_hl << 2; break; case IPOPT_NOP: - xd->amx_hash->Update(&ctx, ipseczeroes, 1); + ahx->Update(&ctx, ipseczeroes, 1); off++; break; @@ -378,7 +345,7 @@ ah_new_input(struct mbuf *m, struct tdb *tdb) case 134: optval = ((u_int8_t *) ip)[off + 1]; - xd->amx_hash->Update(&ctx, (u_int8_t *) ip + off, optval); + ahx->Update(&ctx, (u_int8_t *) ip + off, optval); off += optval; break; @@ -386,16 +353,15 @@ ah_new_input(struct mbuf *m, struct tdb *tdb) default: optval = ((u_int8_t *) ip)[off + 1]; - xd->amx_hash->Update(&ctx, ipseczeroes, optval); + ahx->Update(&ctx, ipseczeroes, optval); off += optval; break; } } - xd->amx_hash->Update(&ctx, (unsigned char *) ah, AH_NEW_FLENGTH - - AH_HMAC_HASHLEN); - xd->amx_hash->Update(&ctx, ipseczeroes, AH_HMAC_HASHLEN); + ahx->Update(&ctx, (unsigned char *) ah, AH_NEW_FLENGTH - AH_HMAC_HASHLEN); + ahx->Update(&ctx, ipseczeroes, AH_HMAC_HASHLEN); /* * Code shamelessly stolen from m_copydata @@ -408,7 +374,7 @@ ah_new_input(struct mbuf *m, struct tdb *tdb) { if (m0 == 0) { - DPRINTF(("ah_new_input(): bad mbuf chain for packet from %x to %x, spi %08x\n", ip->ip_src, ip->ip_dst, ntohl(ah->ah_spi))); + DPRINTF(("ah_new_input(): bad mbuf chain for packet from %s to %s, spi %08x\n", inet_ntoa4(ip->ip_src), inet_ntoa4(ip->ip_dst), ntohl(ah->ah_spi))); ahstat.ahs_hdrops++; m_freem(m); return NULL; @@ -425,7 +391,7 @@ ah_new_input(struct mbuf *m, struct tdb *tdb) { if (m0 == 0) { - DPRINTF(("ah_new_input(): bad mbuf chain for packet from %x to %x, spi %08x\n", ip->ip_src, ip->ip_dst, ntohl(ah->ah_spi))); + DPRINTF(("ah_new_input(): bad mbuf chain for packet from %s to %s, spi %08x\n", inet_ntoa4(ip->ip_src), inet_ntoa4(ip->ip_dst), ntohl(ah->ah_spi))); ahstat.ahs_hdrops++; m_freem(m); return NULL; @@ -433,36 +399,21 @@ ah_new_input(struct mbuf *m, struct tdb *tdb) count = min(m0->m_len - off, len); - xd->amx_hash->Update(&ctx, mtod(m0, unsigned char *) + off, count); + ahx->Update(&ctx, mtod(m0, unsigned char *) + off, count); len -= count; off = 0; m0 = m0->m_next; } - xd->amx_hash->Final((unsigned char *) (aho->ah_data), &ctx); - bcopy(&(xd->amx_octx), &ctx, xd->amx_hash->ctxsize); - xd->amx_hash->Update(&ctx, (unsigned char *) (aho->ah_data), - xd->amx_hash->hashsize); - xd->amx_hash->Final((unsigned char *) (aho->ah_data), &ctx); + ahx->Final((unsigned char *) (aho->ah_data), &ctx); + bcopy(tdb->tdb_octx, &ctx, ahx->ctxsize); + ahx->Update(&ctx, (unsigned char *) (aho->ah_data), ahx->hashsize); + ahx->Final((unsigned char *) (aho->ah_data), &ctx); if (bcmp(aho->ah_data, ah->ah_data, AH_HMAC_HASHLEN)) { - DPRINTF(("ah_new_input(): authentication failed for packet from %x to %x, spi %08x\n", ip->ip_src, ip->ip_dst, ntohl(ah->ah_spi))); -#ifdef ENCDEBUG - if (encdebug) - { - printf("Received authenticator: "); - for (off = 0; off < AH_HMAC_HASHLEN; off++) - printf("%02x ", ah->ah_data[off]); - printf("\n"); - - printf("Computed authenticator: "); - for (off = 0; off < AH_HMAC_HASHLEN; off++) - printf("%02x ", aho->ah_data[off]); - printf("\n"); - } -#endif + DPRINTF(("ah_new_input(): authentication failed for packet from %s to %s, spi %08x\n", inet_ntoa4(ip->ip_src), inet_ntoa4(ip->ip_dst), ntohl(ah->ah_spi))); ahstat.ahs_badauth++; m_freem(m); return NULL; @@ -492,44 +443,6 @@ ah_new_input(struct mbuf *m, struct tdb *tdb) ip->ip_sum = in_cksum(m, (ip->ip_hl << 2)); - /* Update the counters */ - tdb->tdb_cur_packets++; - tdb->tdb_cur_bytes += ntohs(ip->ip_len) - (ip->ip_hl << 2); - ahstat.ahs_ibytes += ntohs(ip->ip_len) - (ip->ip_hl << 2); - - /* Notify on expiration */ - if (tdb->tdb_flags & TDBF_SOFT_PACKETS) - { - if (tdb->tdb_cur_packets >= tdb->tdb_soft_packets) - { - encap_sendnotify(NOTIFY_SOFT_EXPIRE, tdb, NULL); - tdb->tdb_flags &= ~TDBF_SOFT_PACKETS; - } - else - if (tdb->tdb_flags & TDBF_SOFT_BYTES) - if (tdb->tdb_cur_bytes >= tdb->tdb_soft_bytes) - { - encap_sendnotify(NOTIFY_SOFT_EXPIRE, tdb, NULL); - tdb->tdb_flags &= ~TDBF_SOFT_BYTES; - } - } - - if (tdb->tdb_flags & TDBF_PACKETS) - { - if (tdb->tdb_cur_packets >= tdb->tdb_exp_packets) - { - encap_sendnotify(NOTIFY_HARD_EXPIRE, tdb, NULL); - tdb_delete(tdb, 0); - } - else - if (tdb->tdb_flags & TDBF_BYTES) - if (tdb->tdb_cur_bytes >= tdb->tdb_exp_bytes) - { - encap_sendnotify(NOTIFY_HARD_EXPIRE, tdb, NULL); - tdb_delete(tdb, 0); - } - } - return m; } @@ -537,40 +450,37 @@ int ah_new_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb, struct mbuf **mp) { - struct ah_new_xdata *xd; + struct auth_hash *ahx = (struct auth_hash *) tdb->tdb_authalgxform; struct ip *ip, ipo; struct ah_new aho, *ah; - register int len, off, count; - register struct mbuf *m0; + register int len, off, count, ilen; union { MD5_CTX md5ctx; SHA1_CTX sha1ctx; RMD160_CTX rmd160ctx; } ctx; - int ilen, ohlen; u_int8_t optval; - u_char buffer[AH_ALEN_MAX], opts[40]; + u_char opts[40]; ahstat.ahs_output++; m = m_pullup(m, sizeof(struct ip)); if (m == NULL) { - DPRINTF(("ah_new_output(): m_pullup() failed, SA %x/%08x\n", - tdb->tdb_dst, ntohl(tdb->tdb_spi))); + DPRINTF(("ah_new_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 *); - xd = (struct ah_new_xdata *) tdb->tdb_xdata; - if ((ip->ip_hl << 2) > sizeof(struct ip)) { if ((m = m_pullup(m, ip->ip_hl << 2)) == NULL) { - DPRINTF(("ah_new_output(): m_pullup() failed, SA &x/%08x\n", - tdb->tdb_dst, ntohl(tdb->tdb_spi))); + DPRINTF(("ah_new_output(): m_pullup() failed, SA %s/%08x\n", + ipsp_address(tdb->tdb_dst), + ntohl(tdb->tdb_spi))); ahstat.ahs_hdrops++; return ENOBUFS; } @@ -578,18 +488,44 @@ ah_new_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb, ip = mtod(m, struct ip *); } + /* Update the counters */ + tdb->tdb_cur_bytes += ntohs(ip->ip_len) - (ip->ip_hl << 2); + ahstat.ahs_obytes += ntohs(ip->ip_len) - (ip->ip_hl << 2); + + /* Hard expiration */ + if ((tdb->tdb_flags & TDBF_BYTES) && + (tdb->tdb_cur_bytes >= tdb->tdb_exp_bytes)) + { +/* XXX + encap_sendnotify(NOTIFY_HARD_EXPIRE, tdb, NULL); +*/ + tdb_delete(tdb, 0); + m_freem(m); + return EINVAL; + } + + /* Notify on expiration */ + if ((tdb->tdb_flags & TDBF_SOFT_BYTES) && + (tdb->tdb_cur_bytes >= tdb->tdb_soft_bytes)) + { +/* XXX + encap_sendnotify(NOTIFY_SOFT_EXPIRE, tdb, NULL); +*/ + tdb->tdb_flags &= ~TDBF_SOFT_BYTES; /* Turn off checking */ + } + /* Save options */ m_copydata(m, sizeof(struct ip), (ip->ip_hl << 2) - sizeof(struct ip), (caddr_t) opts); - DPRINTF(("ah_new_output(): using hash algorithm %s\n", xd->amx_hash->name)); + DPRINTF(("ah_new_output(): using hash algorithm %s\n", ahx->name)); ilen = ntohs(ip->ip_len); - ohlen = AH_NEW_FLENGTH; - if (ohlen + ilen > IP_MAXPACKET) { - DPRINTF(("ah_new_output(): packet in SA %x/%0x8 got too big\n", - tdb->tdb_dst, ntohl(tdb->tdb_spi))); + if (AH_NEW_FLENGTH + ilen > IP_MAXPACKET) + { + DPRINTF(("ah_new_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; @@ -598,7 +534,7 @@ ah_new_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb, ipo.ip_v = IPVERSION; ipo.ip_hl = ip->ip_hl; ipo.ip_tos = 0; - ipo.ip_len = htons(ohlen + ilen); + ipo.ip_len = htons(AH_NEW_FLENGTH + ilen); ipo.ip_id = ip->ip_id; ipo.ip_off = 0; ipo.ip_ttl = 0; @@ -614,19 +550,19 @@ ah_new_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb, aho.ah_rv = 0; aho.ah_spi = tdb->tdb_spi; - if (xd->amx_rpl == 0) + if (tdb->tdb_rpl == 0) { - DPRINTF(("ah_new_output(): SA %x/%0x8 should have expired\n", - tdb->tdb_dst, ntohl(tdb->tdb_spi))); + DPRINTF(("ah_new_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; } - aho.ah_rpl = htonl(xd->amx_rpl++); + aho.ah_rpl = htonl(tdb->tdb_rpl++); - bcopy((caddr_t)&(xd->amx_ictx), (caddr_t)&ctx, xd->amx_hash->ctxsize); - xd->amx_hash->Update(&ctx, (unsigned char *) &ipo, sizeof(struct ip)); + bcopy(tdb->tdb_ictx, (caddr_t)&ctx, ahx->ctxsize); + ahx->Update(&ctx, (unsigned char *) &ipo, sizeof(struct ip)); /* Options */ if ((ip->ip_hl << 2) > sizeof(struct ip)) @@ -636,13 +572,13 @@ ah_new_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb, switch (optval) { case IPOPT_EOL: - xd->amx_hash->Update(&ctx, ipseczeroes, 1); + ahx->Update(&ctx, ipseczeroes, 1); off = ip->ip_hl << 2; break; case IPOPT_NOP: - xd->amx_hash->Update(&ctx, ipseczeroes, 1); + ahx->Update(&ctx, ipseczeroes, 1); off++; break; @@ -652,7 +588,7 @@ ah_new_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb, case 134: optval = ((u_int8_t *) ip)[off + 1]; - xd->amx_hash->Update(&ctx, (u_int8_t *) ip + off, optval); + ahx->Update(&ctx, (u_int8_t *) ip + off, optval); off += optval; break; @@ -660,14 +596,14 @@ ah_new_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb, default: optval = ((u_int8_t *) ip)[off + 1]; - xd->amx_hash->Update(&ctx, ipseczeroes, optval); + ahx->Update(&ctx, ipseczeroes, optval); off += optval; break; } } - xd->amx_hash->Update(&ctx, (unsigned char *) &aho, AH_NEW_FLENGTH); + ahx->Update(&ctx, (unsigned char *) &aho, AH_NEW_FLENGTH); off = ip->ip_hl << 2; @@ -676,44 +612,46 @@ ah_new_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb, */ len = m->m_pkthdr.len - off; - m0 = m; + *mp = m; while (len > 0) { - if (m0 == 0) + if ((*mp) == 0) { - DPRINTF(("ah_new_output(): bad mbuf chain for packet from %x to %x, spi %08x\n", ipo.ip_src, ipo.ip_dst, ntohl(tdb->tdb_spi))); + DPRINTF(("ah_new_output(): 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 EMSGSIZE; } - count = min(m0->m_len - off, len); + count = min((*mp)->m_len - off, len); - xd->amx_hash->Update(&ctx, mtod(m0, unsigned char *) + off, count); + ahx->Update(&ctx, mtod(*mp, unsigned char *) + off, count); len -= count; off = 0; - m0 = m0->m_next; + *mp = (*mp)->m_next; } + *mp = NULL; + 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); + M_PREPEND(m, AH_NEW_FLENGTH, M_DONTWAIT); if (m == NULL) { - DPRINTF(("ah_new_output(): M_PREPEND() failed for packet from %x to %x, spi %08x\n", ipo.ip_src, ipo.ip_dst, ntohl(tdb->tdb_spi))); + DPRINTF(("ah_new_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)); + m = m_pullup(m, AH_NEW_FLENGTH + (ipo.ip_hl << 2)); if (m == NULL) { - DPRINTF(("ah_new_output(): m_pullup() failed for packet from %x to %x, spi %08x\n", ipo.ip_src, ipo.ip_dst, ntohl(tdb->tdb_spi))); + DPRINTF(("ah_new_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; } @@ -727,58 +665,19 @@ ah_new_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb, ah->ah_spi = aho.ah_spi; ah->ah_rpl = aho.ah_rpl; - xd->amx_hash->Final(buffer, &ctx); - bcopy(&(xd->amx_octx), &ctx, xd->amx_hash->ctxsize); - xd->amx_hash->Update(&ctx, buffer, xd->amx_hash->hashsize); - xd->amx_hash->Final(buffer, &ctx); - /* Restore the options */ - m_copyback(m, sizeof(struct ip), (ip->ip_hl << 2) - sizeof(struct ip), - (caddr_t) opts); + bcopy(opts, (caddr_t) (ip + 1), (ip->ip_hl << 2) - sizeof(struct ip)); + + /* Finish computing the authenticator */ + ahx->Final(opts, &ctx); + bcopy(tdb->tdb_octx, &ctx, ahx->ctxsize); + ahx->Update(&ctx, opts, ahx->hashsize); + ahx->Final(opts, &ctx); /* Copy the authenticator */ - bcopy(buffer, ah->ah_data, AH_HMAC_HASHLEN); + bcopy(opts, ah->ah_data, AH_HMAC_HASHLEN); *mp = m; - /* Update the counters */ - tdb->tdb_cur_packets++; - tdb->tdb_cur_bytes += ntohs(ip->ip_len) - (ip->ip_hl << 2) - - AH_NEW_FLENGTH; - ahstat.ahs_obytes += ntohs(ip->ip_len) - (ip->ip_hl << 2) - AH_NEW_FLENGTH; - - /* Notify on expiration */ - if (tdb->tdb_flags & TDBF_SOFT_PACKETS) - { - if (tdb->tdb_cur_packets >= tdb->tdb_soft_packets) - { - encap_sendnotify(NOTIFY_SOFT_EXPIRE, tdb, NULL); - tdb->tdb_flags &= ~TDBF_SOFT_PACKETS; - } - else - if (tdb->tdb_flags & TDBF_SOFT_BYTES) - if (tdb->tdb_cur_bytes >= tdb->tdb_soft_bytes) - { - encap_sendnotify(NOTIFY_SOFT_EXPIRE, tdb, NULL); - tdb->tdb_flags &= ~TDBF_SOFT_BYTES; - } - } - - if (tdb->tdb_flags & TDBF_PACKETS) - { - if (tdb->tdb_cur_packets >= tdb->tdb_exp_packets) - { - encap_sendnotify(NOTIFY_HARD_EXPIRE, tdb, NULL); - tdb_delete(tdb, 0); - } - else - if (tdb->tdb_flags & TDBF_BYTES) - if (tdb->tdb_cur_bytes >= tdb->tdb_exp_bytes) - { - encap_sendnotify(NOTIFY_HARD_EXPIRE, tdb, NULL); - tdb_delete(tdb, 0); - } - } - return 0; } diff --git a/sys/netinet/ip_ah_old.c b/sys/netinet/ip_ah_old.c index 23ea072b899..4102de90b94 100644 --- a/sys/netinet/ip_ah_old.c +++ b/sys/netinet/ip_ah_old.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_ah_old.c,v 1.18 1999/01/11 22:52:09 deraadt Exp $ */ +/* $OpenBSD: ip_ah_old.c,v 1.19 1999/02/24 22:33:00 angelos Exp $ */ /* * The authors of this code are John Ioannidis (ji@tla.org), @@ -64,10 +64,10 @@ #include <sys/socketvar.h> #include <net/raw_cb.h> -#include <net/encap.h> #include <netinet/ip_ipsp.h> #include <netinet/ip_ah.h> +#include <net/pfkeyv2.h> #ifdef ENCDEBUG #define DPRINTF(x) if (encdebug) printf x @@ -75,18 +75,16 @@ #define DPRINTF(x) #endif -extern void encap_sendnotify(int, struct tdb *, void *); - -struct ah_hash ah_old_hash[] = { - { ALG_AUTH_MD5, "Keyed MD5", - AH_MD5_ALEN, +struct auth_hash ah_old_hash[] = { + { SADB_AALG_X_MD5, "Keyed MD5", + 0, AH_MD5_ALEN, sizeof(MD5_CTX), (void (*)(void *))MD5Init, (void (*)(void *, u_int8_t *, u_int16_t))MD5Update, (void (*)(u_int8_t *, void *))MD5Final }, - { ALG_AUTH_SHA1, "Keyed SHA1", - AH_SHA1_ALEN, + { SADB_AALG_X_SHA1, "Keyed SHA1", + 0, AH_SHA1_ALEN, sizeof(SHA1_CTX), (void (*)(void *))SHA1Init, (void (*)(void *, u_int8_t *, u_int16_t))SHA1Update, @@ -101,93 +99,49 @@ struct ah_hash ah_old_hash[] = { int ah_old_attach() { - DPRINTF(("ah_old_attach(): setting up\n")); return 0; } /* - * ah_old_init() is called when an SPI is being set up. It interprets the - * encap_msghdr present in m, and sets up the transformation data. + * ah_old_init() is called when an SPI is being set up. */ int -ah_old_init(struct tdb *tdbp, struct xformsw *xsp, struct mbuf *m) +ah_old_init(struct tdb *tdbp, struct xformsw *xsp, struct ipsecinit *ii) { - struct ah_old_xencap xenc; - struct ah_old_xdata *xd; - struct encap_msghdr *em; - struct ah_hash *thash; + struct auth_hash *thash = NULL; int i; - if (m->m_len < ENCAP_MSG_FIXED_LEN) - { - if ((m = m_pullup(m, ENCAP_MSG_FIXED_LEN)) == NULL) - { - DPRINTF(("ah_old_init(): m_pullup failed\n")); - return ENOBUFS; - } - } - - em = mtod(m, struct encap_msghdr *); - if (em->em_msglen - EMT_SETSPI_FLEN <= AH_OLD_XENCAP_LEN) - { - DPRINTF(("ah_old_init(): initialization failed\n")); - return EINVAL; - } - - /* Just copy the standard fields */ - m_copydata(m, EMT_SETSPI_FLEN, AH_OLD_XENCAP_LEN, (caddr_t) &xenc); - /* Check whether the hash algorithm is supported */ - for (i=sizeof(ah_old_hash)/sizeof(struct ah_hash)-1; i >= 0; i--) - if (xenc.amx_hash_algorithm == ah_old_hash[i].type) + for (i = sizeof(ah_old_hash) / sizeof(struct auth_hash) - 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", xenc.amx_hash_algorithm)); - m_freem(m); + DPRINTF(("ah_old_init(): unsupported authentication algorithm %d specified\n", ii->ii_authalg)); return EINVAL; } - DPRINTF(("ah_old_init(): initalized TDB with hash algorithm %d: %s\n", - xenc.amx_hash_algorithm, ah_old_hash[i].name)); thash = &ah_old_hash[i]; - if (xenc.amx_keylen + EMT_SETSPI_FLEN + AH_OLD_XENCAP_LEN != em->em_msglen) - { - DPRINTF(("ah_old_init(): message length (%d) doesn't match\n", - em->em_msglen)); - return EINVAL; - } - - MALLOC(tdbp->tdb_xdata, caddr_t, sizeof(struct ah_old_xdata) + - xenc.amx_keylen, M_XDATA, M_WAITOK); - if (tdbp->tdb_xdata == NULL) - { - DPRINTF(("ah_old_init(): MALLOC() failed\n")); - return ENOBUFS; - } - - bzero(tdbp->tdb_xdata, sizeof(struct ah_old_xdata) + xenc.amx_keylen); - xd = (struct ah_old_xdata *) tdbp->tdb_xdata; + DPRINTF(("ah_old_init(): initalized TDB with hash algorithm %s\n", + thash->name)); - /* Pointer to the transform */ tdbp->tdb_xform = xsp; + tdbp->tdb_authalgxform = thash; - xd->amx_keylen = xenc.amx_keylen; - xd->amx_hash_algorithm = xenc.amx_hash_algorithm; - xd->amx_hash = thash; - - /* Pass name of auth algorithm for kernfs */ - tdbp->tdb_authname = xd->amx_hash->name; + tdbp->tdb_amxkeylen = ii->ii_authkeylen; + MALLOC(tdbp->tdb_amxkey, u_int8_t *, tdbp->tdb_amxkeylen, + M_XDATA, M_WAITOK); - /* Copy the key material */ - m_copydata(m, EMT_SETSPI_FLEN + AH_OLD_XENCAP_LEN, xd->amx_keylen, - (caddr_t) xd->amx_key); + bcopy(ii->ii_authkey, tdbp->tdb_amxkey, tdbp->tdb_amxkeylen); - xd->amx_hash->Init(&(xd->amx_ctx)); - xd->amx_hash->Update(&(xd->amx_ctx), xd->amx_key, xd->amx_keylen); - xd->amx_hash->Final(NULL, &(xd->amx_ctx)); + 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 */ @@ -201,12 +155,18 @@ ah_old_init(struct tdb *tdbp, struct xformsw *xsp, struct mbuf *m) int ah_old_zeroize(struct tdb *tdbp) { - DPRINTF(("ah_old_zeroize(): freeing memory\n")); - if (tdbp->tdb_xdata) + if (tdbp->tdb_amxkey) + { + FREE(tdbp->tdb_amxkey, M_XDATA); + tdbp->tdb_amxkey = NULL; + } + + if (tdbp->tdb_ictx) { - FREE(tdbp->tdb_xdata, M_XDATA); - tdbp->tdb_xdata = NULL; + FREE(tdbp->tdb_ictx, M_XDATA); + tdbp->tdb_ictx = NULL; } + return 0; } @@ -218,7 +178,7 @@ ah_old_zeroize(struct tdb *tdbp) struct mbuf * ah_old_input(struct mbuf *m, struct tdb *tdb) { - struct ah_old_xdata *xd; + 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; @@ -231,11 +191,7 @@ ah_old_input(struct mbuf *m, struct tdb *tdb) u_char buffer[40]; aho = (struct ah_old *) buffer; - - xd = (struct ah_old_xdata *) tdb->tdb_xdata; - - alen = xd->amx_hash->hashsize; - + alen = ahx->hashsize; ohlen = sizeof(struct ip) + AH_OLD_FLENGTH + alen; if (m->m_len < ohlen) @@ -267,6 +223,32 @@ ah_old_input(struct mbuf *m, struct tdb *tdb) 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)) + { +/* XXX + encap_sendnotify(NOTIFY_HARD_EXPIRE, tdb, NULL); +*/ + m_freem(m); + tdb_delete(tdb, 0); + return NULL; + } + + /* Notify on expiration */ + if ((tdb->tdb_flags & TDBF_SOFT_BYTES) && + (tdb->tdb_cur_bytes >= tdb->tdb_soft_bytes)) + { +/* XXX + encap_sendnotify(NOTIFY_SOFT_EXPIRE, tdb, NULL); +*/ + 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() */ @@ -276,8 +258,8 @@ ah_old_input(struct mbuf *m, struct tdb *tdb) ipo.ip_ttl = 0; ipo.ip_sum = 0; - bcopy(&(xd->amx_ctx), &ctx, xd->amx_hash->ctxsize); - xd->amx_hash->Update(&ctx, (unsigned char *) &ipo, sizeof(struct ip)); + 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)) @@ -287,13 +269,13 @@ ah_old_input(struct mbuf *m, struct tdb *tdb) switch (optval) { case IPOPT_EOL: - xd->amx_hash->Update(&ctx, ipseczeroes, 1); + ahx->Update(&ctx, ipseczeroes, 1); off = ip->ip_hl << 2; break; case IPOPT_NOP: - xd->amx_hash->Update(&ctx, ipseczeroes, 1); + ahx->Update(&ctx, ipseczeroes, 1); off++; break; @@ -303,7 +285,7 @@ ah_old_input(struct mbuf *m, struct tdb *tdb) case 134: optval = ((u_int8_t *) ip)[off + 1]; - xd->amx_hash->Update(&ctx, (u_int8_t *) ip + off, optval); + ahx->Update(&ctx, (u_int8_t *) ip + off, optval); off += optval; break; @@ -311,7 +293,7 @@ ah_old_input(struct mbuf *m, struct tdb *tdb) default: optval = ((u_int8_t *) ip)[off + 1]; - xd->amx_hash->Update(&ctx, ipseczeroes, optval); + ahx->Update(&ctx, ipseczeroes, optval); off += optval; break; @@ -319,8 +301,8 @@ ah_old_input(struct mbuf *m, struct tdb *tdb) } - xd->amx_hash->Update(&ctx, (unsigned char *) ah, AH_OLD_FLENGTH); - xd->amx_hash->Update(&ctx, ipseczeroes, alen); + ahx->Update(&ctx, (unsigned char *) ah, AH_OLD_FLENGTH); + ahx->Update(&ctx, ipseczeroes, alen); /* * Code shamelessly stolen from m_copydata @@ -333,7 +315,7 @@ ah_old_input(struct mbuf *m, struct tdb *tdb) { if (m0 == 0) { - DPRINTF(("ah_old_input(): bad mbuf chain for packet from %x to %x, spi %08x\n", ipo.ip_src, ipo.ip_dst, ntohl(tdb->tdb_spi))); + 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; @@ -350,7 +332,7 @@ ah_old_input(struct mbuf *m, struct tdb *tdb) { if (m0 == 0) { - DPRINTF(("ah_old_input(): bad mbuf chain for packet from %x to %x, spi %08x\n", ipo.ip_src, ipo.ip_dst, ntohl(tdb->tdb_spi))); + 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; @@ -358,15 +340,15 @@ ah_old_input(struct mbuf *m, struct tdb *tdb) count = min(m0->m_len - off, len); - xd->amx_hash->Update(&ctx, mtod(m0, unsigned char *) + off, count); + ahx->Update(&ctx, mtod(m0, unsigned char *) + off, count); len -= count; off = 0; m0 = m0->m_next; } - xd->amx_hash->Update(&ctx, (unsigned char *) xd->amx_key, xd->amx_keylen); - xd->amx_hash->Final((unsigned char *) (aho->ah_data), &ctx); + 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)) { @@ -399,44 +381,6 @@ ah_old_input(struct mbuf *m, struct tdb *tdb) ip->ip_sum = in_cksum(m, (ip->ip_hl << 2)); - /* Update the counters */ - tdb->tdb_cur_packets++; - tdb->tdb_cur_bytes += ntohs(ip->ip_len) - (ip->ip_hl << 2); - ahstat.ahs_ibytes += ntohs(ip->ip_len) - (ip->ip_hl << 2); - - /* Notify on expiration */ - if (tdb->tdb_flags & TDBF_SOFT_PACKETS) - { - if (tdb->tdb_cur_packets >= tdb->tdb_soft_packets) - { - encap_sendnotify(NOTIFY_SOFT_EXPIRE, tdb, NULL); - tdb->tdb_flags &= ~TDBF_SOFT_PACKETS; - } - else - if (tdb->tdb_flags & TDBF_SOFT_BYTES) - if (tdb->tdb_cur_bytes >= tdb->tdb_soft_bytes) - { - encap_sendnotify(NOTIFY_SOFT_EXPIRE, tdb, NULL); - tdb->tdb_flags &= ~TDBF_SOFT_BYTES; - } - } - - if (tdb->tdb_flags & TDBF_PACKETS) - { - if (tdb->tdb_cur_packets >= tdb->tdb_exp_packets) - { - encap_sendnotify(NOTIFY_HARD_EXPIRE, tdb, NULL); - tdb_delete(tdb, 0); - } - else - if (tdb->tdb_flags & TDBF_BYTES) - if (tdb->tdb_cur_bytes >= tdb->tdb_exp_bytes) - { - encap_sendnotify(NOTIFY_HARD_EXPIRE, tdb, NULL); - tdb_delete(tdb, 0); - } - } - return m; } @@ -444,7 +388,7 @@ int ah_old_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb, struct mbuf **mp) { - struct ah_old_xdata *xd; + struct auth_hash *ahx = (struct auth_hash *) tdb->tdb_authalgxform; struct ip *ip, ipo; struct ah_old *ah, aho; register int len, off, count; @@ -457,26 +401,55 @@ ah_old_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb, 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 %x/%08x\n", - tdb->tdb_dst, ntohl(tdb->tdb_spi))); + 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 *); - xd = (struct ah_old_xdata *) tdb->tdb_xdata; + /* 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)) + { +/* XXX + encap_sendnotify(NOTIFY_HARD_EXPIRE, tdb, NULL); +*/ + tdb_delete(tdb, 0); + m_freem(m); + return EINVAL; + } + + /* Notify on expiration */ + if ((tdb->tdb_flags & TDBF_SOFT_BYTES) && + (tdb->tdb_cur_bytes >= tdb->tdb_soft_bytes)) + { +/* XXX + encap_sendnotify(NOTIFY_SOFT_EXPIRE, tdb, NULL); +*/ + 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 &x/%08x\n", - tdb->tdb_dst, ntohl(tdb->tdb_spi))); + 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; } @@ -484,8 +457,6 @@ ah_old_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb, ip = mtod(m, struct ip *); } - alen = xd->amx_hash->hashsize; - /* Save the options */ m_copydata(m, sizeof(struct ip), (ip->ip_hl << 2) - sizeof(struct ip), (caddr_t) opts); @@ -493,9 +464,10 @@ ah_old_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb, ilen = ntohs(ip->ip_len); ohlen = AH_OLD_FLENGTH + alen; - if (ohlen + ilen > IP_MAXPACKET) { - DPRINTF(("ah_old_output(): packet in SA %x/%0x8 got too big\n", - tdb->tdb_dst, ntohl(tdb->tdb_spi))); + 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; @@ -518,8 +490,8 @@ ah_old_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb, aho.ah_rv = 0; aho.ah_spi = tdb->tdb_spi; - bcopy(&(xd->amx_ctx), &ctx, xd->amx_hash->ctxsize); - xd->amx_hash->Update(&ctx, (unsigned char *) &ipo, sizeof(struct ip)); + 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)) @@ -529,13 +501,13 @@ ah_old_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb, switch (optval) { case IPOPT_EOL: - xd->amx_hash->Update(&ctx, ipseczeroes, 1); + ahx->Update(&ctx, ipseczeroes, 1); off = ip->ip_hl << 2; break; case IPOPT_NOP: - xd->amx_hash->Update(&ctx, ipseczeroes, 1); + ahx->Update(&ctx, ipseczeroes, 1); off++; break; @@ -545,7 +517,7 @@ ah_old_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb, case 134: optval = ((u_int8_t *) ip)[off + 1]; - xd->amx_hash->Update(&ctx, (u_int8_t *) ip + off, optval); + ahx->Update(&ctx, (u_int8_t *) ip + off, optval); off += optval; break; @@ -553,15 +525,15 @@ ah_old_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb, default: optval = ((u_int8_t *) ip)[off + 1]; - xd->amx_hash->Update(&ctx, ipseczeroes, optval); + ahx->Update(&ctx, ipseczeroes, optval); off += optval; break; } } - xd->amx_hash->Update(&ctx, (unsigned char *) &aho, AH_OLD_FLENGTH); - xd->amx_hash->Update(&ctx, ipseczeroes, alen); + 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; @@ -577,21 +549,21 @@ ah_old_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb, { if (m0 == 0) { - DPRINTF(("ah_old_output(): M_PREPEND() failed for packet from %x to %x, spi %08x\n", ipo.ip_src, ipo.ip_dst, ntohl(tdb->tdb_spi))); + 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); - xd->amx_hash->Update(&ctx, mtod(m0, unsigned char *) + off, count); + ahx->Update(&ctx, mtod(m0, unsigned char *) + off, count); len -= count; off = 0; m0 = m0->m_next; } - xd->amx_hash->Update(&ctx, (unsigned char *) xd->amx_key, xd->amx_keylen); + ahx->Update(&ctx, (unsigned char *) tdb->tdb_amxkey, tdb->tdb_amxkeylen); ipo.ip_tos = ip->ip_tos; ipo.ip_id = ip->ip_id; @@ -602,14 +574,14 @@ ah_old_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb, M_PREPEND(m, ohlen, M_DONTWAIT); if (m == NULL) { - DPRINTF(("ah_old_output(): M_PREPEND() failed for packet from %x to %x, spi %08x\n", ipo.ip_src, ipo.ip_dst, ntohl(tdb->tdb_spi))); + 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 %x to %x, spi %08x\n", ipo.ip_src, ipo.ip_dst, ntohl(tdb->tdb_spi))); + 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; } @@ -626,49 +598,9 @@ ah_old_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb, m_copyback(m, sizeof(struct ip), (ip->ip_hl << 2) - sizeof(struct ip), (caddr_t) opts); - xd->amx_hash->Final(ah->ah_data, &ctx); + ahx->Final(ah->ah_data, &ctx); *mp = m; - /* Update the counters */ - tdb->tdb_cur_packets++; - 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; - - /* Notify on expiration */ - if (tdb->tdb_flags & TDBF_SOFT_PACKETS) - { - if (tdb->tdb_cur_packets >= tdb->tdb_soft_packets) - { - encap_sendnotify(NOTIFY_SOFT_EXPIRE, tdb, NULL); - tdb->tdb_flags &= ~TDBF_SOFT_PACKETS; - } - else - if (tdb->tdb_flags & TDBF_SOFT_BYTES) - if (tdb->tdb_cur_bytes >= tdb->tdb_soft_bytes) - { - encap_sendnotify(NOTIFY_SOFT_EXPIRE, tdb, NULL); - tdb->tdb_flags &= ~TDBF_SOFT_BYTES; - } - } - - if (tdb->tdb_flags & TDBF_PACKETS) - { - if (tdb->tdb_cur_packets >= tdb->tdb_exp_packets) - { - encap_sendnotify(NOTIFY_HARD_EXPIRE, tdb, NULL); - tdb_delete(tdb, 0); - } - else - if (tdb->tdb_flags & TDBF_BYTES) - if (tdb->tdb_cur_bytes >= tdb->tdb_exp_bytes) - { - encap_sendnotify(NOTIFY_HARD_EXPIRE, tdb, NULL); - tdb_delete(tdb, 0); - } - } - return 0; } diff --git a/sys/netinet/ip_esp.c b/sys/netinet/ip_esp.c index dcc6d0c9ad5..66189caa2bb 100644 --- a/sys/netinet/ip_esp.c +++ b/sys/netinet/ip_esp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_esp.c,v 1.16 1998/06/10 23:57:14 provos Exp $ */ +/* $OpenBSD: ip_esp.c,v 1.17 1999/02/24 22:33:01 angelos Exp $ */ /* * The authors of this code are John Ioannidis (ji@tla.org), @@ -65,16 +65,22 @@ #include <sys/socketvar.h> #include <net/raw_cb.h> -#include <net/encap.h> #include <netinet/ip_icmp.h> #include <netinet/ip_ipsp.h> #include <netinet/ip_esp.h> -#include <sys/syslog.h> #include "bpfilter.h" -void esp_input __P((struct mbuf *, int)); +extern struct ifnet enc_softc; + +#ifdef ENCDEBUG +#define DPRINTF(x) if (encdebug) printf x +#else +#define DPRINTF(x) +#endif + +void esp_input __P((struct mbuf *, int)); /* * esp_input gets called when we receive an packet with an ESP. @@ -83,6 +89,7 @@ void esp_input __P((struct mbuf *, int)); void esp_input(register struct mbuf *m, int iphlen) { + union sockaddr_union sunion; struct ifqueue *ifq = NULL; struct expiration *exp; struct ip *ipo, ipn; @@ -101,10 +108,6 @@ esp_input(register struct mbuf *m, int iphlen) { if ((m = m_pullup(m, iphlen + sizeof(u_int32_t))) == 0) { -#ifdef ENCDEBUG - if (encdebug) - printf("esp_input(): (possibly too short) packet from %x to %x dropped\n", ipo->ip_src, ipo->ip_dst); -#endif /* ENCDEBUG */ espstat.esps_hdrops++; return; } @@ -120,11 +123,14 @@ esp_input(register struct mbuf *m, int iphlen) * IP packet ready to go through input processing. */ - tdbp = gettdb(spi, ipo->ip_dst, IPPROTO_ESP); + bzero(&sunion, sizeof(sunion)); + sunion.sin.sin_family = AF_INET; + sunion.sin.sin_len = sizeof(struct sockaddr_in); + sunion.sin.sin_addr = ipo->ip_dst; + tdbp = gettdb(spi, &sunion, IPPROTO_ESP); if (tdbp == NULL) { - if (encdebug) - log(LOG_ERR, "esp_input(): could not find SA for ESP packet from %x to %x, spi %08x\n", ipo->ip_src, ipo->ip_dst, ntohl(spi)); + DPRINTF(("esp_input(): could not find SA for packet from %s to %s, spi %08x\n", inet_ntoa4(ipo->ip_src), ipsp_address(sunion), ntohl(spi))); m_freem(m); espstat.esps_notdb++; return; @@ -132,8 +138,7 @@ esp_input(register struct mbuf *m, int iphlen) if (tdbp->tdb_flags & TDBF_INVALID) { - if (encdebug) - log(LOG_ALERT, "esp_input(): attempted to use invalid ESP SA %08x, packet %x->%x\n", ntohl(spi), ipo->ip_src, ipo->ip_dst); + DPRINTF(("esp_input(): attempted to use invalid SA %08x, packet from %s to %s\n", ntohl(spi), inet_ntoa4(ipo->ip_src), ipsp_address(sunion))); m_freem(m); espstat.esps_invalid++; return; @@ -141,8 +146,7 @@ esp_input(register struct mbuf *m, int iphlen) if (tdbp->tdb_xform == NULL) { - if (encdebug) - log(LOG_ALERT, "esp_input(): attempted to use uninitialized ESP SA %08x, packet from %x to %x\n", ntohl(spi), ipo->ip_src, ipo->ip_dst); + DPRINTF(("esp_input(): attempted to use uninitialized SA %08x, packet from %s to %s\n", ntohl(spi), inet_ntoa4(ipo->ip_src), ipsp_address(sunion))); m_freem(m); espstat.esps_noxform++; return; @@ -158,21 +162,10 @@ esp_input(register struct mbuf *m, int iphlen) if (tdbp->tdb_flags & TDBF_FIRSTUSE) { exp = get_expiration(); - if (exp == (struct expiration *) NULL) - { - if (encdebug) - log(LOG_WARNING, - "esp_input(): out of memory for expiration timer\n"); - espstat.esps_hdrops++; - m_freem(m); - return; - } - - exp->exp_dst.s_addr = tdbp->tdb_dst.s_addr; + bcopy(&tdbp->tdb_dst, &exp->exp_dst, SA_LEN(&tdbp->tdb_dst.sa)); exp->exp_spi = tdbp->tdb_spi; exp->exp_sproto = tdbp->tdb_sproto; exp->exp_timeout = tdbp->tdb_first_use + tdbp->tdb_exp_first_use; - put_expiration(exp); } @@ -180,21 +173,10 @@ esp_input(register struct mbuf *m, int iphlen) (tdbp->tdb_soft_first_use <= tdbp->tdb_exp_first_use)) { exp = get_expiration(); - if (exp == (struct expiration *) NULL) - { - if (encdebug) - log(LOG_WARNING, - "esp_input(): out of memory for expiration timer\n"); - espstat.esps_hdrops++; - m_freem(m); - return; - } - - exp->exp_dst.s_addr = tdbp->tdb_dst.s_addr; + bcopy(&tdbp->tdb_dst, &exp->exp_dst, SA_LEN(&tdbp->tdb_dst.sa)); exp->exp_spi = tdbp->tdb_spi; exp->exp_sproto = tdbp->tdb_sproto; exp->exp_timeout = tdbp->tdb_first_use + tdbp->tdb_soft_first_use; - put_expiration(exp); } } @@ -205,8 +187,7 @@ esp_input(register struct mbuf *m, int iphlen) if (m == NULL) { - if (encdebug) - log(LOG_ALERT, "esp_input(): processing failed for ESP packet from %x to %x, spi %08x\n", ipn.ip_src, ipn.ip_dst, ntohl(spi)); + DPRINTF(("esp_input(): processing failed for ESP packet from %s to %s, spi %08x\n", inet_ntoa4(ipn.ip_src), ipsp_address(sunion), ntohl(spi))); espstat.esps_badkcr++; return; } @@ -217,30 +198,25 @@ esp_input(register struct mbuf *m, int iphlen) /* ipn will now contain the inner IP header */ m_copydata(m, ipo->ip_hl << 2, sizeof(struct ip), (caddr_t) &ipn); - /* Encapsulating SPI */ - if (tdbp->tdb_osrc.s_addr && tdbp->tdb_odst.s_addr) + if (tdbp->tdb_flags & TDBF_UNIQUE) + if ((ipn.ip_src.s_addr != ipo->ip_src.s_addr) || + (ipn.ip_dst.s_addr != ipo->ip_dst.s_addr)) + { + DPRINTF(("esp_input(): ESP-tunnel with different internal addresses %s->%s (%s->%s), SA %s/%08x\n", inet_ntoa4(ipo->ip_src), inet_ntoa4(ipo->ip_dst), inet_ntoa4(ipn.ip_src), ipsp_address(sunion), ipsp_address(tdbp->tdb_dst), ntohl(tdbp->tdb_spi))); + m_freem(m); + espstat.esps_hdrops++; + return; + } + + /* + * Check that the inner source address is the same as + * the proxy address, if available. + */ + if ((tdbp->tdb_proxy.sin.sin_addr.s_addr != INADDR_ANY) && + (ipn.ip_src.s_addr != tdbp->tdb_proxy.sin.sin_addr.s_addr)) { - if (tdbp->tdb_flags & TDBF_UNIQUE) - if ((ipn.ip_src.s_addr != ipo->ip_src.s_addr) || - (ipn.ip_dst.s_addr != ipo->ip_dst.s_addr)) - { - if (encdebug) - log(LOG_ALERT, "esp_input(): ESP-tunnel with different internal addresses %x/%x, SA %08x/%x\n", ipo->ip_src, ipo->ip_dst, tdbp->tdb_spi, tdbp->tdb_dst); - m_freem(m); - espstat.esps_hdrops++; - return; - } - - /* - * XXX Here we should be checking that the inner IP addresses - * XXX are acceptable/authorized. - */ - } - else /* So we're paranoid */ - { - if (encdebug) - log(LOG_ALERT, "esp_input(): ESP-tunnel used when expecting ESP-transport, SA %08x/%x\n", tdbp->tdb_spi, tdbp->tdb_dst); - m_freem(m); + DPRINTF(("esp_input(): inner source address %s doesn't correspond to expected proxy source %s, SA %s/%08x\n", inet_ntoa4(ipo->ip_src), inet_ntoa4(tdbp->tdb_proxy.sin.sin_addr), inet_ntoa4(tdbp->tdb_dst.sin.sin_addr), ntohl(tdbp->tdb_spi))); + m_free(m); espstat.esps_hdrops++; return; } @@ -250,15 +226,14 @@ esp_input(register struct mbuf *m, int iphlen) * Check that the source address is an expected one, if we know what * it's supposed to be. This avoids source address spoofing. */ - if (tdbp->tdb_src.s_addr != INADDR_ANY) - if (ipo->ip_src.s_addr != tdbp->tdb_src.s_addr) - { - if (encdebug) - log(LOG_ALERT, "esp_input(): source address %x doesn't correspond to expected source %x, SA %08x/%x\n", ipo->ip_src, tdbp->tdb_src, tdbp->tdb_dst, tdbp->tdb_spi); - m_free(m); - espstat.esps_hdrops++; - return; - } + if ((tdbp->tdb_src.sin.sin_addr.s_addr != INADDR_ANY) && + (ipo->ip_src.s_addr != tdbp->tdb_src.sin.sin_addr.s_addr)) + { + DPRINTF(("esp_input(): source address %s doesn't correspond to expected source %s, SA %s/%08x\n", inet_ntoa4(ipo->ip_src), ipsp_address(tdbp->tdb_src), ipsp_address(tdbp->tdb_dst), ntohl(tdbp->tdb_spi))); + m_free(m); + espstat.esps_hdrops++; + return; + } /* Packet is confidental */ m->m_flags |= M_CONF; @@ -278,7 +253,7 @@ esp_input(register struct mbuf *m, int iphlen) hdr.af = AF_INET; hdr.spi = tdbp->tdb_spi; - hdr.flags = m->m_flags & (M_AUTH|M_CONF|M_TUNNEL); + hdr.flags = m->m_flags & (M_AUTH|M_CONF); m0.m_next = m; m0.m_len = ENC_HDRLEN; @@ -302,10 +277,7 @@ esp_input(register struct mbuf *m, int iphlen) m_freem(m); espstat.esps_qfull++; splx(s); -#ifdef ENCDEBUG - if (encdebug) - printf("esp_input(): dropped packet because of full IP queue\n"); -#endif /* ENCDEBUG */ + DPRINTF(("esp_input(): dropped packet because of full IP queue\n")); return; } diff --git a/sys/netinet/ip_esp.h b/sys/netinet/ip_esp.h index ccbc83cb730..b1f7af1a8d7 100644 --- a/sys/netinet/ip_esp.h +++ b/sys/netinet/ip_esp.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_esp.h,v 1.20 1999/02/17 20:39:17 deraadt Exp $ */ +/* $OpenBSD: ip_esp.h,v 1.21 1999/02/24 22:33:01 angelos Exp $ */ /* * The authors of this code are John Ioannidis (ji@tla.org), @@ -38,181 +38,44 @@ * Per RFC1827 (Atkinson, 1995) */ -#ifndef _MD5_H_ -#include <sys/md5k.h> -#endif - -#include <netinet/ip_sha1.h> -#include <netinet/ip_rmd160.h> -#include <netinet/ip_blf.h> -#include <netinet/ip_cast.h> -#include <netinet/ip_skipjack.h> - -/* IV lengths */ -#define ESP_DES_IVS 8 -#define ESP_3DES_IVS 8 -#define ESP_BLF_IVS 8 -#define ESP_CAST_IVS 8 -#define ESP_SKIPJACK_IVS 8 - -#define ESP_MAX_IVS ESP_3DES_IVS - -/* Block sizes -- it is assumed that they're powers of 2 */ -#define ESP_DES_BLKS 8 -#define ESP_3DES_BLKS 8 -#define ESP_BLF_BLKS 8 -#define ESP_CAST_BLKS 8 -#define ESP_SKIPJACK_BLKS 8 - -#define ESP_MAX_BLKS ESP_3DES_BLKS - /* Various defines for the "new" ESP */ #define ESP_NEW_ALEN 12 /* 96bits authenticator */ -#define ESP_NEW_IPAD_VAL 0x36 -#define ESP_NEW_OPAD_VAL 0x5C - -struct esp_hash { - int type; - char *name; - u_int16_t hashsize; - u_int16_t ctxsize; - void (*Init) __P((void *)); - void (*Update) __P((void *, u_int8_t *, u_int16_t)); - void (*Final) __P((u_int8_t *, void *)); -}; - -struct esp_xform { - int type; - char *name; - u_int16_t blocksize, ivsize; - u_int16_t minkey, maxkey; - u_int32_t ivmask; /* Or all possible modes, zero iv = 1 */ - void (*encrypt) __P((void *, u_int8_t *)); - void (*decrypt) __P((void *, u_int8_t *)); -}; - -struct esp_old { - u_int32_t esp_spi; /* Security Parameters Index */ - u_int8_t esp_iv[8]; /* iv[4] may actually be data! */ -}; - -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]! */ -}; -struct espstat { - u_int32_t esps_hdrops; /* packet shorter than header shows */ - u_int32_t esps_notdb; - u_int32_t esps_badkcr; - u_int32_t esps_qfull; - u_int32_t esps_noxform; - u_int32_t esps_badilen; - u_int32_t esps_wrap; /* Replay counter wrapped around */ - u_int32_t esps_badauth; /* Only valid for transforms with auth */ - u_int32_t esps_replay; /* Possible packet replay detected */ - u_int32_t esps_input; /* Input ESP packets */ - u_int32_t esps_output; /* Output ESP packets */ - u_int32_t esps_invalid; /* Trying to use an invalid TDB */ - u_int64_t esps_ibytes; /* input bytes */ - u_int64_t esps_obytes; /* output bytes */ - u_int32_t esps_toobig; /* packet got larger than IP_MAXPACKET */ +struct esp_old +{ + u_int32_t esp_spi; /* Security Parameters Index */ + u_int8_t esp_iv[8]; /* iv[4] may actually be data! */ }; -struct esp_old_xdata { - u_int32_t edx_enc_algorithm; - int32_t edx_ivlen; /* 4 or 8 */ - struct esp_xform *edx_xform; - union { - u_int8_t Iv[ESP_3DES_IVS]; /* that's enough space */ - u_int32_t Ivl; /* make sure this is 4 bytes */ - u_int64_t Ivq; /* make sure this is 8 bytes! */ - } Iu; -#define edx_iv Iu.Iv -#define edx_ivl Iu.Ivl -#define edx_ivq Iu.Ivq - union { - u_int8_t Rk[3][8]; - u_int32_t Eks[3][16][2]; - } Xu; -#define edx_rk Xu.Rk -#define edx_eks Xu.Eks -}; +#define ESP_OLD_FLENGTH 12 +#define ESP_NEW_FLENGTH 16 -struct esp_old_xencap { - u_int32_t edx_enc_algorithm; - u_int32_t edx_ivlen; - u_int32_t edx_keylen; - u_int8_t edx_data[1]; /* IV + key material */ +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_OLD_XENCAP_LEN (3 * sizeof(u_int32_t)) - -struct esp_new_xencap { - u_int32_t edx_enc_algorithm; - u_int32_t edx_hash_algorithm; - u_int32_t edx_ivlen; /* 0 or 8 */ - u_int16_t edx_confkeylen; - u_int16_t edx_authkeylen; - int32_t edx_wnd; - u_int32_t edx_flags; - u_int8_t edx_data[1]; /* IV + key material */ +struct espstat +{ + u_int32_t esps_hdrops; /* packet shorter than header shows */ + u_int32_t esps_notdb; + u_int32_t esps_badkcr; + u_int32_t esps_qfull; + u_int32_t esps_noxform; + u_int32_t esps_badilen; + u_int32_t esps_wrap; /* Replay counter wrapped around */ + u_int32_t esps_badauth; /* Only valid for transforms with auth */ + u_int32_t esps_replay; /* Possible packet replay detected */ + u_int32_t esps_input; /* Input ESP packets */ + u_int32_t esps_output; /* Output ESP packets */ + u_int32_t esps_invalid; /* Trying to use an invalid TDB */ + u_int64_t esps_ibytes; /* input bytes */ + u_int64_t esps_obytes; /* output bytes */ + u_int32_t esps_toobig; /* packet got larger than IP_MAXPACKET */ }; -#define ESP_NEW_XENCAP_LEN (6 * sizeof(u_int32_t)) - -#define ESP_NEW_FLAG_AUTH 0x00000001 /* Doing authentication too */ -#define ESP_NEW_FLAG_NPADDING 0x00000002 /* New style padding */ - -struct esp_new_xdata { - u_int32_t edx_enc_algorithm; - u_int32_t edx_hash_algorithm; - u_int32_t edx_ivlen; /* 0 or 8 */ - u_int32_t edx_rpl; /* Replay counter */ - int32_t edx_wnd; /* Replay window */ - u_int32_t edx_bitmap; - u_int32_t edx_flags; - u_int32_t edx_initial; /* initial replay value */ - struct esp_hash *edx_hash; - struct esp_xform *edx_xform; - union { - u_int8_t Iv[ESP_MAX_IVS]; /* that's enough space */ - u_int32_t Ivl; /* make sure this is 4 bytes */ - u_int64_t Ivq; /* make sure this is 8 bytes! */ - } Iu; - union { - u_int8_t Rk[3][8]; - u_int32_t Eks[3][16][2]; - blf_ctx Bks; - cast_key Cks; - u_int8_t *Sks[10]; - } Xu; - union { - MD5_CTX edx_MD5_ictx; - SHA1_CTX edx_SHA1_ictx; - RMD160_CTX edx_RMD160_ictx; - } edx_ictx; - union { - MD5_CTX edx_MD5_octx; - SHA1_CTX edx_SHA1_octx; - RMD160_CTX edx_RMD160_octx; - } edx_octx; -}; - -#define edx_bks Xu.Bks -#define edx_cks Xu.Cks -#define edx_sks Xu.Sks -#define edx_md5_ictx edx_ictx.edx_MD5_ictx -#define edx_md5_octx edx_octx.edx_MD5_octx -#define edx_sha1_ictx edx_ictx.edx_SHA1_ictx -#define edx_sha1_octx edx_octx.edx_SHA1_octx -#define edx_rmd160_ictx edx_ictx.edx_RMD160_ictx -#define edx_rmd160_octx edx_octx.edx_RMD160_octx - -#define ESP_OLD_FLENGTH 12 -#define ESP_NEW_FLENGTH 16 - #ifdef _KERNEL struct espstat espstat; -#endif +#endif /* _Kernel */ diff --git a/sys/netinet/ip_esp_new.c b/sys/netinet/ip_esp_new.c index 5a45bd97e76..26026302756 100644 --- a/sys/netinet/ip_esp_new.c +++ b/sys/netinet/ip_esp_new.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_esp_new.c,v 1.33 1999/02/17 20:39:17 deraadt Exp $ */ +/* $OpenBSD: ip_esp_new.c,v 1.34 1999/02/24 22:33:02 angelos Exp $ */ /* * The authors of this code are John Ioannidis (ji@tla.org), @@ -63,12 +63,11 @@ #include <sys/socketvar.h> #include <net/raw_cb.h> -#include <net/encap.h> #include <netinet/ip_icmp.h> #include <netinet/ip_ipsp.h> #include <netinet/ip_esp.h> -#include <netinet/ip_ah.h> +#include <net/pfkeyv2.h> #ifdef ENCDEBUG #define DPRINTF(x) if (encdebug) printf x @@ -76,39 +75,36 @@ #define DPRINTF(x) #endif -extern void encap_sendnotify(int, struct tdb *, void *); extern void des_ecb3_encrypt(caddr_t, caddr_t, caddr_t, caddr_t, caddr_t, int); extern void des_ecb_encrypt(caddr_t, caddr_t, caddr_t, int); extern void des_set_key(caddr_t, caddr_t); -static void des1_encrypt(void *, u_int8_t *); -static void des3_encrypt(void *, u_int8_t *); -static void blf_encrypt(void *, u_int8_t *); -static void cast5_encrypt(void *, u_int8_t *); -static void skipjack_encrypt(void *, u_int8_t *); -static void des1_decrypt(void *, u_int8_t *); -static void des3_decrypt(void *, u_int8_t *); -static void blf_decrypt(void *, u_int8_t *); -static void cast5_decrypt(void *, u_int8_t *); -static void skipjack_decrypt(void *, u_int8_t *); - -struct esp_hash esp_new_hash[] = { - { ALG_AUTH_MD5, "HMAC-MD5-96", - AH_MD5_ALEN, +static void des1_encrypt(struct tdb *, u_int8_t *); +static void des3_encrypt(struct tdb *, u_int8_t *); +static void blf_encrypt(struct tdb *, u_int8_t *); +static void cast5_encrypt(struct tdb *, u_int8_t *); +static void des1_decrypt(struct tdb *, u_int8_t *); +static void des3_decrypt(struct tdb *, u_int8_t *); +static void blf_decrypt(struct tdb *, u_int8_t *); +static void cast5_decrypt(struct tdb *, u_int8_t *); + +struct auth_hash esp_new_hash[] = { + { SADB_AALG_MD5HMAC96, "HMAC-MD5-96", + MD5HMAC96_KEYSIZE, AH_MD5_ALEN, sizeof(MD5_CTX), (void (*) (void *)) MD5Init, (void (*) (void *, u_int8_t *, u_int16_t)) MD5Update, (void (*) (u_int8_t *, void *)) MD5Final }, - { ALG_AUTH_SHA1, "HMAC-SHA1-96", - AH_SHA1_ALEN, + { SADB_AALG_SHA1HMAC96, "HMAC-SHA1-96", + SHA1HMAC96_KEYSIZE, AH_SHA1_ALEN, sizeof(SHA1_CTX), (void (*) (void *)) SHA1Init, (void (*) (void *, u_int8_t *, u_int16_t)) SHA1Update, (void (*) (u_int8_t *, void *)) SHA1Final }, - { ALG_AUTH_RMD160, "HMAC-RIPEMD-160-96", - AH_RMD160_ALEN, + { SADB_AALG_X_RIPEMD160HMAC96, "HMAC-RIPEMD-160-96", + RIPEMD160HMAC96_KEYSIZE, AH_RMD160_ALEN, sizeof(RMD160_CTX), (void (*)(void *)) RMD160Init, (void (*)(void *, u_int8_t *, u_int16_t)) RMD160Update, @@ -116,358 +112,251 @@ struct esp_hash esp_new_hash[] = { } }; -struct esp_xform esp_new_xform[] = { - { ALG_ENC_DES, "Data Encryption Standard (DES)", +struct enc_xform esp_new_xform[] = { + { SADB_EALG_DESCBC, "Data Encryption Standard (DES)", ESP_DES_BLKS, ESP_DES_IVS, - 8, 8, 8 | 1, + 8, 8, 8, des1_encrypt, des1_decrypt }, - { ALG_ENC_3DES, "Triple DES (3DES)", + { SADB_EALG_3DESCBC, "Triple DES (3DES)", ESP_3DES_BLKS, ESP_3DES_IVS, - 24, 24, 8 | 1, + 24, 24, 8, des3_encrypt, des3_decrypt }, - { ALG_ENC_BLF, "Blowfish", + { SADB_EALG_X_BLF, "Blowfish", ESP_BLF_BLKS, ESP_BLF_IVS, - 5, BLF_MAXKEYLEN, 8 | 1, + 5, BLF_MAXKEYLEN, 8, blf_encrypt, blf_decrypt }, - { ALG_ENC_CAST, "CAST", + { SADB_EALG_X_CAST, "CAST", ESP_CAST_BLKS, ESP_CAST_IVS, - 5, 16, 8 | 1, + 5, 16, 8, cast5_encrypt, cast5_decrypt - }, - { ALG_ENC_CAST, "Skipjack", - ESP_SKIPJACK_BLKS, ESP_SKIPJACK_IVS, - 10, 10, 8 | 1, - skipjack_encrypt, - skipjack_decrypt } }; static void -des1_encrypt(void *pxd, u_int8_t *blk) -{ - struct esp_new_xdata *xd = pxd; - des_ecb_encrypt(blk, blk, (caddr_t) (xd->edx_eks[0]), 1); -} - -static void -des1_decrypt(void *pxd, u_int8_t *blk) +des1_encrypt(struct tdb *tdb, u_int8_t *blk) { - struct esp_new_xdata *xd = pxd; - des_ecb_encrypt(blk, blk, (caddr_t) (xd->edx_eks[0]), 0); + des_ecb_encrypt(blk, blk, tdb->tdb_key, 1); } static void -des3_encrypt(void *pxd, u_int8_t *blk) +des1_decrypt(struct tdb *tdb, u_int8_t *blk) { - struct esp_new_xdata *xd = pxd; - des_ecb3_encrypt(blk, blk, (caddr_t) (xd->edx_eks[0]), - (caddr_t) (xd->edx_eks[1]), - (caddr_t) (xd->edx_eks[2]), 1); + des_ecb_encrypt(blk, blk, tdb->tdb_key, 0); } static void -des3_decrypt(void *pxd, u_int8_t *blk) +des3_encrypt(struct tdb *tdb, u_int8_t *blk) { - struct esp_new_xdata *xd = pxd; - des_ecb3_encrypt(blk, blk, (caddr_t) (xd->edx_eks[2]), - (caddr_t) (xd->edx_eks[1]), - (caddr_t) (xd->edx_eks[0]), 0); + des_ecb3_encrypt(blk, blk, tdb->tdb_key, tdb->tdb_key + 128, + tdb->tdb_key + 256, 1); } static void -blf_encrypt(void *pxd, u_int8_t *blk) +des3_decrypt(struct tdb *tdb, u_int8_t *blk) { - struct esp_new_xdata *xd = pxd; - Blowfish_encipher(&xd->edx_bks, (u_int32_t *) blk, - (u_int32_t *) (blk + 4)); + des_ecb3_encrypt(blk, blk, tdb->tdb_key + 256, tdb->tdb_key + 128, + tdb->tdb_key, 0); } static void -blf_decrypt(void *pxd, u_int8_t *blk) +blf_encrypt(struct tdb *tdb, u_int8_t *blk) { - struct esp_new_xdata *xd = pxd; - Blowfish_decipher(&xd->edx_bks, (u_int32_t *) blk, - (u_int32_t *) (blk + 4)); + blf_ecb_encrypt((blf_ctx *) tdb->tdb_key, blk, 8); } static void -cast5_encrypt(void *pxd, u_int8_t *blk) +blf_decrypt(struct tdb *tdb, u_int8_t *blk) { - struct esp_new_xdata *xd = pxd; - cast_encrypt(&xd->edx_cks, blk, blk); + blf_ecb_decrypt((blf_ctx *) tdb->tdb_key, blk, 8); } static void -cast5_decrypt(void *pxd, u_int8_t *blk) +cast5_encrypt(struct tdb *tdb, u_int8_t *blk) { - struct esp_new_xdata *xd = pxd; - cast_decrypt(&xd->edx_cks, blk, blk); + cast_encrypt((cast_key *) tdb->tdb_key, blk, blk); } static void -skipjack_encrypt(void *pxd, u_int8_t *blk) +cast5_decrypt(struct tdb *tdb, u_int8_t *blk) { - struct esp_new_xdata *xd = pxd; - skipjack_forwards(blk, blk, xd->edx_sks); -} - -static void -skipjack_decrypt(void *pxd, u_int8_t *blk) -{ - struct esp_new_xdata *xd = pxd; - skipjack_backwards(blk, blk, xd->edx_sks); + cast_decrypt((cast_key *) tdb->tdb_key, blk, blk); } /* * esp_new_attach() is called from the transformation initialization code. - * It just returns. */ int esp_new_attach() { - DPRINTF(("esp_new_attach(): setting up\n")); return 0; } /* - * esp_new_init() is called when an SPI is being set up. It interprets the - * encap_msghdr present in m, and sets up the transformation data, in - * this case, the encryption and decryption key schedules + * esp_new_init() is called when an SPI is being set up. */ int -esp_new_init(struct tdb *tdbp, struct xformsw *xsp, struct mbuf *m) +esp_new_init(struct tdb *tdbp, struct xformsw *xsp, struct ipsecinit *ii) { - struct esp_new_xdata *xd; - struct esp_new_xencap txd; - struct encap_msghdr *em; - struct esp_xform *txform; - struct esp_hash *thash; - caddr_t buffer = NULL; - u_int32_t rk[14]; - int blocklen, i; - - if (m->m_len < ENCAP_MSG_FIXED_LEN) - { - if ((m = m_pullup(m, ENCAP_MSG_FIXED_LEN)) == NULL) - { - DPRINTF(("esp_new_init(): m_pullup failed\n")); - return ENOBUFS; - } - } - - em = mtod(m, struct encap_msghdr *); - if (em->em_msglen - EMT_SETSPI_FLEN <= ESP_NEW_XENCAP_LEN) - { - DPRINTF(("esp_new_init(): initialization failed\n")); - return EINVAL; - } - - /* Just copy the standard fields */ - m_copydata(m, EMT_SETSPI_FLEN, ESP_NEW_XENCAP_LEN, (caddr_t) &txd); + 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(struct esp_xform) - 1; i >= 0; i--) - if (txd.edx_enc_algorithm == esp_new_xform[i].type) - break; + for (i = sizeof(esp_new_xform) / sizeof(struct enc_xform) - 1; + i >= 0; i--) + if (ii->ii_encalg == esp_new_xform[i].type) + break; + if (i < 0) { - DPRINTF(("esp_new_init(): unsupported encryption algorithm %d specified\n", txd.edx_enc_algorithm)); + DPRINTF(("esp_new_init(): unsupported encryption algorithm %d specified\n", ii->ii_encalg)); return EINVAL; } txform = &esp_new_xform[i]; - DPRINTF(("esp_new_init(): initialized TDB with enc algorithm %d: %s\n", - txd.edx_enc_algorithm, esp_new_xform[i].name)); - /* Check whether the authentication algorithm is supported */ - if (txd.edx_flags & ESP_NEW_FLAG_AUTH) + if (ii->ii_enckeylen < txform->minkey) { - for (i = sizeof(esp_new_hash) / sizeof(struct esp_hash) - 1; i >= 0; - i--) - if (txd.edx_hash_algorithm == esp_new_hash[i].type) - break; - if (i < 0) - { - DPRINTF(("esp_new_init(): unsupported authentication algorithm %d specified\n", txd.edx_hash_algorithm)); - return EINVAL; - } - - DPRINTF(("esp_new_init(): initialized TDB with hash algorithm %d: %s\n", - txd.edx_hash_algorithm, esp_new_hash[i].name)); - blocklen = HMAC_BLOCK_LEN; - thash = &esp_new_hash[i]; - } - - if (txd.edx_ivlen + txd.edx_confkeylen + txd.edx_authkeylen + - EMT_SETSPI_FLEN + ESP_NEW_XENCAP_LEN != em->em_msglen) - { - if (encdebug) - DPRINTF(("esp_new_init(): message length (%d) doesn't match\n", em->em_msglen)); + DPRINTF(("esp_new_init(): keylength %d too small (min length is %d) for algorithm %s\n", ii->ii_enckeylen, txform->minkey, txform->name)); return EINVAL; } - - /* Check the IV length */ - if (((txd.edx_ivlen == 0) && !(txform->ivmask&1)) || - ((txd.edx_ivlen != 0) && ( - !(txd.edx_ivlen & txform->ivmask) || - (txd.edx_ivlen & (txd.edx_ivlen - 1))))) + + if (ii->ii_enckeylen > txform->maxkey) { - DPRINTF(("esp_new_init(): unsupported IV length %d\n", txd.edx_ivlen)); + DPRINTF(("esp_new_init(): keylength %d too large (max length is %d) for algorithm %s\n", ii->ii_enckeylen, txform->maxkey, txform->name)); return EINVAL; } - /* Check the key length */ - if (txd.edx_confkeylen < txform->minkey || - txd.edx_confkeylen > txform->maxkey) + if (ii->ii_authalg) { - DPRINTF(("esp_new_init(): bad key length %d\n", txd.edx_confkeylen)); - return EINVAL; - } + for (i = sizeof(esp_new_hash) / sizeof(struct auth_hash) - 1; + i >= 0; i--) + if (ii->ii_authalg == esp_new_hash[i].type) + break; - MALLOC(tdbp->tdb_xdata, caddr_t, sizeof(struct esp_new_xdata), - M_XDATA, M_WAITOK); - if (tdbp->tdb_xdata == NULL) - { - DPRINTF(("esp_new_init(): MALLOC() failed\n")); - return ENOBUFS; - } + if (i < 0) + { + DPRINTF(("esp_new_init(): unsupported authentication algorithm %d specified\n", ii->ii_authalg)); + return EINVAL; + } - bzero(tdbp->tdb_xdata, sizeof(struct esp_new_xdata)); - xd = (struct esp_new_xdata *) tdbp->tdb_xdata; + thash = &esp_new_hash[i]; - /* Pointer to the transform */ - tdbp->tdb_xform = xsp; + 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)); + return EINVAL; + } + + tdbp->tdb_authalgxform = thash; - xd->edx_ivlen = txd.edx_ivlen; - xd->edx_enc_algorithm = txd.edx_enc_algorithm; - xd->edx_wnd = txd.edx_wnd; - xd->edx_flags = txd.edx_flags; - xd->edx_hash_algorithm = txd.edx_hash_algorithm; - xd->edx_bitmap = 0; - xd->edx_xform = txform; + DPRINTF(("esp_new_init(): initialized TDB with hash algorithm %s\n", + thash->name)); + } + + tdbp->tdb_xform = xsp; + tdbp->tdb_encalgxform = txform; + tdbp->tdb_bitmap = 0; + tdbp->tdb_rpl = AH_HMAC_INITIAL_RPL; - /* Pass name of enc algorithm for kernfs */ - tdbp->tdb_confname = xd->edx_xform->name; + DPRINTF(("esp_new_init(): initialized TDB with enc algorithm %s\n", + txform->name)); - /* Replay counters are mandatory, even without auth */ - xd->edx_rpl = AH_HMAC_INITIAL_RPL; + tdbp->tdb_ivlen = txform->ivmask; - /* Copy the IV */ - m_copydata(m, EMT_SETSPI_FLEN + ESP_NEW_XENCAP_LEN, xd->edx_ivlen, - (caddr_t) xd->edx_iv); + /* Initialize the IV */ + get_random_bytes(tdbp->tdb_iv, tdbp->tdb_ivlen); - /* Copy the key material */ - m_copydata(m, EMT_SETSPI_FLEN + ESP_NEW_XENCAP_LEN + xd->edx_ivlen, - txd.edx_confkeylen, (caddr_t) rk); - switch (xd->edx_enc_algorithm) + switch (ii->ii_encalg) { - case ALG_ENC_DES: - des_set_key((caddr_t) rk, (caddr_t) (xd->edx_eks[0])); + case SADB_EALG_DESCBC: + MALLOC(tdbp->tdb_key, u_int8_t *, 128, M_XDATA, M_WAITOK); + bzero(tdbp->tdb_key, 128); + des_set_key(ii->ii_enckey, tdbp->tdb_key); break; - case ALG_ENC_3DES: - des_set_key((caddr_t) rk, (caddr_t) (xd->edx_eks[0])); - des_set_key((caddr_t) (rk + 2), (caddr_t) (xd->edx_eks[1])); - des_set_key((caddr_t) (rk + 4), (caddr_t) (xd->edx_eks[2])); - break; - case ALG_ENC_BLF: - blf_key(&xd->edx_bks, (caddr_t) rk, txd.edx_confkeylen); + case SADB_EALG_3DESCBC: + MALLOC(tdbp->tdb_key, u_int8_t *, 384, M_XDATA, M_WAITOK); + bzero(tdbp->tdb_key, 384); + des_set_key(ii->ii_enckey, tdbp->tdb_key); + des_set_key(ii->ii_enckey + 8, tdbp->tdb_key + 128); + des_set_key(ii->ii_enckey + 16, tdbp->tdb_key + 256); break; - case ALG_ENC_CAST: - cast_setkey(&xd->edx_cks, (caddr_t) rk, txd.edx_confkeylen); + + case SADB_EALG_X_BLF: + MALLOC(tdbp->tdb_key, u_int8_t *, sizeof(blf_ctx), + M_XDATA, M_WAITOK); + bzero(tdbp->tdb_key, sizeof(blf_ctx)); + blf_key((blf_ctx *) tdbp->tdb_key, ii->ii_enckey, + ii->ii_enckeylen); break; - case ALG_ENC_SKIPJACK: - subkey_table_gen((caddr_t) rk, xd->edx_sks); + + case SADB_EALG_X_CAST: + MALLOC(tdbp->tdb_key, u_int8_t *, sizeof(cast_key), + M_XDATA, M_WAITOK); + bzero(tdbp->tdb_key, sizeof(cast_key)); + cast_setkey((cast_key *) tdbp->tdb_key, ii->ii_enckey, + ii->ii_enckeylen); break; } - if (txd.edx_flags & ESP_NEW_FLAG_AUTH) + if (thash) { - xd->edx_hash = thash; - - /* Pass name of auth algorithm for kernfs */ - tdbp->tdb_authname = xd->edx_hash->name; - - DPRINTF(("esp_new_init(): using %d bytes of authentication key\n", - txd.edx_authkeylen)); - - MALLOC(buffer, caddr_t, - txd.edx_authkeylen < blocklen ? blocklen : txd.edx_authkeylen, - M_TEMP, M_WAITOK); - if (buffer == NULL) - { - DPRINTF(("esp_new_init(): MALLOC() failed\n")); - free(tdbp->tdb_xdata, M_XDATA); - return ENOBUFS; - } - - bzero(buffer, txd.edx_authkeylen < blocklen ? - blocklen : txd.edx_authkeylen); - - /* Copy the key to the buffer */ - m_copydata(m, EMT_SETSPI_FLEN + ESP_NEW_XENCAP_LEN + xd->edx_ivlen + - txd.edx_confkeylen, txd.edx_authkeylen, buffer); - - /* Shorten the key if necessary */ - if (txd.edx_authkeylen > blocklen) - { - xd->edx_hash->Init(&(xd->edx_ictx)); - xd->edx_hash->Update(&(xd->edx_ictx), buffer, txd.edx_authkeylen); - bzero(buffer, txd.edx_authkeylen < blocklen ? - blocklen : txd.edx_authkeylen); - xd->edx_hash->Final(buffer, &(xd->edx_ictx)); - } - /* Precompute the I and O pads of the HMAC */ - for (i = 0; i < blocklen; i++) - buffer[i] ^= HMAC_IPAD_VAL; - - xd->edx_hash->Init(&(xd->edx_ictx)); - xd->edx_hash->Update(&(xd->edx_ictx), buffer, blocklen); + 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 < blocklen; i++) - buffer[i] ^= (HMAC_IPAD_VAL ^ HMAC_OPAD_VAL); - - xd->edx_hash->Init(&(xd->edx_octx)); - xd->edx_hash->Update(&(xd->edx_octx), buffer, blocklen); - - bzero(buffer, blocklen); - free(buffer, M_TEMP); + 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(rk, 14 * sizeof(u_int32_t)); /* paranoid */ - bzero(ipseczeroes, IPSEC_ZEROES_SIZE); /* paranoid */ - return 0; } int esp_new_zeroize(struct tdb *tdbp) { - struct esp_new_xdata *xd = (struct esp_new_xdata *) tdbp->tdb_xdata; - - DPRINTF(("esp_new_zeroize(): freeing memory\n")); - if (xd->edx_enc_algorithm == ALG_ENC_SKIPJACK) { - int k; + if (tdbp->tdb_key) + { + FREE(tdbp->tdb_key, M_XDATA); + tdbp->tdb_key = NULL; + } - for (k = 0; k < 10; k++) - free(xd->edx_sks[k], M_TEMP); + if (tdbp->tdb_ictx) + { + FREE(tdbp->tdb_ictx, M_XDATA); + tdbp->tdb_ictx = NULL; } - if (tdbp->tdb_xdata) + if (tdbp->tdb_octx) { - FREE(tdbp->tdb_xdata, M_XDATA); - tdbp->tdb_xdata = NULL; + FREE(tdbp->tdb_octx, M_XDATA); + tdbp->tdb_octx = NULL; } + return 0; } @@ -475,10 +364,11 @@ esp_new_zeroize(struct tdb *tdbp) struct mbuf * esp_new_input(struct mbuf *m, struct tdb *tdb) { + 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], niv[ESP_MAX_IVS]; u_char blk[ESP_MAX_BLKS], *lblk, opts[40]; int ohlen, oplen, plen, alen, ilen, i, blks, rest; - struct esp_new_xdata *xd; int count, off, errc; struct mbuf *mi, *mo; u_char *idat, *odat, *ivp, *ivn; @@ -492,11 +382,9 @@ esp_new_input(struct mbuf *m, struct tdb *tdb) } ctx; u_char buf[AH_ALEN_MAX], buf2[AH_ALEN_MAX]; - xd = (struct esp_new_xdata *) tdb->tdb_xdata; + blks = espx->blocksize; - blks = xd->edx_xform->blocksize; - - if (xd->edx_flags & ESP_NEW_FLAG_AUTH) + if (esph) alen = AH_HMAC_HASHLEN; else alen = 0; @@ -527,26 +415,52 @@ esp_new_input(struct mbuf *m, struct tdb *tdb) ip = mtod(m, struct ip *); } + /* Update the counters */ + tdb->tdb_cur_bytes += ip->ip_len - ohlen - alen; + espstat.esps_ibytes += ip->ip_len - ohlen - alen; + + /* Hard expiration */ + if ((tdb->tdb_flags & TDBF_BYTES) && + (tdb->tdb_cur_bytes >= tdb->tdb_exp_bytes)) + { +/* XXX + encap_sendnotify(NOTIFY_HARD_EXPIRE, tdb, NULL); +*/ + tdb_delete(tdb, 0); + m_freem(m); + return NULL; + } + + /* Notify on expiration */ + if ((tdb->tdb_flags & TDBF_SOFT_BYTES) && + (tdb->tdb_cur_bytes >= tdb->tdb_soft_bytes)) + { +/* XXX + encap_sendnotify(NOTIFY_SOFT_EXPIRE, tdb, NULL); +*/ + tdb->tdb_flags &= ~TDBF_SOFT_BYTES; /* Turn off checking */ + } + esp = (struct esp_new *) ((u_int8_t *) ip + (ip->ip_hl << 2)); ipo = *ip; /* Replay window checking */ - if (xd->edx_wnd >= 0) + if (tdb->tdb_wnd > 0) { btsx = ntohl(esp->esp_rpl); - if ((errc = checkreplaywindow32(btsx, 0, &(xd->edx_rpl), xd->edx_wnd, - &(xd->edx_bitmap))) != 0) + if ((errc = checkreplaywindow32(btsx, 0, &(tdb->tdb_rpl), tdb->tdb_wnd, + &(tdb->tdb_bitmap))) != 0) { switch(errc) { case 1: - DPRINTF(("esp_new_input(): replay counter wrapped for packets from %x to %x, spi %08x\n", ip->ip_src, ip->ip_dst, ntohl(esp->esp_spi))); + DPRINTF(("esp_new_input(): replay counter wrapped for packets from %s to %s, spi %08x\n", inet_ntoa4(ip->ip_src), inet_ntoa4(ip->ip_dst), ntohl(esp->esp_spi))); espstat.esps_wrap++; break; case 2: case 3: - DPRINTF(("esp_new_input(): duplicate packet received, %x->%x spi %08x\n", ip->ip_src, ip->ip_dst, ntohl(esp->esp_spi))); + DPRINTF(("esp_new_input(): duplicate packet received from %s to %s, spi %08x\n", inet_ntoa4(ip->ip_src), inet_ntoa4(ip->ip_dst), ntohl(esp->esp_spi))); espstat.esps_replay++; break; } @@ -558,22 +472,22 @@ esp_new_input(struct mbuf *m, struct tdb *tdb) /* Skip the IP header, IP options, SPI, SN and IV and minus Auth Data */ plen = m->m_pkthdr.len - (ip->ip_hl << 2) - 2 * sizeof(u_int32_t) - - xd->edx_ivlen - alen; + tdb->tdb_ivlen - alen; if ((plen & (blks - 1)) || (plen <= 0)) { - DPRINTF(("esp_new_input(): payload not a multiple of %d octets for packet from %x to %x, spi %08x\n", blks, ipo.ip_src, ipo.ip_dst, ntohl(tdb->tdb_spi))); + DPRINTF(("esp_new_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; } - if (xd->edx_flags & ESP_NEW_FLAG_AUTH) + if (esph) { - bcopy(&(xd->edx_ictx), &ctx, xd->edx_hash->ctxsize); + bcopy(tdb->tdb_ictx, &ctx, esph->ctxsize); /* Auth covers SPI + SN + IV */ - oplen = plen + 2 * sizeof(u_int32_t) + xd->edx_ivlen; + oplen = plen + 2 * sizeof(u_int32_t) + tdb->tdb_ivlen; off = (ip->ip_hl << 2); /* Copy the authentication data */ @@ -585,27 +499,27 @@ esp_new_input(struct mbuf *m, struct tdb *tdb) { if (mo == 0) { - DPRINTF(("esp_new_input(): bad mbuf chain for packet from %x to %x, spi %08x\n", ip->ip_src, ip->ip_dst, ntohl(esp->esp_spi))); + DPRINTF(("esp_new_input(): bad mbuf chain for packet from %s to %s, spi %08x\n", inet_ntoa4(ip->ip_src), inet_ntoa4(ip->ip_dst), ntohl(esp->esp_spi))); espstat.esps_hdrops++; m_freem(m); return NULL; } count = min(mo->m_len - off, oplen); - xd->edx_hash->Update(&ctx, mtod(mo, unsigned char *) + off, count); + esph->Update(&ctx, mtod(mo, unsigned char *) + off, count); oplen -= count; off = 0; mo = mo->m_next; } - xd->edx_hash->Final(buf2, &ctx); - bcopy(&(xd->edx_octx), &ctx, xd->edx_hash->ctxsize); - xd->edx_hash->Update(&ctx, buf2, xd->edx_hash->hashsize); - xd->edx_hash->Final(buf2, &ctx); + esph->Final(buf2, &ctx); + bcopy(tdb->tdb_octx, &ctx, esph->ctxsize); + esph->Update(&ctx, buf2, esph->hashsize); + esph->Final(buf2, &ctx); if (bcmp(buf2, buf, AH_HMAC_HASHLEN)) { - DPRINTF(("esp_new_input(): authentication failed for packet from %x to %x, spi %08x\n", ip->ip_src, ip->ip_dst, ntohl(esp->esp_spi))); + DPRINTF(("esp_new_input(): authentication failed for packet from %s to %s, spi %08x\n", inet_ntoa4(ip->ip_src), inet_ntoa4(ip->ip_dst), ntohl(esp->esp_spi))); espstat.esps_badauth++; m_freem(m); return NULL; @@ -616,21 +530,10 @@ esp_new_input(struct mbuf *m, struct tdb *tdb) ilen = m->m_len - (ip->ip_hl << 2) - 2 * sizeof(u_int32_t); idat = mtod(m, unsigned char *) + (ip->ip_hl << 2) + 2 * sizeof(u_int32_t); - if (xd->edx_ivlen == 0) /* Derived IV in use */ - { - bcopy((u_char *) &esp->esp_rpl, iv, sizeof(esp->esp_rpl)); - iv[4] = ~iv[0]; - iv[5] = ~iv[1]; - iv[6] = ~iv[2]; - iv[7] = ~iv[3]; - } - else - { - bcopy(idat, iv, xd->edx_ivlen); - ilen -= xd->edx_ivlen; - idat += xd->edx_ivlen; - } - + bcopy(idat, iv, tdb->tdb_ivlen); + ilen -= tdb->tdb_ivlen; + idat += tdb->tdb_ivlen; + mi = m; /* @@ -666,7 +569,7 @@ esp_new_input(struct mbuf *m, struct tdb *tdb) mi = (mo = mi)->m_next; if (mi == NULL) { - DPRINTF(("esp_new_input(): bad mbuf chain, SA %x/%08x\n", tdb->tdb_dst, ntohl(tdb->tdb_spi))); + DPRINTF(("esp_new_input(): bad mbuf chain, SA %s/%08x\n", ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi))); espstat.esps_hdrops++; m_freem(m); return NULL; @@ -677,7 +580,7 @@ esp_new_input(struct mbuf *m, struct tdb *tdb) { if ((mi = m_pullup(mi, blks - rest)) == NULL) { - DPRINTF(("esp_new_input(): m_pullup() failed, SA %x/%08x\n", tdb->tdb_dst, ntohl(tdb->tdb_spi))); + DPRINTF(("esp_new_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; @@ -697,7 +600,7 @@ esp_new_input(struct mbuf *m, struct tdb *tdb) bcopy(idat, blk + rest, blks - rest); bcopy(blk, ivn, blks); - xd->edx_xform->decrypt(xd, blk); + espx->decrypt(tdb, blk); for (i = 0; i < blks; i++) blk[i] ^= ivp[i]; @@ -722,7 +625,7 @@ esp_new_input(struct mbuf *m, struct tdb *tdb) { bcopy(idat, ivn, blks); - xd->edx_xform->decrypt(xd, idat); + espx->decrypt(tdb, idat); for (i = 0; i < blks; i++) idat[i] ^= ivp[i]; @@ -743,7 +646,7 @@ esp_new_input(struct mbuf *m, struct tdb *tdb) (caddr_t) opts); if (lblk != blk) - bcopy(lblk, blk, blks); + bcopy(lblk, blk, blks); /* * Now, the entire chain has been decrypted. As a side effect, @@ -753,58 +656,30 @@ esp_new_input(struct mbuf *m, struct tdb *tdb) * Verify correct decryption by checking the last padding bytes. */ - if ((xd->edx_flags & ESP_NEW_FLAG_NPADDING) == 0) + if (blk[blks - 2] + 2 + alen > m->m_pkthdr.len - (ip->ip_hl << 2) - 2 * sizeof(u_int32_t) - tdb->tdb_ivlen) { - if (blk[blks - 2] + 2 + alen > m->m_pkthdr.len - (ip->ip_hl << 2) - 2 * sizeof(u_int32_t) - xd->edx_ivlen) - { - DPRINTF(("esp_new_input(): invalid padding length %d for packet from %x to %x, SA %x/%08x\n", blk[blks - 2], ipo.ip_src, ipo.ip_dst, 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)) - { - DPRINTF(("esp_new_input(): decryption failed for packet from %x to %x, SA %x/%08x\n", ipo.ip_src, ipo.ip_dst, tdb->tdb_dst, ntohl(tdb->tdb_spi))); - m_freem(m); - return NULL; - } - - m_adj(m, - blk[blks - 2] - 2 - alen); /* Old type padding */ + DPRINTF(("esp_new_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; } - else + + if ((blk[blks - 2] != blk[blks - 3]) && (blk[blks - 2] != 0)) { - if (blk[blks - 2] + 1 + alen > m->m_pkthdr.len - (ip->ip_hl << 2) - 2 * sizeof(u_int32_t) - xd->edx_ivlen) - { - DPRINTF(("esp_new_input(): invalid padding length %d for packet from %x to %x, SA %x/%08x\n", blk[blks - 2], ipo.ip_src, ipo.ip_dst, tdb->tdb_dst, ntohl(tdb->tdb_spi))); - espstat.esps_badilen++; - m_freem(m); - return NULL; - } - if (blk[blks - 2] == 0) - { - DPRINTF(("esp_new_input(): decryption failed for packet from %x to %x, SA %x/%08x -- peer is probably using old style padding\n", ipo.ip_src, ipo.ip_dst, tdb->tdb_dst, ntohl(tdb->tdb_spi))); - m_freem(m); - return NULL; - } - else - if ((blk[blks - 2] != 1) && (blk[blks - 2] != blk[blks - 3] + 1)) - { - DPRINTF(("esp_new_input(): decryption failed for packet from %x to %x, SA %x/%08x\n", ipo.ip_src, ipo.ip_dst, tdb->tdb_dst, ntohl(tdb->tdb_spi))); - m_freem(m); - return NULL; - } - - m_adj(m, - blk[blks - 2] - 1 - alen); - } + DPRINTF(("esp_new_input(): decryption 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; + } - m_adj(m, 2 * sizeof(u_int32_t) + xd->edx_ivlen); + m_adj(m, - blk[blks - 2] - 2 - alen); /* Old type padding */ + m_adj(m, 2 * 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_new_input(): m_pullup() failed for packet from %x to %x, SA %x/%08x\n", ipo.ip_src, ipo.ip_dst, tdb->tdb_dst, ntohl(tdb->tdb_spi))); + DPRINTF(("esp_new_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; } @@ -814,11 +689,8 @@ esp_new_input(struct mbuf *m, struct tdb *tdb) ipo.ip_p = blk[blks - 1]; ipo.ip_id = htons(ipo.ip_id); ipo.ip_off = 0; - ipo.ip_len += (ipo.ip_hl << 2) - 2 * sizeof(u_int32_t) - xd->edx_ivlen - - blk[blks - 2] - 1 - alen; - - if ((xd->edx_flags & ESP_NEW_FLAG_NPADDING) == 0) - ipo.ip_len -= 1; + ipo.ip_len += (ipo.ip_hl << 2) - 2 * sizeof(u_int32_t) - tdb->tdb_ivlen - + blk[blks - 2] - 2 - alen; ipo.ip_len = htons(ipo.ip_len); ipo.ip_sum = 0; @@ -830,52 +702,6 @@ esp_new_input(struct mbuf *m, struct tdb *tdb) ip->ip_sum = in_cksum(m, (ip->ip_hl << 2)); - /* Update the counters */ - tdb->tdb_cur_packets++; - tdb->tdb_cur_bytes += ntohs(ip->ip_len) - (ip->ip_hl << 2) + - blk[blks - 2] + 1 + alen; - espstat.esps_ibytes += ntohs(ip->ip_len) - (ip->ip_hl << 2) + - blk[blks - 2] + 1 + alen; - - if ((xd->edx_flags & ESP_NEW_FLAG_NPADDING) == 0) - { - tdb->tdb_cur_bytes++; - espstat.esps_ibytes++; - } - - /* Notify on expiration */ - if (tdb->tdb_flags & TDBF_SOFT_PACKETS) - { - if (tdb->tdb_cur_packets >= tdb->tdb_soft_packets) - { - encap_sendnotify(NOTIFY_SOFT_EXPIRE, tdb, NULL); - tdb->tdb_flags &= ~TDBF_SOFT_PACKETS; - } - else - if (tdb->tdb_flags & TDBF_SOFT_BYTES) - if (tdb->tdb_cur_bytes >= tdb->tdb_soft_bytes) - { - encap_sendnotify(NOTIFY_SOFT_EXPIRE, tdb, NULL); - tdb->tdb_flags &= ~TDBF_SOFT_BYTES; - } - } - - if (tdb->tdb_flags & TDBF_PACKETS) - { - if (tdb->tdb_cur_packets >= tdb->tdb_exp_packets) - { - encap_sendnotify(NOTIFY_HARD_EXPIRE, tdb, NULL); - tdb_delete(tdb, 0); - } - else - if (tdb->tdb_flags & TDBF_BYTES) - if (tdb->tdb_cur_bytes >= tdb->tdb_exp_bytes) - { - encap_sendnotify(NOTIFY_HARD_EXPIRE, tdb, NULL); - tdb_delete(tdb, 0); - } - } - return m; } @@ -883,7 +709,8 @@ int esp_new_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb, struct mbuf **mp) { - struct esp_new_xdata *xd; + struct enc_xform *espx = (struct enc_xform *) tdb->tdb_encalgxform; + struct auth_hash *esph = (struct auth_hash *) tdb->tdb_authalgxform; struct ip *ip, ipo; int i, ilen, ohlen, nh, rlen, plen, padding, rest; struct esp_new espo; @@ -897,14 +724,12 @@ esp_new_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb, } ctx; int iphlen, blks, alen; - xd = (struct esp_new_xdata *) tdb->tdb_xdata; + blks = espx->blocksize; - blks = xd->edx_xform->blocksize; - - if (xd->edx_flags & ESP_NEW_FLAG_AUTH) + if (esph) { alen = AH_HMAC_HASHLEN; - DPRINTF(("esp_new_output(): using hash algorithm: %s\n", xd->edx_hash->name)); + DPRINTF(("esp_new_output(): using hash algorithm: %s\n", esph->name)); } else alen = 0; @@ -914,27 +739,53 @@ esp_new_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb, m = m_pullup(m, sizeof (struct ip)); /* Get IP header in one mbuf */ if (m == NULL) { - DPRINTF(("esp_new_output(): m_pullup() failed, SA %x/%08x\n", - tdb->tdb_dst, ntohl(tdb->tdb_spi))); + DPRINTF(("esp_new_output(): m_pullup() failed, SA %s/%08x\n", + ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi))); espstat.esps_hdrops++; return ENOBUFS; } - if (xd->edx_rpl == 0) + if (tdb->tdb_rpl == 0) { - DPRINTF(("esp_new_output(): SA %x/%0x8 should have expired\n", - tdb->tdb_dst, ntohl(tdb->tdb_spi))); + DPRINTF(("esp_new_output(): SA %s/%0x8 should have expired\n", + ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi))); m_freem(m); espstat.esps_wrap++; return ENOBUFS; } espo.esp_spi = tdb->tdb_spi; - espo.esp_rpl = htonl(xd->edx_rpl++); + espo.esp_rpl = htonl(tdb->tdb_rpl++); ip = mtod(m, struct ip *); iphlen = (ip->ip_hl << 2); + /* Update the counters */ + tdb->tdb_cur_bytes += ntohs(ip->ip_len) - (ip->ip_hl << 2); + espstat.esps_obytes += ntohs(ip->ip_len) - (ip->ip_hl << 2); + + /* Hard expiration */ + if ((tdb->tdb_flags & TDBF_BYTES) && + (tdb->tdb_cur_bytes >= tdb->tdb_exp_bytes)) + { +/* XXX + encap_sendnotify(NOTIFY_HARD_EXPIRE, tdb, NULL); +*/ + tdb_delete(tdb, 0); + m_freem(m); + return EINVAL; + } + + /* Notify on expiration */ + if ((tdb->tdb_flags & TDBF_SOFT_BYTES) && + (tdb->tdb_cur_bytes >= tdb->tdb_soft_bytes)) + { +/* XXX + encap_sendnotify(NOTIFY_SOFT_EXPIRE, tdb, NULL); +*/ + tdb->tdb_flags &= ~TDBF_SOFT_BYTES; /* Turn off checking */ + } + /* * If options are present, pullup the IP header, the options. */ @@ -943,8 +794,8 @@ esp_new_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb, m = m_pullup(m, iphlen + 8); if (m == NULL) { - DPRINTF(("esp_new_input(): m_pullup() failed for SA %x/%08x\n", - tdb->tdb_dst, ntohl(tdb->tdb_spi))); + DPRINTF(("esp_new_input(): m_pullup() failed for SA %s/%08x\n", + ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi))); espstat.esps_hdrops++; return ENOBUFS; } @@ -957,7 +808,7 @@ esp_new_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb, } ilen = ntohs(ip->ip_len); /* Size of the packet */ - ohlen = 2 * sizeof(u_int32_t) + xd->edx_ivlen; + ohlen = 2 * sizeof(u_int32_t) + tdb->tdb_ivlen; ipo = *ip; nh = ipo.ip_p; @@ -965,9 +816,10 @@ esp_new_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb, /* Raw payload length */ rlen = ilen - iphlen; padding = ((blks - ((rlen + 2) % blks)) % blks) + 2; - if (iphlen + ohlen + rlen + padding + alen > IP_MAXPACKET) { - DPRINTF(("esp_new_output(): packet in SA %x/%0x8 got too big\n", - tdb->tdb_dst, ntohl(tdb->tdb_spi))); + if (iphlen + ohlen + rlen + padding + alen > IP_MAXPACKET) + { + DPRINTF(("esp_new_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; @@ -976,8 +828,8 @@ esp_new_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb, pad = (u_char *) m_pad(m, padding + alen, 0); if (pad == NULL) { - DPRINTF(("esp_new_output(): m_pad() failed for SA %x/%08x\n", - tdb->tdb_dst, ntohl(tdb->tdb_spi))); + DPRINTF(("esp_new_output(): m_pad() failed for SA %s/%08x\n", + ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi))); return ENOBUFS; } @@ -985,11 +837,7 @@ esp_new_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb, for (i = 0; i < padding - 2; i++) pad[i] = i + 1; - if (xd->edx_flags & ESP_NEW_FLAG_NPADDING) - pad[padding - 2] = padding - 1; - else - pad[padding - 2] = padding - 2; - + pad[padding - 2] = padding - 2; pad[padding - 1] = nh; mi = m; @@ -997,26 +845,15 @@ esp_new_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb, ilen = m->m_len - iphlen; idat = mtod(m, u_char *) + iphlen; - if (xd->edx_ivlen == 0) - { - bcopy((u_char *) &espo.esp_rpl, iv, 4); - iv[4] = ~iv[0]; - iv[5] = ~iv[1]; - iv[6] = ~iv[2]; - iv[7] = ~iv[3]; - } - else - { - bcopy(xd->edx_iv, iv, xd->edx_ivlen); - bcopy(xd->edx_iv, espo.esp_iv, xd->edx_ivlen); - } + bcopy(tdb->tdb_iv, iv, tdb->tdb_ivlen); + bcopy(tdb->tdb_iv, espo.esp_iv, tdb->tdb_ivlen); /* Authenticate the esp header */ - if (xd->edx_flags & ESP_NEW_FLAG_AUTH) + if (esph) { - bcopy(&(xd->edx_ictx), &ctx, xd->edx_hash->ctxsize); - xd->edx_hash->Update(&ctx, (unsigned char *) &espo, - 2 * sizeof(u_int32_t) + xd->edx_ivlen); + bcopy(tdb->tdb_ictx, &ctx, esph->ctxsize); + esph->Update(&ctx, (unsigned char *) &espo, + 2 * sizeof(u_int32_t) + tdb->tdb_ivlen); } /* Encrypt the payload */ @@ -1043,7 +880,8 @@ esp_new_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb, mi = (mo = mi)->m_next; if (mi == NULL) { - DPRINTF(("esp_new_output(): bad mbuf chain, SA %x/%08x\n", tdb->tdb_dst, ntohl(tdb->tdb_spi))); + DPRINTF(("esp_new_output(): bad mbuf chain, SA %s/%08x\n", + ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi))); espstat.esps_hdrops++; m_freem(m); return EINVAL; @@ -1054,7 +892,7 @@ esp_new_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb, { if ((mi = m_pullup(mi, blks - rest)) == NULL) { - DPRINTF(("esp_new_output(): m_pullup() failed, SA %x/%08x\n", tdb->tdb_dst, ntohl(tdb->tdb_spi))); + DPRINTF(("esp_new_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; @@ -1076,10 +914,10 @@ esp_new_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb, for (i = 0; i < blks; i++) blk[i] ^= ivp[i]; - xd->edx_xform->encrypt(xd, blk); + espx->encrypt(tdb, blk); - if (xd->edx_flags & ESP_NEW_FLAG_AUTH) - xd->edx_hash->Update(&ctx, blk, blks); + if (esph) + esph->Update(&ctx, blk, blks); ivp = blk; @@ -1099,10 +937,10 @@ esp_new_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb, for (i = 0; i < blks; i++) idat[i] ^= ivp[i]; - xd->edx_xform->encrypt(xd, idat); + espx->encrypt(tdb, idat); - if (xd->edx_flags & ESP_NEW_FLAG_AUTH) - xd->edx_hash->Update(&ctx, idat, blks); + if (esph) + esph->Update(&ctx, idat, blks); ivp = idat; idat += blks; @@ -1113,12 +951,12 @@ esp_new_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb, } /* Put in authentication data */ - if (xd->edx_flags & ESP_NEW_FLAG_AUTH) + if (esph) { - xd->edx_hash->Final(auth, &ctx); - bcopy(&(xd->edx_octx), &ctx, xd->edx_hash->ctxsize); - xd->edx_hash->Update(&ctx, auth, xd->edx_hash->hashsize); - xd->edx_hash->Final(auth, &ctx); + esph->Final(auth, &ctx); + bcopy(tdb->tdb_octx, &ctx, esph->ctxsize); + esph->Update(&ctx, auth, esph->hashsize); + esph->Final(auth, &ctx); /* Copy the final authenticator */ bcopy(auth, pad + padding, alen); @@ -1132,16 +970,16 @@ esp_new_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb, M_PREPEND(m, ohlen, M_DONTWAIT); if (m == NULL) { - DPRINTF(("esp_new_output(): M_PREPEND failed, SA %x/%08x\n", - tdb->tdb_dst, ntohl(tdb->tdb_spi))); + DPRINTF(("esp_new_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_new_output(): m_pullup() failed, SA %x/%08x\n", - tdb->tdb_dst, ntohl(tdb->tdb_spi))); + DPRINTF(("esp_new_output(): m_pullup() failed, SA %s/%08x\n", + ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi))); espstat.esps_hdrops++; return ENOBUFS; } @@ -1151,7 +989,7 @@ esp_new_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb, ipo.ip_p = IPPROTO_ESP; /* Save the last encrypted block, to be used as the next IV */ - bcopy(ivp, xd->edx_iv, xd->edx_ivlen); + bcopy(ivp, tdb->tdb_iv, tdb->tdb_ivlen); m_copyback(m, 0, sizeof(struct ip), (caddr_t) &ipo); @@ -1165,44 +1003,6 @@ esp_new_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb, *mp = m; - /* Update the counters */ - tdb->tdb_cur_packets++; - tdb->tdb_cur_bytes += rlen + padding; - espstat.esps_obytes += rlen + padding; - - /* Notify on expiration */ - if (tdb->tdb_flags & TDBF_SOFT_PACKETS) - { - if (tdb->tdb_cur_packets >= tdb->tdb_soft_packets) - { - encap_sendnotify(NOTIFY_SOFT_EXPIRE, tdb, NULL); - tdb->tdb_flags &= ~TDBF_SOFT_PACKETS; - } - else - if (tdb->tdb_flags & TDBF_SOFT_BYTES) - if (tdb->tdb_cur_bytes >= tdb->tdb_soft_bytes) - { - encap_sendnotify(NOTIFY_SOFT_EXPIRE, tdb, NULL); - tdb->tdb_flags &= ~TDBF_SOFT_BYTES; - } - } - - if (tdb->tdb_flags & TDBF_PACKETS) - { - if (tdb->tdb_cur_packets >= tdb->tdb_exp_packets) - { - encap_sendnotify(NOTIFY_HARD_EXPIRE, tdb, NULL); - tdb_delete(tdb, 0); - } - else - if (tdb->tdb_flags & TDBF_BYTES) - if (tdb->tdb_cur_bytes >= tdb->tdb_exp_bytes) - { - encap_sendnotify(NOTIFY_HARD_EXPIRE, tdb, NULL); - tdb_delete(tdb, 0); - } - } - return 0; } @@ -1250,3 +1050,4 @@ checkreplaywindow32(u_int32_t seq, u_int32_t initial, u_int32_t *lastseq, *bitmap |= (((u_int32_t) 1) << diff); return 0; } + diff --git a/sys/netinet/ip_esp_old.c b/sys/netinet/ip_esp_old.c index 37e6a63f908..d8089df6866 100644 --- a/sys/netinet/ip_esp_old.c +++ b/sys/netinet/ip_esp_old.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_esp_old.c,v 1.27 1999/02/12 00:46:11 deraadt Exp $ */ +/* $OpenBSD: ip_esp_old.c,v 1.28 1999/02/24 22:33:03 angelos Exp $ */ /* * The authors of this code are John Ioannidis (ji@tla.org), @@ -63,11 +63,11 @@ #include <sys/socketvar.h> #include <net/raw_cb.h> -#include <net/encap.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 @@ -80,188 +80,123 @@ extern void des_ecb3_encrypt(caddr_t, caddr_t, caddr_t, caddr_t, caddr_t, int); extern void des_ecb_encrypt(caddr_t, caddr_t, caddr_t, int); extern void des_set_key(caddr_t, caddr_t); -extern int encap_sendnotify(int, struct tdb *, void *); +static void des1_encrypt(struct tdb *, u_int8_t *); +static void des3_encrypt(struct tdb *, u_int8_t *); +static void des1_decrypt(struct tdb *, u_int8_t *); +static void des3_decrypt(struct tdb *, u_int8_t *); -static void des1_encrypt(void *, u_int8_t *); -static void des3_encrypt(void *, u_int8_t *); -static void des1_decrypt(void *, u_int8_t *); -static void des3_decrypt(void *, u_int8_t *); - -struct esp_xform esp_old_xform[] = { - { ALG_ENC_DES, "Data Encryption Standard (DES)", +struct enc_xform esp_old_xform[] = { + { SADB_EALG_DESCBC, "Data Encryption Standard (DES)", ESP_DES_BLKS, ESP_DES_IVS, - 8, 8, 8 | 4, + 8, 8, 8, des1_encrypt, des1_decrypt }, - { ALG_ENC_3DES, "Triple DES (3DES)", + { SADB_EALG_3DESCBC, "Triple DES (3DES)", ESP_3DES_BLKS, ESP_3DES_IVS, - 24, 24, 8 | 4, + 24, 24, 8, des3_encrypt, des3_decrypt } }; static void -des1_encrypt(void *pxd, u_int8_t *blk) +des1_encrypt(struct tdb *tdb, u_int8_t *blk) { - struct esp_old_xdata *xd = pxd; - des_ecb_encrypt(blk, blk, (caddr_t) (xd->edx_eks[0]), 1); + des_ecb_encrypt(blk, blk, tdb->tdb_key, 1); } static void -des1_decrypt(void *pxd, u_int8_t *blk) +des1_decrypt(struct tdb *tdb, u_int8_t *blk) { - struct esp_old_xdata *xd = pxd; - des_ecb_encrypt(blk, blk, (caddr_t) (xd->edx_eks[0]), 0); + des_ecb_encrypt(blk, blk, tdb->tdb_key, 0); } static void -des3_encrypt(void *pxd, u_int8_t *blk) +des3_encrypt(struct tdb *tdb, u_int8_t *blk) { - struct esp_old_xdata *xd = pxd; - des_ecb3_encrypt(blk, blk, (caddr_t) (xd->edx_eks[2]), - (caddr_t) (xd->edx_eks[1]), - (caddr_t) (xd->edx_eks[0]), 1); + des_ecb3_encrypt(blk, blk, tdb->tdb_key, tdb->tdb_key + 128, + tdb->tdb_key + 256, 1); } static void -des3_decrypt(void *pxd, u_int8_t *blk) +des3_decrypt(struct tdb *tdb, u_int8_t *blk) { - struct esp_old_xdata *xd = pxd; - des_ecb3_encrypt(blk, blk, (caddr_t) (xd->edx_eks[2]), - (caddr_t) (xd->edx_eks[1]), - (caddr_t) (xd->edx_eks[0]), 0); + des_ecb3_encrypt(blk, blk, tdb->tdb_key + 256, tdb->tdb_key + 128, + tdb->tdb_key, 0); } int esp_old_attach() { - DPRINTF(("esp_old_attach(): setting up\n")); return 0; } /* - * esp_old_init() is called when an SPI is being set up. It interprets the - * encap_msghdr present in m, and sets up the transformation data, in - * this case, the encryption and decryption key schedules + * esp_old_init() is called when an SPI is being set up. */ int -esp_old_init(struct tdb *tdbp, struct xformsw *xsp, struct mbuf *m) +esp_old_init(struct tdb *tdbp, struct xformsw *xsp, struct ipsecinit *ii) { - struct esp_old_xdata *xd; - struct esp_old_xencap xenc; - struct encap_msghdr *em; - struct esp_xform *txform; - u_int32_t rk[6]; + struct enc_xform *txform = NULL; int i; - if (m->m_len < ENCAP_MSG_FIXED_LEN) - { - if ((m = m_pullup(m, ENCAP_MSG_FIXED_LEN)) == NULL) - { - DPRINTF(("esp_old_init(): m_pullup failed\n")); - return ENOBUFS; - } - } - - em = mtod(m, struct encap_msghdr *); - if (em->em_msglen - EMT_SETSPI_FLEN <= ESP_OLD_XENCAP_LEN) - { - DPRINTF(("esp_old_init(): initialization failed\n")); - return EINVAL; - } - - /* Just copy the standard fields */ - m_copydata(m, EMT_SETSPI_FLEN, ESP_OLD_XENCAP_LEN, (caddr_t) &xenc); - /* Check whether the encryption algorithm is supported */ - for (i=sizeof(esp_old_xform)/sizeof(struct esp_xform)-1; i >= 0; i--) - if (xenc.edx_enc_algorithm == esp_old_xform[i].type) - break; + for (i = sizeof(esp_old_xform) / sizeof(struct enc_xform) - 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", xenc.edx_enc_algorithm)); + DPRINTF(("esp_old_init(): unsupported encryption algorithm %d specified\n", ii->ii_encalg)); return EINVAL; } txform = &esp_old_xform[i]; - DPRINTF(("esp_old_init(): initialized TDB with enc algorithm %d: %s\n", - xenc.edx_enc_algorithm, esp_old_xform[i].name)); - - if (xenc.edx_ivlen + xenc.edx_keylen + EMT_SETSPI_FLEN + - ESP_OLD_XENCAP_LEN != em->em_msglen) - { - DPRINTF(("esp_old_init(): message length (%d) doesn't match\n", - em->em_msglen)); - return EINVAL; - } - /* Check the IV length */ - if (((xenc.edx_ivlen == 0) && !(txform->ivmask&1)) || - ((xenc.edx_ivlen != 0) && ( - !(xenc.edx_ivlen & txform->ivmask) || - (xenc.edx_ivlen & (xenc.edx_ivlen-1))))) + if (ii->ii_enckeylen < txform->minkey) { - DPRINTF(("esp_old_init(): unsupported IV length %d\n", - xenc.edx_ivlen)); + 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; } - - /* Check the key length */ - if (xenc.edx_keylen < txform->minkey || xenc.edx_keylen > txform->maxkey) + + if (ii->ii_enckeylen > txform->maxkey) { - DPRINTF(("esp_old_init(): bad key length %d\n", xenc.edx_keylen)); + 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; } - MALLOC(tdbp->tdb_xdata, caddr_t, sizeof(struct esp_old_xdata), - M_XDATA, M_WAITOK); - if (tdbp->tdb_xdata == NULL) - { - DPRINTF(("esp_old_init(): MALLOC() failed\n")); - return ENOBUFS; - } - - bzero(tdbp->tdb_xdata, sizeof(struct esp_old_xdata)); - xd = (struct esp_old_xdata *) tdbp->tdb_xdata; - - /* Pointer to the transform */ tdbp->tdb_xform = xsp; + tdbp->tdb_encalgxform = txform; - xd->edx_ivlen = xenc.edx_ivlen; - xd->edx_xform = txform; - xd->edx_enc_algorithm = xenc.edx_enc_algorithm; + DPRINTF(("esp_old_init(): initialized TDB with enc algorithm %s\n", + txform->name)); - /* Pass name of enc algorithm for kernfs */ - tdbp->tdb_confname = xd->edx_xform->name; + tdbp->tdb_ivlen = txform->ivmask; + if (tdbp->tdb_flags & TDBF_HALFIV) + tdbp->tdb_ivlen /= 2; - /* Copy the IV */ - m_copydata(m, EMT_SETSPI_FLEN + ESP_OLD_XENCAP_LEN, xd->edx_ivlen, - (caddr_t) xd->edx_iv); + get_random_bytes(tdbp->tdb_iv, tdbp->tdb_ivlen); - /* Copy the key material */ - m_copydata(m, EMT_SETSPI_FLEN + ESP_OLD_XENCAP_LEN + xd->edx_ivlen, - xenc.edx_keylen, (caddr_t) rk); - - switch (xd->edx_enc_algorithm) + switch (ii->ii_encalg) { - case ALG_ENC_DES: - des_set_key((caddr_t) rk, (caddr_t) (xd->edx_eks[0])); + case SADB_EALG_DESCBC: + MALLOC(tdbp->tdb_key, u_int8_t *, 128, M_XDATA, M_WAITOK); + bzero(tdbp->tdb_key, 128); + des_set_key(ii->ii_enckey, tdbp->tdb_key); break; - case ALG_ENC_3DES: - des_set_key((caddr_t) rk, (caddr_t) (xd->edx_eks[0])); - des_set_key((caddr_t) (rk + 2), (caddr_t) (xd->edx_eks[1])); - des_set_key((caddr_t) (rk + 4), (caddr_t) (xd->edx_eks[2])); + case SADB_EALG_3DESCBC: + MALLOC(tdbp->tdb_key, u_int8_t *, 384, M_XDATA, M_WAITOK); + bzero(tdbp->tdb_key, 384); + des_set_key(ii->ii_enckey, tdbp->tdb_key); + des_set_key(ii->ii_enckey + 8, tdbp->tdb_key + 128); + des_set_key(ii->ii_enckey + 16, tdbp->tdb_key + 256); break; } - bzero(rk, 6 * sizeof(u_int32_t)); /* paranoid */ - - bzero(ipseczeroes, IPSEC_ZEROES_SIZE); /* paranoid */ - return 0; } @@ -269,12 +204,12 @@ esp_old_init(struct tdb *tdbp, struct xformsw *xsp, struct mbuf *m) int esp_old_zeroize(struct tdb *tdbp) { - DPRINTF(("esp_old_zeroize(): freeing memory\n")); - if (tdbp->tdb_xdata) + if (tdbp->tdb_key) { - FREE(tdbp->tdb_xdata, M_XDATA); - tdbp->tdb_xdata = NULL; + FREE(tdbp->tdb_key, M_XDATA); + tdbp->tdb_key = NULL; } + return 0; } @@ -284,7 +219,7 @@ esp_old_zeroize(struct tdb *tdbp) struct mbuf * esp_old_input(struct mbuf *m, struct tdb *tdb) { - struct esp_old_xdata *xd; + 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; @@ -292,9 +227,7 @@ esp_old_input(struct mbuf *m, struct tdb *tdb) int ohlen, plen, ilen, i, blks, rest; struct mbuf *mi, *mo; - xd = (struct esp_old_xdata *) tdb->tdb_xdata; - - blks = xd->edx_xform->blocksize; + blks = espx->blocksize; if (m->m_len < sizeof(struct ip)) { @@ -323,20 +256,45 @@ esp_old_input(struct mbuf *m, struct tdb *tdb) } 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) - - xd->edx_ivlen; + tdb->tdb_ivlen; if ((plen & (blks - 1)) || (plen <= 0)) { - DPRINTF(("esp_old_input(): payload not a multiple of %d octets for packet from %x to %x, spi %08x\n", blks, ipo.ip_src, ipo.ip_dst, ntohl(tdb->tdb_spi))); + 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)) + { +/* XXX + encap_sendnotify(NOTIFY_HARD_EXPIRE, tdb, NULL); +*/ + tdb_delete(tdb, 0); + m_freem(m); + return NULL; + } + + /* Notify on expiration */ + if ((tdb->tdb_flags & TDBF_SOFT_BYTES) && + (tdb->tdb_cur_bytes >= tdb->tdb_soft_bytes)) + { +/* XXX + encap_sendnotify(NOTIFY_SOFT_EXPIRE, tdb, NULL); +*/ + 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; @@ -345,7 +303,7 @@ esp_old_input(struct mbuf *m, struct tdb *tdb) iv[1] = esp->esp_iv[1]; iv[2] = esp->esp_iv[2]; iv[3] = esp->esp_iv[3]; - if (xd->edx_ivlen == 4) /* Half-IV */ + if (tdb->tdb_ivlen == 4) /* Half-IV */ { iv[4] = ~esp->esp_iv[0]; iv[5] = ~esp->esp_iv[1]; @@ -399,8 +357,8 @@ esp_old_input(struct mbuf *m, struct tdb *tdb) mi = (mo = mi)->m_next; if (mi == NULL) { - DPRINTF(("esp_old_input(): bad mbuf chain, SA %x/%08x\n", - tdb->tdb_dst, ntohl(tdb->tdb_spi))); + 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; @@ -411,7 +369,7 @@ esp_old_input(struct mbuf *m, struct tdb *tdb) { if ((mi = m_pullup(mi, blks - rest)) == NULL) { - DPRINTF(("esp_old_input(): m_pullup() failed, SA %x/%08x\n", tdb->tdb_dst, ntohl(tdb->tdb_spi))); + 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; } @@ -430,9 +388,9 @@ esp_old_input(struct mbuf *m, struct tdb *tdb) bcopy(idat, blk + rest, blks - rest); bcopy(blk, ivn, blks); - xd->edx_xform->decrypt(xd, blk); + espx->decrypt(tdb, blk); - for (i=0; i<blks; i++) + for (i=0; i < blks; i++) blk[i] ^= ivp[i]; ivp = ivn; @@ -455,7 +413,7 @@ esp_old_input(struct mbuf *m, struct tdb *tdb) { bcopy(idat, ivn, blks); - xd->edx_xform->decrypt(xd, idat); + espx->decrypt(tdb, idat); for (i = 0; i < blks; i++) idat[i] ^= ivp[i]; @@ -476,7 +434,7 @@ esp_old_input(struct mbuf *m, struct tdb *tdb) (caddr_t) opts); if (lblk != blk) - bcopy(lblk, blk, blks); + bcopy(lblk, blk, blks); /* * Now, the entire chain has been decrypted. As a side effect, @@ -487,24 +445,24 @@ esp_old_input(struct mbuf *m, struct tdb *tdb) * the padding may be random. */ - if (blk[blks - 2] + 2 > m->m_pkthdr.len - (ip->ip_hl << 2) - sizeof(u_int32_t) - - xd->edx_ivlen) + 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 %x to %x, SA %x/%08x\n", blk[blks - 2], ipo.ip_src, ipo.ip_dst, tdb->tdb_dst, ntohl(tdb->tdb_spi))); + 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, 4 + xd->edx_ivlen); + 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 %x to %x, SA %x/%08x\n", ipo.ip_src, ipo.ip_dst, tdb->tdb_dst, ntohl(tdb->tdb_spi))); + 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; } @@ -514,7 +472,7 @@ esp_old_input(struct mbuf *m, struct tdb *tdb) 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) - xd->edx_ivlen - + 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; @@ -526,46 +484,6 @@ esp_old_input(struct mbuf *m, struct tdb *tdb) ip->ip_sum = in_cksum(m, (ip->ip_hl << 2)); - /* Update the counters */ - tdb->tdb_cur_packets++; - tdb->tdb_cur_bytes += ntohs(ip->ip_len) - (ip->ip_hl << 2) + - blk[blks - 2] + 2; - espstat.esps_ibytes += ntohs(ip->ip_len) - (ip->ip_hl << 2) + - blk[blks - 2] + 2; - - /* Notify on expiration */ - if (tdb->tdb_flags & TDBF_SOFT_PACKETS) - { - if (tdb->tdb_cur_packets >= tdb->tdb_soft_packets) - { - encap_sendnotify(NOTIFY_SOFT_EXPIRE, tdb, NULL); - tdb->tdb_flags &= ~TDBF_SOFT_PACKETS; - } - else - if (tdb->tdb_flags & TDBF_SOFT_BYTES) - if (tdb->tdb_cur_bytes >= tdb->tdb_soft_bytes) - { - encap_sendnotify(NOTIFY_SOFT_EXPIRE, tdb, NULL); - tdb->tdb_flags &= ~TDBF_SOFT_BYTES; - } - } - - if (tdb->tdb_flags & TDBF_PACKETS) - { - if (tdb->tdb_cur_packets >= tdb->tdb_exp_packets) - { - encap_sendnotify(NOTIFY_HARD_EXPIRE, tdb, NULL); - tdb_delete(tdb, 0); - } - else - if (tdb->tdb_flags & TDBF_BYTES) - if (tdb->tdb_cur_bytes >= tdb->tdb_exp_bytes) - { - encap_sendnotify(NOTIFY_HARD_EXPIRE, tdb, NULL); - tdb_delete(tdb, 0); - } - } - return m; } @@ -573,7 +491,7 @@ int esp_old_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb, struct mbuf **mp) { - struct esp_old_xdata *xd; + 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; @@ -582,17 +500,15 @@ esp_old_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb, u_char iv[ESP_3DES_IVS], blk[ESP_3DES_IVS], opts[40]; int iphlen, blks; - xd = (struct esp_old_xdata *) tdb->tdb_xdata; - - blks = xd->edx_xform->blocksize; + blks = espx->blocksize; espstat.esps_output++; m = m_pullup(m, sizeof(struct ip)); if (m == NULL) { - DPRINTF(("esp_old_output(): m_pullup() failed for SA %x/%08x\n", - tdb->tdb_dst, ntohl(tdb->tdb_spi))); + 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; } @@ -609,8 +525,8 @@ esp_old_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb, m = m_pullup(m, iphlen); if (m == NULL) { - DPRINTF(("esp_old_output(): m_pullup() failed for SA %x/%08x\n", - tdb->tdb_dst, ntohl(tdb->tdb_spi))); + 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; } @@ -623,7 +539,7 @@ esp_old_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb, } ilen = ntohs(ip->ip_len); - ohlen = sizeof(u_int32_t) + xd->edx_ivlen; + ohlen = sizeof(u_int32_t) + tdb->tdb_ivlen; ipo = *ip; nh = ipo.ip_p; @@ -631,19 +547,46 @@ esp_old_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb, /* 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 %x/%0x8 got too big\n", - tdb->tdb_dst, ntohl(tdb->tdb_spi))); + 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)) + { +/* XXX + encap_sendnotify(NOTIFY_HARD_EXPIRE, tdb, NULL); +*/ + tdb_delete(tdb, 0); + m_freem(m); + return EINVAL; + } + + /* Notify on expiration */ + if ((tdb->tdb_flags & TDBF_SOFT_BYTES) && + (tdb->tdb_cur_bytes >= tdb->tdb_soft_bytes)) + { +/* XXX + encap_sendnotify(NOTIFY_SOFT_EXPIRE, tdb, NULL); +*/ + 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 %x/%08x\n", - tdb->tdb_dst, ntohl(tdb->tdb_spi))); + DPRINTF(("esp_old_output(): m_pad() failed for SA %s/%08x\n", + ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi))); return ENOBUFS; } @@ -659,24 +602,24 @@ esp_old_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb, * We are now ready to encrypt the payload. */ - iv[0] = xd->edx_iv[0]; - iv[1] = xd->edx_iv[1]; - iv[2] = xd->edx_iv[2]; - iv[3] = xd->edx_iv[3]; + 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 (xd->edx_ivlen == 4) /* Half-IV */ + if (tdb->tdb_ivlen == 4) /* Half-IV */ { - iv[4] = ~xd->edx_iv[0]; - iv[5] = ~xd->edx_iv[1]; - iv[6] = ~xd->edx_iv[2]; - iv[7] = ~xd->edx_iv[3]; + 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] = xd->edx_iv[4]; - iv[5] = xd->edx_iv[5]; - iv[6] = xd->edx_iv[6]; - iv[7] = xd->edx_iv[7]; + 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; @@ -701,8 +644,9 @@ esp_old_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb, mi = (mo = mi)->m_next; if (mi == NULL) { - DPRINTF(("esp_old_output(): bad mbuf chain, SA %x/%08x\n", - tdb->tdb_dst, ntohl(tdb->tdb_spi))); + 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; } @@ -712,7 +656,7 @@ esp_old_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb, { if ((mi = m_pullup(mi, blks - rest)) == NULL) { - DPRINTF(("esp_old_output(): m_pullup() failed, SA %x/%08x\n", tdb->tdb_dst, ntohl(tdb->tdb_spi))); + 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; @@ -733,7 +677,7 @@ esp_old_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb, for (i=0; i<blks; i++) blk[i] ^= ivp[i]; - xd->edx_xform->encrypt(xd, blk); + espx->encrypt(tdb, blk); ivp = blk; @@ -753,7 +697,7 @@ esp_old_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb, for (i = 0; i < blks; i++) idat[i] ^= ivp[i]; - xd->edx_xform->encrypt(xd, idat); + espx->encrypt(tdb, idat); ivp = idat; idat += blks; @@ -771,16 +715,16 @@ esp_old_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb, M_PREPEND(m, ohlen, M_DONTWAIT); if (m == NULL) { - DPRINTF(("esp_old_output(): M_PREPEND failed, SA %x/%08x\n", - tdb->tdb_dst, ntohl(tdb->tdb_spi))); + 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 %x/%08x\n", - tdb->tdb_dst, ntohl(tdb->tdb_spi))); + 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; } @@ -788,21 +732,21 @@ esp_old_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb, ipo.ip_len = htons(iphlen + ohlen + rlen + padding); ipo.ip_p = IPPROTO_ESP; - iv[0] = xd->edx_iv[0]; - iv[1] = xd->edx_iv[1]; - iv[2] = xd->edx_iv[2]; - iv[3] = xd->edx_iv[3]; + 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 (xd->edx_ivlen == 8) + if (tdb->tdb_ivlen == 8) { - iv[4] = xd->edx_iv[4]; - iv[5] = xd->edx_iv[5]; - iv[6] = xd->edx_iv[6]; - iv[7] = xd->edx_iv[7]; + 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, xd->edx_iv, xd->edx_ivlen); + bcopy(ivp, tdb->tdb_iv, tdb->tdb_ivlen); m_copyback(m, 0, sizeof(struct ip), (caddr_t) &ipo); @@ -812,48 +756,10 @@ esp_old_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb, (caddr_t) opts); m_copyback(m, iphlen, sizeof(u_int32_t), (caddr_t) &spi); - m_copyback(m, iphlen + sizeof(u_int32_t), xd->edx_ivlen, (caddr_t) iv); + m_copyback(m, iphlen + sizeof(u_int32_t), tdb->tdb_ivlen, (caddr_t) iv); *mp = m; - /* Update the counters */ - tdb->tdb_cur_packets++; - tdb->tdb_cur_bytes += rlen + padding; - espstat.esps_obytes += rlen + padding; - - /* Notify on expiration */ - if (tdb->tdb_flags & TDBF_SOFT_PACKETS) - { - if (tdb->tdb_cur_packets >= tdb->tdb_soft_packets) - { - encap_sendnotify(NOTIFY_SOFT_EXPIRE, tdb, NULL); - tdb->tdb_flags &= ~TDBF_SOFT_PACKETS; - } - else - if (tdb->tdb_flags & TDBF_SOFT_BYTES) - if (tdb->tdb_cur_bytes >= tdb->tdb_soft_bytes) - { - encap_sendnotify(NOTIFY_SOFT_EXPIRE, tdb, NULL); - tdb->tdb_flags &= ~TDBF_SOFT_BYTES; - } - } - - if (tdb->tdb_flags & TDBF_PACKETS) - { - if (tdb->tdb_cur_packets >= tdb->tdb_exp_packets) - { - encap_sendnotify(NOTIFY_HARD_EXPIRE, tdb, NULL); - tdb_delete(tdb, 0); - } - else - if (tdb->tdb_flags & TDBF_BYTES) - if (tdb->tdb_cur_bytes >= tdb->tdb_exp_bytes) - { - encap_sendnotify(NOTIFY_HARD_EXPIRE, tdb, NULL); - tdb_delete(tdb, 0); - } - } - return 0; } diff --git a/sys/netinet/ip_ip4.c b/sys/netinet/ip_ip4.c index 0315ea03494..46406781679 100644 --- a/sys/netinet/ip_ip4.c +++ b/sys/netinet/ip_ip4.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_ip4.c,v 1.22 1999/01/08 21:51:21 provos Exp $ */ +/* $OpenBSD: ip_ip4.c,v 1.23 1999/02/24 22:33:04 angelos Exp $ */ /* * The authors of this code are John Ioannidis (ji@tla.org), @@ -64,13 +64,16 @@ #include <sys/socketvar.h> #include <net/raw_cb.h> -#include <net/encap.h> #include <netinet/ip_ipsp.h> #include <netinet/ip_ip4.h> #include <dev/rndvar.h> -#include <sys/syslog.h> +#ifdef ENCDEBUG +#define DPRINTF(x) if (encdebug) printf x +#else +#define DPRINTF(x) +#endif /* * ip4_input gets called when we receive an encapsulated packet, @@ -105,11 +108,7 @@ ip4_input(m, va_alist) */ if (iphlen > sizeof(struct ip)) { -#ifdef ENCDEBUG - if (encdebug) - printf("ip4_input(): stripping options\n"); -#endif /* ENCDEBUG */ - + DPRINTF(("ip4_input(): stripping options\n")); ip_stripoptions(m, (struct mbuf *) 0); iphlen = sizeof(struct ip); } @@ -128,11 +127,7 @@ ip4_input(m, va_alist) { if ((m = m_pullup(m, iphlen + sizeof(struct ip))) == 0) { -#ifdef ENCDEBUG - if (encdebug) - printf("ip4_input(): m_pullup() failed\n"); -#endif /* ENCDEBUG */ - + DPRINTF(("ip4_input(): m_pullup() failed\n")); ip4stat.ip4s_hdrops++; return; } @@ -151,8 +146,7 @@ ip4_input(m, va_alist) if (ipi->ip_v != IPVERSION) { - if (encdebug) - log(LOG_WARNING, "ip4_input(): wrong version %d on IP packet from %x to %x (%x->%x)\n", ipi->ip_v, ipo->ip_src, ipo->ip_dst, ipi->ip_src, ipi->ip_dst); + DPRINTF(("ip4_input(): wrong version %d on packet from %s to %s (%s->%s)\n", ipi->ip_v, inet_ntoa4(ipo->ip_src), inet_ntoa4(ipo->ip_dst), inet_ntoa4(ipi->ip_src), inet_ntoa4(ipi->ip_dst))); ip4stat.ip4s_notip4++; return; } @@ -165,7 +159,6 @@ ip4_input(m, va_alist) m->m_len -= iphlen; m->m_pkthdr.len -= iphlen; m->m_data += iphlen; - m->m_flags |= M_TUNNEL; /* * Interface pointer stays the same; if no IPsec processing has @@ -184,10 +177,8 @@ ip4_input(m, va_alist) m_freem(m); ip4stat.ip4s_qfull++; splx(s); -#ifdef ENCDEBUG - if (encdebug) - printf("ip4_input(): packet dropped because of full queue\n"); -#endif /* ENCDEBUG */ + + DPRINTF(("ip4_input(): packet dropped because of full queue\n")); return; } @@ -204,6 +195,23 @@ ipe4_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb, struct ip *ipo, *ipi; ushort ilen; + /* Check that the source address, if present, is from AF_INET */ + if ((tdb->tdb_src.sa.sa_family != 0) && + (tdb->tdb_src.sa.sa_family != AF_INET)) + { + DPRINTF(("ipe4_output(): IP in protocol-family <%d> attempted, aborting", tdb->tdb_src.sa.sa_family)); + m_freem(m); + return EINVAL; + } + + /* Check that the destination address is AF_INET */ + if (tdb->tdb_src.sa.sa_family != AF_INET) + { + DPRINTF(("ipe4_output(): IP in protocol-family <%d> attempted, aborting", tdb->tdb_dst.sa.sa_family)); + m_freem(m); + return EINVAL; + } + ip4stat.ip4s_opackets++; ipi = mtod(m, struct ip *); ilen = ntohs(ipi->ip_len); @@ -211,10 +219,7 @@ ipe4_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb, M_PREPEND(m, sizeof(struct ip), M_DONTWAIT); if (m == 0) { -#ifdef ENCDEBUG - if (encdebug) - printf("ipe4_output(): M_PREPEND failed\n"); -#endif /* ENCDEBUG */ + DPRINTF(("ipe4_output(): M_PREPEND failed\n")); return ENOBUFS; } @@ -226,63 +231,33 @@ ipe4_output(struct mbuf *m, struct sockaddr_encap *gw, struct tdb *tdb, ipo->ip_len = htons(ilen + sizeof(struct ip)); ipo->ip_id = ip_randomid(); HTONS(ipo->ip_id); - ipo->ip_off = ipi->ip_off & ~(IP_MF | IP_OFFMASK); /* keep C and DF */ - - if (tdb->tdb_flags & TDBF_SAME_TTL) - ipo->ip_ttl = ipi->ip_ttl; - else - if (tdb->tdb_ttl == 0) - ipo->ip_ttl = ip_defttl; - else - ipo->ip_ttl = tdb->tdb_ttl; - + ipo->ip_off = ipi->ip_off & ~(IP_MF | IP_OFFMASK); /* XXX keep C and DF */ + ipo->ip_ttl = ip_defttl; ipo->ip_p = IPPROTO_IPIP; ipo->ip_sum = 0; - ipo->ip_src = tdb->tdb_osrc; - ipo->ip_dst = tdb->tdb_odst; - -/* - * printf("ip4_output: [%x->%x](l=%d, p=%d)", - * ntohl(ipi->ip_src.s_addr), ntohl(ipi->ip_dst.s_addr), - * ilen, ipi->ip_p); - * printf(" through [%x->%x](l=%d, p=%d)\n", - * ntohl(ipo->ip_src.s_addr), ntohl(ipo->ip_dst.s_addr), - * ipo->ip_len, ipo->ip_p); - */ + + ipo->ip_src = tdb->tdb_src.sin.sin_addr; + ipo->ip_dst = tdb->tdb_dst.sin.sin_addr; *mp = m; /* Update the counters */ if (tdb->tdb_xform->xf_type == XF_IP4) - { - tdb->tdb_cur_packets++; - tdb->tdb_cur_bytes += ntohs(ipo->ip_len) - (ipo->ip_hl << 2); - } + tdb->tdb_cur_bytes += ntohs(ipo->ip_len) - (ipo->ip_hl << 2); ip4stat.ip4s_obytes += ntohs(ipo->ip_len) - (ipo->ip_hl << 2); - return 0; - -/* return ip_output(m, NULL, NULL, IP_ENCAPSULATED, NULL); */ } int ipe4_attach() { -#ifdef ENCDEBUG - if (encdebug) - printf("ipe4_attach(): setting up\n"); -#endif /* ENCDEBUG */ return 0; } int -ipe4_init(struct tdb *tdbp, struct xformsw *xsp, struct mbuf *m) +ipe4_init(struct tdb *tdbp, struct xformsw *xsp, struct ipsecinit *ii) { -#ifdef ENCDEBUG - if (encdebug) - printf("ipe4_init(): setting up\n"); -#endif /* ENCDEBUG */ tdbp->tdb_xform = xsp; return 0; } @@ -290,10 +265,6 @@ ipe4_init(struct tdb *tdbp, struct xformsw *xsp, struct mbuf *m) int ipe4_zeroize(struct tdb *tdbp) { -#ifdef ENCDEBUG - if (encdebug) - printf("ipe4_zeroize(): nothing to do really...\n"); -#endif /* ENCDEBUG */ return 0; } @@ -301,7 +272,7 @@ void ipe4_input(struct mbuf *m, ...) { /* This is a rather serious mistake, so no conditional printing */ - log(LOG_ALERT, "ipe4_input(): should never be called\n"); + printf("ipe4_input(): should never be called\n"); if (m) m_freem(m); } diff --git a/sys/netinet/ip_ip4.h b/sys/netinet/ip_ip4.h index 96df0bab5de..ead2d231566 100644 --- a/sys/netinet/ip_ip4.h +++ b/sys/netinet/ip_ip4.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_ip4.h,v 1.11 1999/02/17 18:10:38 deraadt Exp $ */ +/* $OpenBSD: ip_ip4.h,v 1.12 1999/02/24 22:33:04 angelos Exp $ */ /* * The authors of this code are John Ioannidis (ji@tla.org), @@ -38,15 +38,16 @@ * Not quite all the functionality of RFC-1853, but the main idea is there. */ -struct ip4stat { - u_int32_t ip4s_ipackets; /* total input packets */ - u_int32_t ip4s_opackets; /* total output packets */ - u_int32_t ip4s_hdrops; /* packet shorter than header shows */ - u_int32_t ip4s_badlen; - u_int32_t ip4s_notip4; - u_int32_t ip4s_qfull; - u_int64_t ip4s_ibytes; - u_int64_t ip4s_obytes; +struct ip4stat +{ + u_int32_t ip4s_ipackets; /* total input packets */ + u_int32_t ip4s_opackets; /* total output packets */ + u_int32_t ip4s_hdrops; /* packet shorter than header shows */ + u_int32_t ip4s_badlen; + u_int32_t ip4s_notip4; + u_int32_t ip4s_qfull; + u_int64_t ip4s_ibytes; + u_int64_t ip4s_obytes; }; #define IP4_DEFAULT_TTL 0 diff --git a/sys/netinet/ip_ipsp.c b/sys/netinet/ip_ipsp.c index 76f1397020d..139e21e6721 100644 --- a/sys/netinet/ip_ipsp.c +++ b/sys/netinet/ip_ipsp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_ipsp.c,v 1.31 1999/01/11 22:52:10 deraadt Exp $ */ +/* $OpenBSD: ip_ipsp.c,v 1.32 1999/02/24 22:33:05 angelos Exp $ */ /* * The authors of this code are John Ioannidis (ji@tla.org), @@ -62,14 +62,13 @@ #include <netinet/ip_icmp.h> #include <net/raw_cb.h> -#include <net/encap.h> +#include <net/pfkeyv2.h> #include <netinet/ip_ipsp.h> #include <netinet/ip_ah.h> #include <netinet/ip_esp.h> #include <dev/rndvar.h> -#include <sys/syslog.h> #ifdef ENCDEBUG #define DPRINTF(x) if (encdebug) printf x @@ -77,19 +76,37 @@ #define DPRINTF(x) #endif -int tdb_init __P((struct tdb *, struct mbuf *)); int ipsp_kern __P((int, char **, int)); u_int8_t get_sa_require __P((struct inpcb *)); int check_ipsec_policy __P((struct inpcb *, u_int32_t)); -extern void encap_sendnotify __P((int, struct tdb *, void *)); extern int ipsec_auth_default_level; extern int ipsec_esp_trans_default_level; extern int ipsec_esp_network_default_level; int encdebug = 0; +int ipsec_in_use = 0; u_int32_t kernfs_epoch = 0; +u_int8_t hmac_ipad_buffer[64] = { + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36 }; + +u_int8_t hmac_opad_buffer[64] = { + 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, + 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, + 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, + 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, + 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, + 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, + 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, + 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C }; /* * This is the proper place to define the various encapsulation transforms. @@ -100,7 +117,7 @@ struct xformsw xformsw[] = { ipe4_attach, ipe4_init, ipe4_zeroize, (struct mbuf * (*)(struct mbuf *, struct tdb *))ipe4_input, ipe4_output, }, - { XF_OLD_AH, XFT_AUTH, "Keyed Authentication, RFC 1828/1852", + { 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", @@ -126,25 +143,28 @@ unsigned char ipseczeroes[IPSEC_ZEROES_SIZE]; /* zeroes! */ u_int8_t get_sa_require(struct inpcb *inp) { - u_int8_t sareq = 0; + u_int8_t sareq = 0; - if (inp != NULL) { - sareq |= inp->inp_seclevel[SL_AUTH] >= IPSEC_LEVEL_USE ? - NOTIFY_SATYPE_AUTH : 0; - sareq |= inp->inp_seclevel[SL_ESP_TRANS] >= IPSEC_LEVEL_USE ? - NOTIFY_SATYPE_CONF : 0; - sareq |= inp->inp_seclevel[SL_ESP_NETWORK] >= IPSEC_LEVEL_USE ? - NOTIFY_SATYPE_TUNNEL : 0; - } else { - sareq |= ipsec_auth_default_level >= IPSEC_LEVEL_USE ? - NOTIFY_SATYPE_AUTH : 0; - sareq |= ipsec_esp_trans_default_level >= IPSEC_LEVEL_USE ? - NOTIFY_SATYPE_CONF : 0; - sareq |= ipsec_esp_network_default_level >= IPSEC_LEVEL_USE ? - NOTIFY_SATYPE_TUNNEL : 0; - } - - return (sareq); + if (inp != NULL) + { + sareq |= inp->inp_seclevel[SL_AUTH] >= IPSEC_LEVEL_USE ? + NOTIFY_SATYPE_AUTH : 0; + sareq |= inp->inp_seclevel[SL_ESP_TRANS] >= IPSEC_LEVEL_USE ? + NOTIFY_SATYPE_CONF : 0; + sareq |= inp->inp_seclevel[SL_ESP_NETWORK] >= IPSEC_LEVEL_USE ? + NOTIFY_SATYPE_TUNNEL : 0; + } + else + { + sareq |= ipsec_auth_default_level >= IPSEC_LEVEL_USE ? + NOTIFY_SATYPE_AUTH : 0; + sareq |= ipsec_esp_trans_default_level >= IPSEC_LEVEL_USE ? + NOTIFY_SATYPE_CONF : 0; + sareq |= ipsec_esp_network_default_level >= IPSEC_LEVEL_USE ? + NOTIFY_SATYPE_TUNNEL : 0; + } + + return (sareq); } /* @@ -156,167 +176,185 @@ get_sa_require(struct inpcb *inp) int check_ipsec_policy(struct inpcb *inp, u_int32_t daddr) { - struct socket *so; - struct route_enc re0, *re = &re0; - struct sockaddr_encap *dst; - struct tdb tmptdb; - u_int8_t sa_require, sa_have; - int error, i; - - if (inp == NULL || ((so=inp->inp_socket) == 0)) - return (EINVAL); - - /* If IPSEC is not required just use what we got */ - if (!(sa_require = inp->inp_secrequire)) - return 0; - - bzero((caddr_t) re, sizeof(*re)); - dst = (struct sockaddr_encap *) &re->re_dst; - dst->sen_family = AF_ENCAP; - dst->sen_len = SENT_IP4_LEN; - dst->sen_type = SENT_IP4; - dst->sen_ip_src = inp->inp_laddr; - dst->sen_ip_dst.s_addr = inp->inp_faddr.s_addr ? - inp->inp_faddr.s_addr : daddr; - dst->sen_proto = so->so_proto->pr_protocol; - switch (dst->sen_proto) { + union sockaddr_union sunion; + struct socket *so; + struct route_enc re0, *re = &re0; + struct sockaddr_encap *dst; + u_int8_t sa_require, sa_have; + int error, i; + + if (inp == NULL || ((so = inp->inp_socket) == 0)) + return (EINVAL); + + /* If IPSEC is not required just use what we got */ + if (!(sa_require = inp->inp_secrequire)) + return 0; + + bzero((caddr_t) re, sizeof(*re)); + dst = (struct sockaddr_encap *) &re->re_dst; + dst->sen_family = PF_KEY; + dst->sen_len = SENT_IP4_LEN; + dst->sen_type = SENT_IP4; + dst->sen_ip_src = inp->inp_laddr; + dst->sen_ip_dst.s_addr = inp->inp_faddr.s_addr ? + inp->inp_faddr.s_addr : daddr; + dst->sen_proto = so->so_proto->pr_protocol; + switch (dst->sen_proto) + { case IPPROTO_UDP: case IPPROTO_TCP: - dst->sen_sport = inp->inp_lport; - dst->sen_dport = inp->inp_fport; - break; + dst->sen_sport = inp->inp_lport; + dst->sen_dport = inp->inp_fport; + break; default: - dst->sen_sport = 0; - dst->sen_dport = 0; + dst->sen_sport = 0; + dst->sen_dport = 0; + } + + /* Try to find a flow */ + rtalloc((struct route *) re); + + if (re->re_rt != NULL) + { + struct tdb *tdb; + struct sockaddr_encap *gw; + + gw = (struct sockaddr_encap *) (re->re_rt->rt_gateway); + + if (gw->sen_type == SENT_IPSP) { + sunion.sin.sin_family = AF_INET; + sunion.sin.sin_len = sizeof(struct sockaddr_in); + sunion.sin.sin_addr = gw->sen_ipsp_dst; + + tdb = (struct tdb *) gettdb(gw->sen_ipsp_spi, &sunion, + gw->sen_ipsp_sproto); + + SPI_CHAIN_ATTRIB(sa_have, tdb_onext, tdb); } + else + sa_have = 0; + + RTFREE(re->re_rt); + + /* Check if our requirements are met */ + if (!(sa_require & ~sa_have)) + return 0; + } + else + sa_have = 0; - /* Try to find a flow */ - rtalloc((struct route *) re); + error = i = 0; - if (re->re_rt != NULL) { - struct tdb *tdb; - struct sockaddr_encap *gw; - - gw = (struct sockaddr_encap *) (re->re_rt->rt_gateway); - - if (gw->sen_type == SENT_IPSP) { - tdb = (struct tdb *) gettdb(gw->sen_ipsp_spi, - gw->sen_ipsp_dst, - gw->sen_ipsp_sproto); - - SPI_CHAIN_ATTRIB(sa_have, tdb_onext, tdb); - } else - sa_have = 0; - - RTFREE(re->re_rt); - - /* Check if our requirements are met */ - if (!(sa_require & ~sa_have)) - return 0; - } else - sa_have = 0; - - error = i = 0; - - inp->inp_secresult = SR_WAIT; - - /* If necessary try to notify keymanagement three times */ - while (i < 3) { - DPRINTF(("ipsec: send SA request (%d), remote ip: %0x, SA type: %d\n", i+1, dst->sen_ip_dst, sa_require)); - - /* Send notify */ - bzero((caddr_t) &tmptdb, sizeof(tmptdb)); - tmptdb.tdb_src = dst->sen_ip_src; - tmptdb.tdb_dst = dst->sen_ip_dst; - /* - * When we already have an insufficient SA, we need to - * establish a new SA which combines the required - * attributes and the already existant. This can go - * once we can do socket specific keying. - */ - tmptdb.tdb_satype = sa_require | sa_have; - encap_sendnotify(NOTIFY_REQUEST_SA, &tmptdb, inp); + inp->inp_secresult = SR_WAIT; + + /* If necessary try to notify keymanagement three times */ + while (i < 3) + { + /* XXX address */ + DPRINTF(("ipsec: send SA request (%d), remote ip: %s, SA type: %d\n", + i + 1, inet_ntoa4(dst->sen_ip_dst), sa_require)); + + /* Send notify */ + /* XXX PF_KEYv2 Notify */ - /* - * Wait for the keymanagement daemon to establich a new SA, - * even on error check again, perhaps some other process - * already established the necessary SA. - */ - error = tsleep((caddr_t)inp, PSOCK|PCATCH, "ipsecnotify", 30*hz); - - DPRINTF(("check_ipsec: sleep %d\n", error)); - - if (error && error != EWOULDBLOCK) - break; - /* - * A Key Management daemon returned an apropriate SA back - * to the kernel, the kernel noted that state in the waiting - * socket. - */ - if (inp->inp_secresult == SR_SUCCESS) - return (0); - /* - * Key Management returned a permanent failure, we do not - * need to retry again. XXX - when more than one key - * management daemon is available we can not do that. - */ - if (inp->inp_secresult == SR_FAILED) - break; - i++; - } + /* + * Wait for the keymanagement daemon to establich a new SA, + * even on error check again, perhaps some other process + * already established the necessary SA. + */ + error = tsleep((caddr_t)inp, PSOCK|PCATCH, "ipsecnotify", 30*hz); + DPRINTF(("check_ipsec: sleep %d\n", error)); + + if (error && error != EWOULDBLOCK) + break; + /* + * A Key Management daemon returned an apropriate SA back + * to the kernel, the kernel noted that state in the waiting + * socket. + */ + if (inp->inp_secresult == SR_SUCCESS) + return (0); + /* + * Key Management returned a permanent failure, we do not + * need to retry again. XXX - when more than one key + * management daemon is available we can not do that. + */ + if (inp->inp_secresult == SR_FAILED) + break; + i++; + } - return (error ? error : EWOULDBLOCK); + return (error ? error : EWOULDBLOCK); } /* * Reserve an SPI; the SA is not valid yet though. Zero is reserved as * an error return value. If tspi is not zero, we try to allocate that - * SPI. SPIs less than 255 are reserved, so we check for those too. + * SPI. */ u_int32_t -reserve_spi(u_int32_t tspi, struct in_addr src, u_int8_t proto, int *errval) +reserve_spi(u_int32_t sspi, u_int32_t tspi, union sockaddr_union *src, + union sockaddr_union *dst, u_int8_t sproto, int *errval) { struct tdb *tdbp; - u_int32_t spi = tspi; /* Don't change */ + u_int32_t spi; + int nums; + + if (tspi <= 255) /* We don't reserve 0 < SPI <= 255 */ + { + (*errval) = EEXIST; + return 0; + } - while (1) + if ((sspi == tspi) && (sspi != 0)) /* Asking for a specific SPI */ + nums = 1; + else + nums = 50; /* XXX figure out some good value */ + + while (nums--) { - while (ntohl(spi) <= 255) /* Get a new SPI */ - get_random_bytes((void *) &spi, sizeof(spi)); - - /* Check whether we're using this SPI already */ - if (gettdb(spi, src, proto) != (struct tdb *) NULL) + if (tspi != 0) /* SPIRANGE was defined */ { - if (tspi != 0) /* If one was proposed, report error */ + if (sspi == tspi) /* Specific SPI asked */ + spi = tspi; + else /* Range specified */ { - (*errval) = EEXIST; - return 0; + get_random_bytes((void *) &spi, sizeof(spi)); + spi = sspi + (spi % (tspi - sspi)); } - - spi = 0; - continue; } - - MALLOC(tdbp, struct tdb *, sizeof(*tdbp), M_TDB, M_WAITOK); - if (tdbp == NULL) - { - (*errval) = ENOBUFS; - return 0; - } + else /* Some SPI */ + get_random_bytes((void *) &spi, sizeof(spi)); + + if (spi <= 255) /* Don't allocate SPI <= 255, they're reserved */ + continue; + else + spi = htonl(spi); - bzero((caddr_t) tdbp, sizeof(*tdbp)); + /* Check whether we're using this SPI already */ + if (gettdb(spi, dst, sproto) != (struct tdb *) NULL) + continue; + + MALLOC(tdbp, struct tdb *, sizeof(struct tdb), M_TDB, M_WAITOK); + bzero((caddr_t) tdbp, sizeof(struct tdb)); tdbp->tdb_spi = spi; - tdbp->tdb_dst = src; - tdbp->tdb_sproto = proto; - tdbp->tdb_flags |= TDBF_INVALID; + bcopy(&dst->sa, &tdbp->tdb_dst.sa, SA_LEN(&dst->sa)); + bcopy(&src->sa, &tdbp->tdb_src.sa, SA_LEN(&src->sa)); + tdbp->tdb_sproto = sproto; + tdbp->tdb_flags |= TDBF_INVALID; /* Mark SA as invalid for now */ + tdbp->tdb_established = time.tv_sec; tdbp->tdb_epoch = kernfs_epoch - 1; - puttdb(tdbp); + + /* XXX Should set up a silent expiration for this */ return spi; } + + (*errval) = EEXIST; + return 0; } /* @@ -328,16 +366,22 @@ reserve_spi(u_int32_t tspi, struct in_addr src, u_int8_t proto, int *errval) */ struct tdb * -gettdb(u_int32_t spi, struct in_addr dst, u_int8_t proto) +gettdb(u_int32_t spi, union sockaddr_union *dst, u_int8_t proto) { - int hashval; + u_int8_t *ptr = (u_int8_t *) dst; + u_int32_t hashval = proto + spi; struct tdb *tdbp; - - hashval = (spi + dst.s_addr + proto) % TDB_HASHMOD; - + int i; + + for (i = 0; i < SA_LEN(&dst->sa); i++) + hashval += ptr[i]; + + hashval %= TDB_HASHMOD; + for (tdbp = tdbh[hashval]; tdbp; tdbp = tdbp->tdb_hnext) - if ((tdbp->tdb_spi == spi) && (tdbp->tdb_dst.s_addr == dst.s_addr) - && (tdbp->tdb_sproto == proto)) + if ((tdbp->tdb_spi == spi) && + !bcmp(&tdbp->tdb_dst, dst, SA_LEN(&dst->sa)) && + (tdbp->tdb_sproto == proto)) break; return tdbp; @@ -349,9 +393,6 @@ get_flow(void) struct flow *flow; MALLOC(flow, struct flow *, sizeof(struct flow), M_TDB, M_WAITOK); - if (flow == (struct flow *) NULL) - return (struct flow *) NULL; - bzero(flow, sizeof(struct flow)); return flow; @@ -364,8 +405,6 @@ get_expiration(void) MALLOC(exp, struct expiration *, sizeof(struct expiration), M_TDB, M_WAITOK); - if (exp == (struct expiration *) NULL) - return (struct expiration *) NULL; bzero(exp, sizeof(struct expiration)); @@ -373,12 +412,12 @@ get_expiration(void) } void -cleanup_expirations(struct in_addr dst, u_int32_t spi, u_int8_t sproto) +cleanup_expirations(union sockaddr_union *dst, u_int32_t spi, u_int8_t sproto) { struct expiration *exp, *nexp; - - for (exp = explist; exp; exp = exp ? exp->exp_next : explist) - if ((exp->exp_dst.s_addr == dst.s_addr) && + + for (exp = explist; exp; exp = (exp ? exp->exp_next : explist)) + if (!bcmp(&exp->exp_dst, dst, SA_LEN(&dst->sa)) && (exp->exp_spi == spi) && (exp->exp_sproto == sproto)) { /* Link previous to next */ @@ -390,10 +429,10 @@ cleanup_expirations(struct in_addr dst, u_int32_t spi, u_int8_t sproto) /* Link next (if it exists) to previous */ if (exp->exp_next != (struct expiration *) NULL) exp->exp_next->exp_prev = exp->exp_prev; - + nexp = exp; exp = exp->exp_prev; - free(nexp, M_TDB); + FREE(nexp, M_TDB); } } @@ -421,48 +460,51 @@ handle_expirations(void *arg) if (explist) explist->exp_prev = NULL; - tdb = gettdb(exp->exp_spi, exp->exp_dst, exp->exp_sproto); + tdb = gettdb(exp->exp_spi, &exp->exp_dst, exp->exp_sproto); if (tdb == (struct tdb *) NULL) { free(exp, M_TDB); continue; /* TDB is gone, ignore this */ } - /* Soft expirations */ - if (tdb->tdb_flags & TDBF_SOFT_TIMER) + /* Hard expirations first */ + if ((tdb->tdb_flags & TDBF_TIMER) && + (tdb->tdb_exp_timeout <= time.tv_sec)) { - if (tdb->tdb_soft_timeout <= time.tv_sec) +/* XXX + encap_sendnotify(NOTIFY_HARD_EXPIRE, tdb, NULL); +*/ + tdb_delete(tdb, 0); + } + else + if ((tdb->tdb_flags & TDBF_FIRSTUSE) && + (tdb->tdb_first_use + tdb->tdb_exp_first_use <= time.tv_sec)) { - encap_sendnotify(NOTIFY_SOFT_EXPIRE, tdb, NULL); - tdb->tdb_flags &= ~TDBF_SOFT_TIMER; +/* XXX + encap_sendnotify(NOTIFY_HARD_EXPIRE, tdb, NULL); +*/ + tdb_delete(tdb, 0); } - else - if (tdb->tdb_flags & TDBF_SOFT_FIRSTUSE) - if (tdb->tdb_first_use + tdb->tdb_soft_first_use <= - time.tv_sec) - { - encap_sendnotify(NOTIFY_SOFT_EXPIRE, tdb, NULL); - tdb->tdb_flags &= ~TDBF_SOFT_FIRSTUSE; - } - } - /* Hard expirations */ - if (tdb->tdb_flags & TDBF_TIMER) + /* Soft expirations */ + if ((tdb->tdb_flags & TDBF_SOFT_TIMER) && + (tdb->tdb_soft_timeout <= time.tv_sec)) { - if (tdb->tdb_exp_timeout <= time.tv_sec) +/* XXX + encap_sendnotify(NOTIFY_SOFT_EXPIRE, tdb, NULL); +*/ + tdb->tdb_flags &= ~TDBF_SOFT_TIMER; + } + else + if ((tdb->tdb_flags & TDBF_SOFT_FIRSTUSE) && + (tdb->tdb_first_use + tdb->tdb_soft_first_use <= + time.tv_sec)) { - encap_sendnotify(NOTIFY_HARD_EXPIRE, tdb, NULL); - tdb_delete(tdb, 0); +/* XXX + encap_sendnotify(NOTIFY_SOFT_EXPIRE, tdb, NULL); +*/ + tdb->tdb_flags &= ~TDBF_SOFT_FIRSTUSE; } - else - if (tdb->tdb_flags & TDBF_FIRSTUSE) - if (tdb->tdb_first_use + tdb->tdb_exp_first_use <= - time.tv_sec) - { - encap_sendnotify(NOTIFY_HARD_EXPIRE, tdb, NULL); - tdb_delete(tdb, 0); - } - } free(exp, M_TDB); } @@ -535,28 +577,27 @@ put_expiration(struct expiration *exp) } struct flow * -find_flow(struct in_addr src, struct in_addr srcmask, struct in_addr dst, - struct in_addr dstmask, u_int8_t proto, u_int16_t sport, - u_int16_t dport, struct tdb *tdb) +find_flow(union sockaddr_union *src, union sockaddr_union *srcmask, + union sockaddr_union * dst, union sockaddr_union *dstmask, + u_int8_t proto, struct tdb *tdb) { struct flow *flow; for (flow = tdb->tdb_flow; flow; flow = flow->flow_next) - if ((src.s_addr == flow->flow_src.s_addr) && - (dst.s_addr == flow->flow_dst.s_addr) && - (srcmask.s_addr == flow->flow_srcmask.s_addr) && - (dstmask.s_addr == flow->flow_dstmask.s_addr) && - (proto == flow->flow_proto) && - (sport == flow->flow_sport) && (dport == flow->flow_dport)) + if (!bcmp(&src->sa, &flow->flow_src.sa, SA_LEN(&src->sa)) && + !bcmp(&dst->sa, &flow->flow_dst.sa, SA_LEN(&dst->sa)) && + !bcmp(&srcmask->sa, &flow->flow_srcmask.sa, SA_LEN(&srcmask->sa)) && + !bcmp(&dstmask->sa, &flow->flow_dstmask.sa, SA_LEN(&dstmask->sa)) && + (proto == flow->flow_proto)) return flow; return (struct flow *) NULL; } struct flow * -find_global_flow(struct in_addr src, struct in_addr srcmask, - struct in_addr dst, struct in_addr dstmask, - u_int8_t proto, u_int16_t sport, u_int16_t dport) +find_global_flow(union sockaddr_union *src, union sockaddr_union *srcmask, + union sockaddr_union *dst, union sockaddr_union *dstmask, + u_int8_t proto) { struct flow *flow; struct tdb *tdb; @@ -564,8 +605,8 @@ find_global_flow(struct in_addr src, struct in_addr srcmask, for (i = 0; i < TDB_HASHMOD; i++) for (tdb = tdbh[i]; tdb; tdb = tdb->tdb_hnext) - if ((flow = find_flow(src, srcmask, dst, dstmask, proto, sport, - dport, tdb)) != (struct flow *) NULL) + if ((flow = find_flow(src, srcmask, dst, dstmask, proto, tdb)) != + (struct flow *) NULL) return flow; return (struct flow *) NULL; @@ -574,10 +615,13 @@ find_global_flow(struct in_addr src, struct in_addr srcmask, void puttdb(struct tdb *tdbp) { - int hashval; + u_int8_t *ptr = (u_int8_t *) &tdbp->tdb_dst; + u_int32_t hashval = tdbp->tdb_sproto + tdbp->tdb_spi, i; - hashval = ((tdbp->tdb_sproto + tdbp->tdb_spi + tdbp->tdb_dst.s_addr) - % TDB_HASHMOD); + for (i = 0; i < SA_LEN(&tdbp->tdb_dst.sa); i++) + hashval += ptr[i]; + + hashval %= TDB_HASHMOD; tdbp->tdb_hnext = tdbh[hashval]; tdbh[hashval] = tdbp; } @@ -599,17 +643,20 @@ put_flow(struct flow *flow, struct tdb *tdb) void delete_flow(struct flow *flow, struct tdb *tdb) { - if (tdb->tdb_flow == flow) + if (tdb) { - tdb->tdb_flow = flow->flow_next; - if (tdb->tdb_flow) - tdb->tdb_flow->flow_prev = (struct flow *) NULL; - } - else - { - flow->flow_prev->flow_next = flow->flow_next; - if (flow->flow_next) - flow->flow_next->flow_prev = flow->flow_prev; + if (tdb->tdb_flow == flow) + { + tdb->tdb_flow = flow->flow_next; + if (tdb->tdb_flow) + tdb->tdb_flow->flow_prev = (struct flow *) NULL; + } + else + { + flow->flow_prev->flow_next = flow->flow_next; + if (flow->flow_next) + flow->flow_next->flow_prev = flow->flow_prev; + } } FREE(flow, M_TDB); @@ -618,12 +665,15 @@ delete_flow(struct flow *flow, struct tdb *tdb) int tdb_delete(struct tdb *tdbp, int delchain) { + u_int8_t *ptr = (u_int8_t *) &tdbp->tdb_dst; struct tdb *tdbpp; struct flow *flow; - int hashval; + u_int32_t hashval = tdbp->tdb_sproto + tdbp->tdb_spi, i; - hashval = ((tdbp->tdb_sproto + tdbp->tdb_spi + tdbp->tdb_dst.s_addr) - % TDB_HASHMOD); + for (i = 0; i < SA_LEN(&tdbp->tdb_dst.sa); i++) + hashval += ptr[i]; + + hashval %= TDB_HASHMOD; if (tdbh[hashval] == tdbp) { @@ -638,27 +688,41 @@ tdb_delete(struct tdb *tdbp, int delchain) tdbpp = tdbp; } - if (tdbp != tdbpp) - return EINVAL; /* Should never happen */ - - /* If there was something before us in the chain, make it point nowhere */ - if (tdbp->tdb_inext) + /* + * If there was something before us in the chain pointing to us, + * make it point nowhere + */ + if ((tdbp->tdb_inext) && + (tdbp->tdb_inext->tdb_onext == tdbp)) tdbp->tdb_inext->tdb_onext = NULL; - /* If there was something after us in the chain, make it point nowhere */ - if (tdbp->tdb_onext) + /* + * If there was something after us in the chain pointing to us, + * make it point nowhere + */ + if ((tdbp->tdb_onext) && + (tdbp->tdb_onext->tdb_inext == tdbp)) tdbp->tdb_onext->tdb_inext = NULL; - + tdbpp = tdbp->tdb_onext; - + if (tdbp->tdb_xform) (*(tdbp->tdb_xform->xf_zeroize))(tdbp); for (flow = tdbp->tdb_flow; flow; flow = tdbp->tdb_flow) - delete_flow(flow, tdbp); + { + delete_flow(flow, tdbp); + ipsec_in_use--; + } + + cleanup_expirations(&tdbp->tdb_dst, tdbp->tdb_spi, tdbp->tdb_sproto); + + if (tdbp->tdb_srcid) + FREE(tdbp->tdb_srcid, M_XDATA); + + if (tdbp->tdb_dstid) + FREE(tdbp->tdb_dstid, M_XDATA); - cleanup_expirations(tdbp->tdb_dst, tdbp->tdb_spi, tdbp->tdb_sproto); - FREE(tdbp, M_TDB); if (delchain && tdbpp) @@ -668,26 +732,21 @@ tdb_delete(struct tdb *tdbp, int delchain) } int -tdb_init(struct tdb *tdbp, struct mbuf *m) +tdb_init(struct tdb *tdbp, u_int16_t alg, struct ipsecinit *ii) { - int alg; - struct encap_msghdr *em; struct xformsw *xsp; - - em = mtod(m, struct encap_msghdr *); - alg = em->em_alg; /* Record establishment time */ tdbp->tdb_established = time.tv_sec; - tdbp->tdb_epoch = kernfs_epoch - 1; for (xsp = xformsw; xsp < xformswNXFORMSW; xsp++) if (xsp->xf_type == alg) - return (*(xsp->xf_init))(tdbp, xsp, m); + return (*(xsp->xf_init))(tdbp, xsp, ii); - DPRINTF(("tdb_init(): no alg %d for spi %08x, addr %x, proto %d\n", - alg, ntohl(tdbp->tdb_spi), tdbp->tdb_dst.s_addr, tdbp->tdb_sproto)); + DPRINTF(("tdb_init(): no alg %d for spi %08x, addr %s, proto %d\n", + alg, ntohl(tdbp->tdb_spi), ipsp_address(tdbp->tdb_dst), + tdbp->tdb_sproto)); return EINVAL; } @@ -700,7 +759,6 @@ ipsp_kern(int off, char **bufp, int len) { static char buffer[IPSEC_KERNFS_BUFSIZE]; struct tdb *tdb; - struct flow *fl; int l, i; if (off == 0) @@ -720,59 +778,119 @@ ipsp_kern(int off, char **bufp, int len) tdb->tdb_epoch = kernfs_epoch; l = sprintf(buffer, "SPI = %08x, Destination = %s, Sproto = %u\n", - ntohl(tdb->tdb_spi), inet_ntoa(tdb->tdb_dst), - tdb->tdb_sproto); - - l += sprintf(buffer + l, "\testablished %d seconds ago\n", + ntohl(tdb->tdb_spi), + ipsp_address(tdb->tdb_dst), tdb->tdb_sproto); + + l += sprintf(buffer + l, "\tEstablished %d seconds ago\n", time.tv_sec - tdb->tdb_established); - - l += sprintf(buffer + l, "\tsrc = %s, flags = %08x, SAtype = %u\n", - inet_ntoa(tdb->tdb_src), tdb->tdb_flags, - tdb->tdb_satype); + + l += sprintf(buffer + l, "\tSource = %s", + ipsp_address(tdb->tdb_src)); + + if (tdb->tdb_proxy.sa.sa_family) + l += sprintf(buffer + l, ", Proxy = %s\n", + ipsp_address(tdb->tdb_proxy)); + else + l += sprintf(buffer + l, "\n"); + + l += sprintf(buffer + l, "\tFlags (%08x) = <", tdb->tdb_flags); + + if ((tdb->tdb_flags & ~(TDBF_TIMER | TDBF_BYTES | + TDBF_ALLOCATIONS | TDBF_FIRSTUSE | + TDBF_SOFT_TIMER | TDBF_SOFT_BYTES | + TDBF_SOFT_FIRSTUSE | + TDBF_SOFT_ALLOCATIONS)) == 0) + l += sprintf(buffer + l, "none>\n"); + else + { + /* We can reuse variable 'i' here, since we're not looping */ + i = 0; + + if (tdb->tdb_flags & TDBF_UNIQUE) + { + if (i) + l += sprintf(buffer + l, ", "); + else + i = 1; + + l += sprintf(buffer + l, "unique"); + i = 1; + } + + if (tdb->tdb_flags & TDBF_INVALID) + { + if (i) + l += sprintf(buffer + l, ", "); + else + i = 1; + + l += sprintf(buffer + l, "invalid"); + } + + if (tdb->tdb_flags & TDBF_HALFIV) + { + if (i) + l += sprintf(buffer + l, ", "); + else + i = 1; + + l += sprintf(buffer + l, "halviv"); + } + + if (tdb->tdb_flags & TDBF_PFS) + { + if (i) + l += sprintf(buffer + l, ", "); + else + i = 1; + + l += sprintf(buffer + l, "pfs"); + } + + if (tdb->tdb_flags & TDBF_TUNNELING) + { + if (i) + l += sprintf(buffer + l, ", "); + else + i = 1; + + l += sprintf(buffer + l, "tunneling"); + } + + l += sprintf(buffer + l, ">\n"); + } if (tdb->tdb_xform) l += sprintf(buffer + l, "\txform = <%s>\n", tdb->tdb_xform->xf_name); - else - l += sprintf(buffer + l, "\txform = <(null)>\n"); - if (tdb->tdb_confname) - l += sprintf(buffer + l, "\t\tencryption = <%s>\n", - tdb->tdb_confname); - if (tdb->tdb_authname) - l += sprintf(buffer + l, "\t\tauthentication = <%s>\n", - tdb->tdb_authname); + if (tdb->tdb_encalgxform) + l += sprintf(buffer + l, "\t\tEncryption = <%s>\n", + tdb->tdb_encalgxform->name); - l += sprintf(buffer + l, "\tOSrc = %s", inet_ntoa(tdb->tdb_osrc)); - - l += sprintf(buffer + l, " ODst = %s, TTL = %u\n", - inet_ntoa(tdb->tdb_odst), tdb->tdb_ttl); + if (tdb->tdb_authalgxform) + l += sprintf(buffer + l, "\t\tAuthentication = <%s>\n", + tdb->tdb_authalgxform->name); if (tdb->tdb_onext) l += sprintf(buffer + l, - "\tNext (on output) SA: SPI = %08x, " + "\tNext SA: SPI = %08x, " "Destination = %s, Sproto = %u\n", ntohl(tdb->tdb_onext->tdb_spi), - inet_ntoa(tdb->tdb_onext->tdb_dst), + ipsp_address(tdb->tdb_onext->tdb_dst), tdb->tdb_onext->tdb_sproto); if (tdb->tdb_inext) l += sprintf(buffer + l, - "\tNext (on input) SA: SPI = %08x, " + "\tPrevious SA: SPI = %08x, " "Destination = %s, Sproto = %u\n", ntohl(tdb->tdb_inext->tdb_spi), - inet_ntoa(tdb->tdb_inext->tdb_dst), + ipsp_address(tdb->tdb_inext->tdb_dst), tdb->tdb_inext->tdb_sproto); - /* XXX We can reuse variable i, we're not going to loop again */ - for (i = 0, fl = tdb->tdb_flow; fl; fl = fl->flow_next) - i++; + if (tdb->tdb_flow) + l+= sprintf(buffer + l, "\tUsed by at least one flow\n"); - l += sprintf(buffer + l, - "\t%u flows counted " - "(use netstat -r for more information)\n", - i); - l += sprintf(buffer + l, "\tExpirations:\n"); if (tdb->tdb_flags & TDBF_TIMER) @@ -793,29 +911,34 @@ ipsp_kern(int off, char **bufp, int len) l += sprintf(buffer + l, "\t\tSoft expiration after %qu bytes\n", tdb->tdb_soft_bytes); + if ((tdb->tdb_flags & TDBF_BYTES) || + (tdb->tdb_flags & TDBF_SOFT_BYTES)) l += sprintf(buffer + l, "\t\tCurrently %qu bytes processed\n", tdb->tdb_cur_bytes); - if (tdb->tdb_flags & TDBF_PACKETS) + if (tdb->tdb_flags & TDBF_ALLOCATIONS) l += sprintf(buffer + l, - "\t\tHard expiration after %qu packets\n", - tdb->tdb_exp_packets); + "\t\tHard expiration after %u flows\n", + tdb->tdb_exp_allocations); - if (tdb->tdb_flags & TDBF_SOFT_PACKETS) + if (tdb->tdb_flags & TDBF_SOFT_ALLOCATIONS) l += sprintf(buffer + l, - "\t\tSoft expiration after %qu packets\n", - tdb->tdb_soft_packets); + "\t\tSoft expiration after %u flows\n", + tdb->tdb_soft_allocations); - l += sprintf(buffer + l, "\t\tCurrently %qu packets processed\n", - tdb->tdb_cur_packets); + if ((tdb->tdb_flags & TDBF_ALLOCATIONS) || + (tdb->tdb_flags & TDBF_SOFT_ALLOCATIONS)) + l += sprintf(buffer + l, "\t\tCurrently %u flows processed\n", + tdb->tdb_cur_allocations); - if (tdb->tdb_flags & TDBF_FIRSTUSE) { - if (tdb->tdb_first_use) + if (tdb->tdb_flags & TDBF_FIRSTUSE) + { + if (tdb->tdb_first_use) l += sprintf(buffer + l, "\t\tHard expiration(2) in %qu seconds\n", (tdb->tdb_first_use + tdb->tdb_exp_first_use) - time.tv_sec); - else + else l += sprintf(buffer + l, "\t\tHard expiration in %qu seconds after first " "use\n", tdb->tdb_exp_first_use); @@ -834,7 +957,7 @@ ipsp_kern(int off, char **bufp, int len) } if (!(tdb->tdb_flags & (TDBF_TIMER | TDBF_SOFT_TIMER | TDBF_BYTES | - TDBF_SOFT_PACKETS | TDBF_PACKETS | + TDBF_SOFT_ALLOCATIONS | TDBF_ALLOCATIONS | TDBF_SOFT_BYTES | TDBF_FIRSTUSE | TDBF_SOFT_FIRSTUSE))) l += sprintf(buffer + l, "\t\t(none)\n"); @@ -846,3 +969,33 @@ ipsp_kern(int off, char **bufp, int len) return 0; } + +char * +inet_ntoa4(struct in_addr ina) +{ + static char buf[4][4 * sizeof "123"]; + unsigned char *ucp = (unsigned char *) &ina; + static int i = 1; + + i = (i + 1) % 2; + sprintf(buf[i], "%d.%d.%d.%d", ucp[0] & 0xff, ucp[1] & 0xff, + ucp[2] & 0xff, ucp[3] & 0xff); + return (buf[i]); +} + +char * +ipsp_address(union sockaddr_union sa) +{ + switch (sa.sa.sa_family) + { + case AF_INET: + return inet_ntoa4(sa.sin.sin_addr); + +#if INET6 + /* XXX Add AF_INET6 support here */ +#endif /* INET6 */ + + default: + return "(unknown address family)"; + } +} diff --git a/sys/netinet/ip_ipsp.h b/sys/netinet/ip_ipsp.h index 34f306f4a92..ab34c6c6796 100644 --- a/sys/netinet/ip_ipsp.h +++ b/sys/netinet/ip_ipsp.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_ipsp.h,v 1.23 1999/02/17 20:39:17 deraadt Exp $ */ +/* $OpenBSD: ip_ipsp.h,v 1.24 1999/02/24 22:33:06 angelos Exp $ */ /* * The authors of this code are John Ioannidis (ji@tla.org), @@ -37,119 +37,291 @@ * IPSP global definitions. */ -struct expiration { - u_int32_t exp_timeout; - struct in_addr exp_dst; - u_int32_t exp_spi; - u_int8_t exp_sproto; - struct expiration *exp_next; - struct expiration *exp_prev; +#include <sys/md5k.h> +#include <netinet/ip_sha1.h> +#include <netinet/ip_rmd160.h> +#include <netinet/ip_blf.h> +#include <netinet/ip_cast.h> +#include <sys/socket.h> + +/* HMAC key sizes */ +#define MD5HMAC96_KEYSIZE 16 +#define SHA1HMAC96_KEYSIZE 20 +#define RIPEMD160HMAC96_KEYSIZE 20 + +/* IV lengths */ +#define ESP_DES_IVS 8 +#define ESP_3DES_IVS 8 +#define ESP_BLF_IVS 8 +#define ESP_CAST_IVS 8 +#define ESP_MAX_IVS 8 /* Keep updated */ + +/* Block sizes -- it is assumed that they're powers of 2 */ +#define ESP_DES_BLKS 8 +#define ESP_3DES_BLKS 8 +#define ESP_BLF_BLKS 8 +#define ESP_CAST_BLKS 8 +#define ESP_MAX_BLKS 8 /* Keep updated */ + +#define HMAC_BLOCK_LEN 64 + +#define AH_HMAC_HASHLEN 12 /* 96 bits of authenticator */ +#define AH_HMAC_RPLENGTH 4 /* 32 bits of replay counter */ +#define AH_HMAC_INITIAL_RPL 1 /* Replay counter initial value */ + +/* HMAC definitions */ +#define HMAC_IPAD_VAL 0x36 +#define HMAC_OPAD_VAL 0x5C +#define HMAC_BLOCK_LEN 64 + +/* Authenticator lengths */ +#define AH_MD5_ALEN 16 +#define AH_SHA1_ALEN 20 +#define AH_RMD160_ALEN 20 +#define AH_ALEN_MAX 20 /* Keep updated */ + +struct sockaddr_encap +{ + u_int8_t sen_len; /* length */ + u_int8_t sen_family; /* PF_KEY */ + u_int16_t sen_type; /* see SENT_* */ + union + { + u_int8_t Data[16]; /* other stuff mapped here */ + + struct /* SENT_IP4 */ + { + struct in_addr Src; + struct in_addr Dst; + u_int16_t Sport; + u_int16_t Dport; + u_int8_t Proto; + u_int8_t Filler[3]; + } Sip4; + + struct /* SENT_IPSP */ + { + struct in_addr Dst; + u_int32_t Spi; + u_int8_t Sproto; + u_int8_t Filler[7]; + } Sipsp; + } Sen; }; -struct flow { - struct flow *flow_next; /* Next in flow chain */ - struct flow *flow_prev; /* Previous in flow chain */ - struct tdb *flow_sa; /* Pointer to the SA */ - struct in_addr flow_src; /* Source address */ - struct in_addr flow_srcmask; /* Source netmask */ - struct in_addr flow_dst; /* Destination address */ - struct in_addr flow_dstmask; /* Destination netmask */ - u_int16_t flow_sport; /* Source port, if applicable */ - u_int16_t flow_dport; /* Destination port, if applicable */ - u_int8_t flow_proto; /* Transport protocol, if applicable */ - u_int8_t foo[3]; /* Alignment */ -}; +#define sen_data Sen.Data +#define sen_ip_src Sen.Sip4.Src +#define sen_ip_dst Sen.Sip4.Dst +#define sen_proto Sen.Sip4.Proto +#define sen_sport Sen.Sip4.Sport +#define sen_dport Sen.Sip4.Dport +#define sen_ipsp_dst Sen.Sipsp.Dst +#define sen_ipsp_spi Sen.Sipsp.Spi +#define sen_ipsp_sproto Sen.Sipsp.Sproto -struct tdb { /* tunnel descriptor block */ - struct tdb *tdb_hnext; /* next in hash chain */ - struct tdb *tdb_onext; /* next in output */ - struct tdb *tdb_inext; /* next in input (prev!) */ - struct xformsw *tdb_xform; /* transformation to use */ - u_int32_t tdb_spi; /* SPI to use */ - u_int32_t tdb_flags; /* Flags related to this TDB */ -#define TDBF_UNIQUE 0x00001 /* This should not be used by others */ -#define TDBF_TIMER 0x00002 /* Absolute expiration timer in use */ -#define TDBF_BYTES 0x00004 /* Check the byte counters */ -#define TDBF_PACKETS 0x00008 /* Check the packet counters */ -#define TDBF_INVALID 0x00010 /* This SPI is not valid yet/anymore */ -#define TDBF_FIRSTUSE 0x00020 /* Expire after first use */ -#define TDBF_TUNNELING 0x00040 /* Do IP-in-IP encapsulation */ -#define TDBF_SOFT_TIMER 0x00080 /* Soft expiration */ -#define TDBF_SOFT_BYTES 0x00100 /* Soft expiration */ -#define TDBF_SOFT_PACKETS 0x00200 /* Soft expiration */ -#define TDBF_SOFT_FIRSTUSE 0x00400 /* Soft expiration */ -#define TDBF_SAME_TTL 0x00800 /* Keep the packet TTL, in tunneling */ - u_int64_t tdb_exp_packets; /* Expire after so many packets s|r */ - u_int64_t tdb_soft_packets; /* Expiration warning */ - u_int64_t tdb_cur_packets; /* Current number of packets s|r'ed */ - u_int64_t tdb_exp_bytes; /* Expire after so many bytes passed */ - u_int64_t tdb_soft_bytes; /* Expiration warning */ - u_int64_t tdb_cur_bytes; /* Current count of bytes */ - u_int64_t tdb_exp_timeout; /* When does the SPI expire */ - u_int64_t tdb_soft_timeout; /* Send a soft-expire warning */ - u_int64_t tdb_established; /* When was the SPI established */ - u_int64_t tdb_first_use; /* When was it first used */ - u_int64_t tdb_soft_first_use; /* Soft warning */ - u_int64_t tdb_exp_first_use; /* Expire if tdb_first_use + - tdb_exp_first_use <= curtime */ - struct in_addr tdb_dst; /* dest address for this SPI */ - struct in_addr tdb_src; /* source address for this SPI, - * used when tunneling */ - struct in_addr tdb_osrc; - struct in_addr tdb_odst; /* Source and destination addresses - * of outer IP header if we're doing - * tunneling */ - caddr_t tdb_xdata; /* transformation data (opaque) */ - struct flow *tdb_flow; /* Which flows use this SA */ - - u_int8_t tdb_ttl; /* TTL used in tunneling */ - u_int8_t tdb_sproto; /* IPsec protocol */ - u_int16_t tdb_satype; /* Alignment */ - u_int32_t tdb_epoch; /* Used by the kernfs interface */ - u_int8_t *tdb_confname; /* Used by the kernfs interface */ - u_int8_t *tdb_authname; /* Used by the kernfs interface */ -}; +/* + * The "type" is really part of the address as far as the routing + * system is concerned. By using only one bit in the type field + * for each type, we sort-of make sure that different types of + * encapsulation addresses won't be matched against the wrong type. + * + */ -#define TDB_HASHMOD 257 +#define SENT_IP4 0x0001 /* data is two struct in_addr */ +#define SENT_IPSP 0x0002 /* data as in IP4 plus SPI */ -struct xformsw +/* + * SENT_HDRLEN is the length of the "header" + * SENT_*_LEN are the lengths of various forms of sen_data + * SENT_*_OFF are the offsets in the sen_data array of various fields + */ + +#define SENT_HDRLEN (2 * sizeof(u_int8_t) + sizeof(u_int16_t)) + +#define SENT_IP4_SRCOFF (0) +#define SENT_IP4_DSTOFF (sizeof (struct in_addr)) + +#define SENT_IP4_LEN 20 +#define SENT_IPSP_LEN 20 + +#define NOTIFY_SOFT_EXPIRE 0 /* Soft expiration of SA */ +#define NOTIFY_HARD_EXPIRE 1 /* Hard expiration of SA */ +#define NOTIFY_REQUEST_SA 2 /* Establish an SA */ + +#define NOTIFY_SATYPE_CONF 1 /* SA should do encryption */ +#define NOTIFY_SATYPE_AUTH 2 /* SA should do authentication */ +#define NOTIFY_SATYPE_TUNNEL 4 /* SA should use tunneling */ + +/* + * For encapsulation routes are possible not only for the destination + * address but also for the protocol, source and destination ports + * if available + */ + +struct route_enc { + struct rtentry *re_rt; + struct sockaddr_encap re_dst; +}; + +struct expiration { - u_short xf_type; /* Unique ID of xform */ - u_short xf_flags; /* flags (see below) */ - char *xf_name; /* human-readable name */ - int (*xf_attach) __P((void)); /* called at config time */ + u_int32_t exp_timeout; + union sockaddr_union exp_dst; + u_int32_t exp_spi; + u_int8_t exp_sproto; + struct expiration *exp_next; + struct expiration *exp_prev; +}; - /* xform initialization */ - int (*xf_init) __P((struct tdb *, struct xformsw *, struct mbuf *)); +struct flow +{ + struct flow *flow_next; /* Next in flow chain */ + struct flow *flow_prev; /* Previous in flow chain */ + struct tdb *flow_sa; /* Pointer to the SA */ + union sockaddr_union flow_src; /* Source address */ + union sockaddr_union flow_srcmask; /* Source netmask */ + union sockaddr_union flow_dst; /* Destination address */ + union sockaddr_union flow_dstmask; /* Destination netmask */ + u_int8_t flow_proto; /* Transport protocol, if applicable */ + u_int8_t foo[3]; /* Alignment */ +}; - int (*xf_zeroize) __P((struct tdb *)); /* termination */ +struct tdb /* tunnel descriptor block */ +{ + struct tdb *tdb_hnext; /* Next in hash chain */ + struct tdb *tdb_onext; /* Next in output */ + struct tdb *tdb_inext; /* Previous in output */ + + struct xformsw *tdb_xform; /* Transformation to use */ + struct enc_xform *tdb_encalgxform; /* Encryption algorithm xform */ + struct auth_hash *tdb_authalgxform; /* Authentication algorithm xform */ + +#define TDBF_UNIQUE 0x00001 /* This should not be used by others */ +#define TDBF_TIMER 0x00002 /* Absolute expiration timer in use */ +#define TDBF_BYTES 0x00004 /* Check the byte counters */ +#define TDBF_ALLOCATIONS 0x00008 /* Check the flows counters */ +#define TDBF_INVALID 0x00010 /* This SPI is not valid yet/anymore */ +#define TDBF_FIRSTUSE 0x00020 /* Expire after first use */ +#define TDBF_HALFIV 0x00040 /* Use half-length IV (ESP old only) */ +#define TDBF_SOFT_TIMER 0x00080 /* Soft expiration */ +#define TDBF_SOFT_BYTES 0x00100 /* Soft expiration */ +#define TDBF_SOFT_ALLOCATIONS 0x00200 /* Soft expiration */ +#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 */ + u_int32_t tdb_flags; /* Flags related to this TDB */ + + u_int32_t tdb_exp_allocations; /* Expire after so many flows */ + u_int32_t tdb_soft_allocations; /* Expiration warning */ + u_int32_t tdb_cur_allocations; /* Total number of allocations */ + + u_int64_t tdb_exp_bytes; /* Expire after so many bytes passed */ + u_int64_t tdb_soft_bytes; /* Expiration warning */ + u_int64_t tdb_cur_bytes; /* Current count of bytes */ + + u_int64_t tdb_exp_timeout; /* When does the SPI expire */ + u_int64_t tdb_soft_timeout; /* Send a soft-expire warning */ + u_int64_t tdb_established; /* When was the SPI established */ + + u_int64_t tdb_first_use; /* When was it first used */ + u_int64_t tdb_soft_first_use; /* Soft warning */ + u_int64_t tdb_exp_first_use; /* Expire if tdb_first_use + + * tdb_exp_first_use <= curtime */ + u_int32_t tdb_spi; /* SPI */ + u_int16_t tdb_amxkeylen; /* AH-old only */ + u_int16_t tdb_ivlen; /* IV length */ + u_int8_t tdb_sproto; /* IPsec protocol */ + u_int8_t tdb_wnd; /* Replay window */ + u_int16_t tdb_FILLER; /* Padding */ + + union sockaddr_union tdb_dst; /* Destination address for this SA */ + union sockaddr_union tdb_src; /* Source address for this SA */ + union sockaddr_union tdb_proxy; + + u_int8_t *tdb_key; /* Key material (schedules) */ + u_int8_t *tdb_ictx; /* Authentication contexts */ + 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 */ + + union + { + u_int8_t Iv[ESP_3DES_IVS]; /* That's enough space */ + u_int32_t Ivl; /* Make sure this is 4 bytes */ + u_int64_t Ivq; /* Make sure this is 8 bytes! */ + }IV; +#define tdb_iv IV.Iv +#define tdb_ivl IV.Ivl +#define tdb_ivq IV.Ivq + + u_int32_t tdb_rpl; /* Replay counter */ + u_int32_t tdb_bitmap; /* Used for replay sliding window */ + u_int32_t tdb_initial; /* Initial replay value */ + + u_int32_t tdb_epoch; /* Used by the kernfs interface */ + u_int16_t tdb_srcid_len; + u_int16_t tdb_dstid_len; + u_int16_t tdb_srcid_type; + u_int16_t tdb_dstid_type; + + struct flow *tdb_flow; /* Which flows use this SA */ +}; - /* called when packet received */ - struct mbuf *(*xf_input) __P((struct mbuf *, struct tdb *)); +#define TDB_HASHMOD 257 - /* called when packet sent */ - int (*xf_output) __P((struct mbuf *, struct sockaddr_encap *, - struct tdb *, struct mbuf **)); +struct auth_hash { + int type; + char *name; + u_int16_t keysize; + u_int16_t hashsize; + u_int16_t ctxsize; + void (*Init)(void *); + void (*Update)(void *, u_int8_t *, u_int16_t); + void (*Final)(u_int8_t *, void *); }; -#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 */ +struct enc_xform { + int type; + char *name; + u_int16_t blocksize, ivsize; + u_int16_t minkey, maxkey; + u_int32_t ivmask; /* Or all possible modes, zero iv = 1 */ + void (*encrypt)(struct tdb *, u_int8_t *); + void (*decrypt)(struct tdb *, u_int8_t *); +}; -/* Supported key hash algorithms */ -#define ALG_AUTH_MD5 1 -#define ALG_AUTH_SHA1 2 -#define ALG_AUTH_RMD160 3 +struct ipsecinit +{ + u_int8_t *ii_enckey; + u_int8_t *ii_authkey; + u_int16_t ii_enckeylen; + u_int16_t ii_authkeylen; + u_int8_t ii_encalg; + u_int8_t ii_authalg; +}; + +struct xformsw +{ + u_short xf_type; /* Unique ID of xform */ + u_short xf_flags; /* flags (see below) */ + char *xf_name; /* human-readable name */ + int (*xf_attach)(void); /* called at config time */ + int (*xf_init)(struct tdb *, struct xformsw *, struct ipsecinit *); + int (*xf_zeroize)(struct tdb *); /* termination */ + struct mbuf *(*xf_input)(struct mbuf *, struct tdb *); /* input */ + int (*xf_output)(struct mbuf *, struct sockaddr_encap *, + struct tdb *, struct mbuf **); /* output */ +}; -/* Supported encryption algorithms */ -#define ALG_ENC_DES 1 -#define ALG_ENC_3DES 2 -#define ALG_ENC_BLF 3 -#define ALG_ENC_CAST 4 -#define ALG_ENC_SKIPJACK 5 +/* 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 */ +/* xform attributes */ #define XFT_AUTH 0x0001 #define XFT_CONF 0x0100 @@ -160,11 +332,11 @@ struct xformsw static __inline u_int64_t htonq(u_int64_t q) { - register u_int32_t u, l; - u = q >> 32; - l = (u_int32_t) q; + register u_int32_t u, l; + u = q >> 32; + l = (u_int32_t) q; - return htonl(u) | ((u_int64_t)htonl(l) << 32); + return htonl(u) | ((u_int64_t)htonl(l) << 32); } #define ntohq(_x) htonq(_x) @@ -178,36 +350,41 @@ htonq(u_int64_t q) #error "Please fix <machine/endian.h>" #endif -extern unsigned char ipseczeroes[]; - /* * Names for IPsec sysctl objects */ -#define IPSECCTL_ENCAP 0 +#define IPSECCTL_PFKEY 0 #define IPSECCTL_MAXID 1 #define CTL_IPSEC_NAMES {\ - { "encap", CTLTYPE_NODE }, \ + { "pfkey", CTLTYPE_NODE }, \ +} + +#define PFKEYCTL_ENCDEBUG 1 +#define PFKEYCTL_MAXID 2 + +#define PFKEYCTL_NAMES {\ + { 0, 0 }, \ + { "encdebug", CTLTYPE_INT }, \ } #ifdef _KERNEL extern int encdebug; +extern int ipsec_in_use; +extern u_int8_t hmac_ipad_buffer[64]; +extern u_int8_t hmac_opad_buffer[64]; struct tdb *tdbh[TDB_HASHMOD]; struct expiration *explist; extern struct xformsw xformsw[], *xformswNXFORMSW; -u_int32_t notify_msgids; /* Check if a given tdb has encryption, authentication and/or tunneling */ -#define TDB_ATTRIB(x) \ - (((x)->tdb_confname != NULL ? NOTIFY_SATYPE_CONF : 0)| \ - ((x)->tdb_authname != NULL ? NOTIFY_SATYPE_AUTH : 0)| \ - ((x)->tdb_confname != NULL && \ - ((x)->tdb_flags & TDBF_TUNNELING) ? NOTIFY_SATYPE_TUNNEL : 0)) +#define TDB_ATTRIB(x) (((x)->tdb_encalgxform ? NOTIFY_SATYPE_CONF : 0)| \ + ((x)->tdb_authalgxform ? NOTIFY_SATYPE_AUTH : 0)) /* Traverse spi chain and get attributes */ -#define SPI_CHAIN_ATTRIB(have, TDB_DIR, TDBP) { \ +#define SPI_CHAIN_ATTRIB(have, TDB_DIR, TDBP) {\ struct tdb *tmptdb = (TDBP); \ (have) = 0; \ \ @@ -219,32 +396,39 @@ u_int32_t notify_msgids; } \ } +/* Misc. */ +extern char *inet_ntoa4(struct in_addr); +extern char *ipsp_address(union sockaddr_union); + /* TDB management routines */ -extern u_int32_t reserve_spi(u_int32_t, struct in_addr, u_int8_t, int *); -extern struct tdb *gettdb(u_int32_t, struct in_addr, u_int8_t); +extern u_int32_t reserve_spi(u_int32_t, u_int32_t, union sockaddr_union *, + union sockaddr_union *, u_int8_t, int *); +extern struct tdb *gettdb(u_int32_t, union sockaddr_union *, u_int8_t); extern void puttdb(struct tdb *); extern int tdb_delete(struct tdb *, int); +extern int tdb_init (struct tdb *, u_int16_t, struct ipsecinit *); /* Expiration management routines */ extern struct expiration *get_expiration(void); extern void put_expiration(struct expiration *); extern void handle_expirations(void *); -extern void cleanup_expirations(struct in_addr, u_int32_t, u_int8_t); +extern void cleanup_expirations(union sockaddr_union *, u_int32_t, u_int8_t); /* Flow management routines */ extern struct flow *get_flow(void); extern void put_flow(struct flow *, struct tdb *); extern void delete_flow(struct flow *, struct tdb *); -extern struct flow *find_flow(struct in_addr, struct in_addr, struct in_addr, - struct in_addr, u_int8_t, u_int16_t, u_int16_t, - struct tdb *); -extern struct flow *find_global_flow(struct in_addr, struct in_addr, - struct in_addr, struct in_addr, u_int8_t, - u_int16_t, u_int16_t); +extern struct flow *find_flow(union sockaddr_union *, union sockaddr_union *, + union sockaddr_union *, union sockaddr_union *, + u_int8_t, struct tdb *); +extern struct flow *find_global_flow(union sockaddr_union *, + union sockaddr_union *, + union sockaddr_union *, + union sockaddr_union *, u_int8_t); /* XF_IP4 */ extern int ipe4_attach(void); -extern int ipe4_init(struct tdb *, struct xformsw *, struct mbuf *); +extern int ipe4_init(struct tdb *, struct xformsw *, struct ipsecinit *); extern int ipe4_zeroize(struct tdb *); extern int ipe4_output(struct mbuf *, struct sockaddr_encap *, struct tdb *, struct mbuf **); @@ -253,7 +437,7 @@ extern void ip4_input __P((struct mbuf *, ...)); /* XF_OLD_AH */ extern int ah_old_attach(void); -extern int ah_old_init(struct tdb *, struct xformsw *, struct mbuf *); +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 sockaddr_encap *, struct tdb *, struct mbuf **); @@ -261,7 +445,7 @@ extern struct mbuf *ah_old_input(struct mbuf *, struct tdb *); /* XF_NEW_AH */ extern int ah_new_attach(void); -extern int ah_new_init(struct tdb *, struct xformsw *, struct mbuf *); +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 sockaddr_encap *, struct tdb *, struct mbuf **); @@ -269,7 +453,7 @@ extern struct mbuf *ah_new_input(struct mbuf *, struct tdb *); /* XF_OLD_ESP */ extern int esp_old_attach(void); -extern int esp_old_init(struct tdb *, struct xformsw *, struct mbuf *); +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 sockaddr_encap *, struct tdb *, struct mbuf **); @@ -277,7 +461,7 @@ extern struct mbuf *esp_old_input(struct mbuf *, struct tdb *); /* XF_NEW_ESP */ extern int esp_new_attach(void); -extern int esp_new_init(struct tdb *, struct xformsw *, struct mbuf *); +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 sockaddr_encap *, struct tdb *, struct mbuf **); @@ -288,5 +472,7 @@ extern caddr_t m_pad(struct mbuf *, int, int); /* Replay window */ extern int checkreplaywindow32(u_int32_t, u_int32_t, u_int32_t *, u_int32_t, - u_int32_t *); + u_int32_t *); + +extern unsigned char ipseczeroes[]; #endif diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c index 5ccf119abe8..f3976ded930 100644 --- a/sys/netinet/ip_output.c +++ b/sys/netinet/ip_output.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_output.c,v 1.39 1999/01/11 00:42:53 angelos Exp $ */ +/* $OpenBSD: ip_output.c,v 1.40 1999/02/24 22:33:07 angelos Exp $ */ /* $NetBSD: ip_output.c,v 1.28 1996/02/13 23:43:07 christos Exp $ */ /* @@ -64,11 +64,15 @@ #include <machine/stdarg.h> #ifdef IPSEC -#include <net/encap.h> #include <netinet/ip_ipsp.h> #include <netinet/udp.h> #include <netinet/tcp.h> -#include <sys/syslog.h> + +#ifdef ENCDEBUG +#define DPRINTF(x) if (encdebug) printf x +#else +#define DPRINTF(x) +#endif extern u_int8_t get_sa_require __P((struct inpcb *)); @@ -117,6 +121,7 @@ ip_output(m0, va_alist) struct ip_moptions *imo; va_list ap; #ifdef IPSEC + union sockaddr_union sunion; struct mbuf *mp; struct udphdr *udp; struct tcphdr *tcp; @@ -163,7 +168,8 @@ ip_output(m0, va_alist) /* * Check if the packet needs encapsulation */ - if (!(flags & IP_ENCAPSULATED) && + if ((ipsec_in_use != 0) && + !(flags & IP_ENCAPSULATED) && (inp == NULL || (inp->inp_seclevel[SL_AUTH] != IPSEC_LEVEL_BYPASS || inp->inp_seclevel[SL_ESP_TRANS] != IPSEC_LEVEL_BYPASS || @@ -180,7 +186,7 @@ ip_output(m0, va_alist) bzero((caddr_t) re, sizeof(*re)); ddst = (struct sockaddr_encap *) &re->re_dst; - ddst->sen_family = AF_ENCAP; + ddst->sen_family = PF_KEY; ddst->sen_len = SENT_IP4_LEN; ddst->sen_type = SENT_IP4; ddst->sen_ip_src = ip->ip_src; @@ -234,10 +240,8 @@ ip_output(m0, va_alist) goto no_encap; if (gw == NULL || gw->sen_type != SENT_IPSP) { -#ifdef ENCDEBUG - if (encdebug) - printf("ip_output(): no gw or gw data not IPSP\n"); -#endif /* ENCDEBUG */ + DPRINTF(("ip_output(): no gw or gw data not IPSP\n")); + if (re->re_rt) RTFREE(re->re_rt); error = EHOSTUNREACH; @@ -250,17 +254,11 @@ ip_output(m0, va_alist) * indicate the need for an SA when none is established. */ if (ntohl(gw->sen_ipsp_spi) == 0x1) { - struct tdb tmptdb; - sa_require = NOTIFY_SATYPE_AUTH | NOTIFY_SATYPE_TUNNEL; if (gw->sen_ipsp_sproto == IPPROTO_ESP) sa_require |= NOTIFY_SATYPE_CONF; - tmptdb.tdb_dst.s_addr = gw->sen_ipsp_dst.s_addr; - tmptdb.tdb_satype = sa_require; - - /* Request SA with key management */ - encap_sendnotify(NOTIFY_REQUEST_SA, &tmptdb, NULL); + /* XXX PF_KEYv2 notification message */ /* * When sa_require is set, the packet will be dropped @@ -280,8 +278,12 @@ ip_output(m0, va_alist) * and then pass it, along with the packet and the gw, * to the appropriate transformation. */ - tdb = (struct tdb *) gettdb(gw->sen_ipsp_spi, gw->sen_ipsp_dst, - gw->sen_ipsp_sproto); + bzero(&sunion, sizeof(sunion)); + sunion.sin.sin_family = AF_INET; + sunion.sin.sin_len = sizeof(struct sockaddr_in); + sunion.sin.sin_addr = gw->sen_ipsp_dst; + tdb = (struct tdb *) gettdb(gw->sen_ipsp_spi, &sunion, + gw->sen_ipsp_sproto); /* * Now we check if this tdb has all the transforms which @@ -293,10 +295,8 @@ ip_output(m0, va_alist) goto no_encap; if (tdb == NULL) { -#ifdef ENCDEBUG - if (encdebug) - printf("ip_output(): non-existant TDB for SA %08x/%x/%d\n", ntohl(gw->sen_ipsp_spi), gw->sen_ipsp_dst, gw->sen_ipsp_sproto); -#endif + DPRINTF(("ip_output(): non-existant TDB for SA %s/%08x/%u\n", inet_ntoa4(gw->sen_ipsp_dst), ntohl(gw->sen_ipsp_spi), gw->sen_ipsp_sproto)); + if (re->re_rt) RTFREE(re->re_rt); error = EHOSTUNREACH; @@ -306,8 +306,9 @@ ip_output(m0, va_alist) /* Fix the ip_src field if necessary */ if (ip->ip_src.s_addr == INADDR_ANY) { - if (tdb && tdb->tdb_src.s_addr != 0) /* Provided */ - ip->ip_src = tdb->tdb_src; + if (tdb && tdb->tdb_src.sin.sin_addr.s_addr != 0 && + tdb->tdb_src.sa.sa_family == AF_INET) + ip->ip_src = tdb->tdb_src.sin.sin_addr; else { if (ro == 0) { @@ -349,63 +350,39 @@ ip_output(m0, va_alist) } } -#ifdef ENCDEBUG - if (encdebug) { - printf("ip_output(): tdb=%08x, tdb->tdb_xform=0x%x,", - tdb, tdb->tdb_xform); - printf(" tdb->tdb_xform->xf_output=%x, sproto=%x\n", - tdb->tdb_xform->xf_output, tdb->tdb_sproto); - } -#endif /* ENCDEBUG */ - while (tdb && tdb->tdb_xform) { /* Check if the SPI is invalid */ if (tdb->tdb_flags & TDBF_INVALID) { - if (encdebug) - log(LOG_ALERT, "ip_output(): attempt to use invalid SA %08x/%x/%x\n", ntohl(tdb->tdb_spi), tdb->tdb_dst, - tdb->tdb_sproto); + DPRINTF(("ip_output(): attempt to use invalid SA %s/%08x/%u\n", ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi), tdb->tdb_sproto)); m_freem(m); RTFREE(re->re_rt); return ENXIO; } -#ifdef ENCDEBUG - if (encdebug) - printf("ip_output(): calling %s\n", - tdb->tdb_xform->xf_name); -#endif /* ENCDEBUG */ + DPRINTF(("ip_output(): calling %s\n", + tdb->tdb_xform->xf_name)); /* Register first use, setup expiration timer */ if (tdb->tdb_first_use == 0) { - tdb->tdb_first_use = time.tv_sec; - - if (tdb->tdb_flags & TDBF_FIRSTUSE) { - exp = get_expiration(); - if (exp == NULL) - goto expbail; - exp->exp_dst.s_addr = - tdb->tdb_dst.s_addr; - exp->exp_spi = tdb->tdb_spi; - exp->exp_sproto = tdb->tdb_sproto; - exp->exp_timeout = tdb->tdb_first_use + - tdb->tdb_exp_first_use; - put_expiration(exp); + tdb->tdb_first_use = time.tv_sec; + + if (tdb->tdb_flags & TDBF_FIRSTUSE) { + exp = get_expiration(); + bcopy(&tdb->tdb_dst, &exp->exp_dst, + SA_LEN(&tdb->tdb_dst.sa)); + exp->exp_spi = tdb->tdb_spi; + exp->exp_sproto = tdb->tdb_sproto; + exp->exp_timeout = tdb->tdb_first_use + + tdb->tdb_exp_first_use; + put_expiration(exp); } if ((tdb->tdb_flags & TDBF_SOFT_FIRSTUSE) && (tdb->tdb_soft_first_use <= tdb->tdb_exp_first_use)) { exp = get_expiration(); - if (exp == NULL) { -expbail: - if (encdebug) - log(LOG_WARNING, "ip_output(): no memory for exp timer\n"); - m_freem(m); - RTFREE(re->re_rt); - return ENOBUFS; - } - exp->exp_dst.s_addr = - tdb->tdb_dst.s_addr; + bcopy(&tdb->tdb_dst, &exp->exp_dst, + SA_LEN(&tdb->tdb_dst.sa)); exp->exp_spi = tdb->tdb_spi; exp->exp_sproto = tdb->tdb_sproto; exp->exp_timeout = tdb->tdb_first_use + @@ -415,12 +392,12 @@ expbail: } /* Check for tunneling */ - if ((tdb->tdb_flags & TDBF_TUNNELING) && - (tdb->tdb_xform->xf_type != XF_IP4)){ -#ifdef ENCDEBUG - if (encdebug) - printf("ip_output(): tunneling\n"); -#endif /* ENCDEBUG */ + if (((tdb->tdb_dst.sin.sin_addr.s_addr != + ip->ip_dst.s_addr) || + (tdb->tdb_flags & TDBF_TUNNELING)) && + (tdb->tdb_xform->xf_type != XF_IP4)) + { + DPRINTF(("ip_output(): tunneling\n")); /* * Fix checksum here, AH and ESP fix the |