From 401f201bd4f0a01cb0841fe44c30f9888159ac66 Mon Sep 17 00:00:00 2001 From: tobhe Date: Sun, 24 Oct 2021 22:34:19 +0000 Subject: [PATCH] Refactor ah_input() and ah_output() for new crypto API. ok bluhm@ --- sys/netinet/ip_ah.c | 167 ++++++++++++++---------------------------- sys/netinet/ip_ipsp.h | 5 +- 2 files changed, 57 insertions(+), 115 deletions(-) diff --git a/sys/netinet/ip_ah.c b/sys/netinet/ip_ah.c index 40347ee61b9..0a9a4fbbc04 100644 --- a/sys/netinet/ip_ah.c +++ b/sys/netinet/ip_ah.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_ah.c,v 1.163 2021/10/24 17:08:27 bluhm Exp $ */ +/* $OpenBSD: ip_ah.c,v 1.164 2021/10/24 22:34:19 tobhe Exp $ */ /* * The authors of this code are John Ioannidis (ji@tla.org), * Angelos D. Keromytis (kermit@csd.uch.gr) and @@ -530,17 +530,20 @@ int ah_input(struct mbuf **mp, struct tdb *tdb, int skip, int protoff) { const struct auth_hash *ahx = tdb->tdb_authalgxform; - struct mbuf *m = *mp; - struct tdb_crypto *tc = NULL; - u_int32_t btsx, esn; - u_int8_t hl; + struct mbuf *m = *mp, *m1, *m0; + struct cryptodesc *crda = NULL; + struct cryptop *crp = NULL; + int roff; + uint32_t btsx, esn; + uint8_t *ptr = NULL; + uint8_t hl; int error, rplen, clen; - u_int64_t ibytes; + uint64_t ibytes; + uint64_t rpl; #ifdef ENCDEBUG char buf[INET6_ADDRSTRLEN]; #endif - struct cryptodesc *crda = NULL; - struct cryptop *crp = NULL; + uint8_t calc[AH_ALEN_MAX]; rplen = AH_FLENGTH + sizeof(u_int32_t); @@ -658,10 +661,9 @@ ah_input(struct mbuf **mp, struct tdb *tdb, int skip, int protoff) } /* Allocate IPsec-specific opaque crypto info. */ - tc = malloc(sizeof(*tc) + skip + rplen + ahx->authsize, M_XDATA, - M_NOWAIT | M_ZERO); - if (tc == NULL) { - DPRINTF("failed to allocate tdb_crypto"); + ptr = malloc(skip + rplen + ahx->authsize, M_XDATA, M_NOWAIT | M_ZERO); + if (ptr == NULL) { + DPRINTF("failed to allocate buffer"); ahstat_inc(ahs_crypto); error = ENOBUFS; goto drop; @@ -671,7 +673,7 @@ ah_input(struct mbuf **mp, struct tdb *tdb, int skip, int protoff) * Save the authenticator, the skipped portion of the packet, * and the AH header. */ - m_copydata(m, 0, skip + rplen + ahx->authsize, tc + 1); + m_copydata(m, 0, skip + rplen + ahx->authsize, ptr); /* Zeroize the authenticator on the packet. */ m_copyback(m, skip + rplen, ahx->authsize, ipseczeroes, M_NOWAIT); @@ -690,15 +692,6 @@ ah_input(struct mbuf **mp, struct tdb *tdb, int skip, int protoff) crp->crp_buf = (caddr_t)m; crp->crp_sid = tdb->tdb_cryptoid; - /* These are passed as-is to the callback. */ - tc->tc_skip = skip; - tc->tc_protoff = protoff; - tc->tc_spi = tdb->tdb_spi; - tc->tc_proto = tdb->tdb_sproto; - tc->tc_rdomain = tdb->tdb_rdomain; - memcpy(&tc->tc_dst, &tdb->tdb_dst, sizeof(union sockaddr_union)); - tc->tc_rpl = tdb->tdb_rpl; - KERNEL_LOCK(); while ((error = crypto_invoke(crp)) == EAGAIN) { /* Reset the session ID */ @@ -717,59 +710,30 @@ ah_input(struct mbuf **mp, struct tdb *tdb, int skip, int protoff) /* Release the crypto descriptors */ crypto_freereq(crp); - - return ah_input_cb(tdb, tc, mp, clen); - - drop: - m_freemp(mp); - crypto_freereq(crp); - free(tc, M_XDATA, 0); - return error; -} - -int -ah_input_cb(struct tdb *tdb, struct tdb_crypto *tc, struct mbuf **mp, int clen) -{ - const struct auth_hash *ahx = tdb->tdb_authalgxform; - struct mbuf *m = *mp; - int roff, rplen, skip, protoff; - u_int64_t rpl; - u_int32_t btsx, esn; - caddr_t ptr; - unsigned char calc[AH_ALEN_MAX]; - struct mbuf *m1, *m0; -#ifdef ENCDEBUG - char buf[INET6_ADDRSTRLEN]; -#endif - - NET_ASSERT_LOCKED(); - - skip = tc->tc_skip; - protoff = tc->tc_protoff; - rpl = tc->tc_rpl; - - rplen = AH_FLENGTH + sizeof(u_int32_t); + crp = NULL; /* Copy authenticator off the packet. */ m_copydata(m, skip + rplen, ahx->authsize, calc); - ptr = (caddr_t) (tc + 1); - /* Verify authenticator. */ if (timingsafe_bcmp(ptr + skip + rplen, calc, ahx->authsize)) { DPRINTF("authentication failed for packet in SA %s/%08x", ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)), ntohl(tdb->tdb_spi)); ahstat_inc(ahs_badauth); - goto baddone; + error = -1; + goto drop; } /* Fix the Next Protocol field. */ - ((u_int8_t *) ptr)[protoff] = ((u_int8_t *) ptr)[skip]; + ptr[protoff] = ptr[skip]; /* Copyback the saved (uncooked) network headers. */ m_copyback(m, 0, skip, ptr, M_NOWAIT); + free(ptr, M_XDATA, 0); + ptr = NULL; + /* Replay window checking, if applicable. */ if (tdb->tdb_wnd > 0) { m_copydata(m, skip + offsetof(struct ah, ah_rpl), @@ -787,26 +751,30 @@ ah_input_cb(struct tdb *tdb, struct tdb_crypto *tc, struct mbuf **mp, int clen) ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)), ntohl(tdb->tdb_spi)); ahstat_inc(ahs_wrap); - goto baddone; + error = -1; + goto drop; case 2: DPRINTF("old packet received in SA %s/%08x", ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)), ntohl(tdb->tdb_spi)); ahstat_inc(ahs_replay); - goto baddone; + error = -1; + goto drop; case 3: DPRINTF("duplicate packet received in SA %s/%08x", ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)), ntohl(tdb->tdb_spi)); ahstat_inc(ahs_replay); - goto baddone; + error = -1; + goto drop; default: DPRINTF("bogus value from checkreplaywindow() " "in SA %s/%08x", ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)), ntohl(tdb->tdb_spi)); ahstat_inc(ahs_replay); - goto baddone; + error = -1; + goto drop; } } @@ -817,7 +785,8 @@ ah_input_cb(struct tdb *tdb, struct tdb_crypto *tc, struct mbuf **mp, int clen) ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)), ntohl(tdb->tdb_spi)); ahstat_inc(ahs_hdrops); - goto baddone; + error = -1; + goto drop; } /* Remove the AH header from the mbuf. */ @@ -889,14 +858,13 @@ ah_input_cb(struct tdb *tdb, struct tdb_crypto *tc, struct mbuf **mp, int clen) m->m_pkthdr.len -= rplen + ahx->authsize; } - free(tc, M_XDATA, 0); - return ipsec_common_input_cb(mp, tdb, skip, protoff); - baddone: + drop: + free(ptr, M_XDATA, 0); m_freemp(mp); - free(tc, M_XDATA, 0); - return -1; + crypto_freereq(crp); + return error; } /* @@ -907,13 +875,13 @@ ah_output(struct mbuf *m, struct tdb *tdb, int skip, int protoff) { const struct auth_hash *ahx = tdb->tdb_authalgxform; struct cryptodesc *crda; - struct tdb_crypto *tc = NULL; struct mbuf *mi; struct cryptop *crp = NULL; - u_int64_t replay64; - u_int16_t iplen; + uint64_t replay64; + uint16_t iplen; int error, rplen, roff, ilen, olen; - u_int8_t prot; + uint8_t *ptr = NULL; + uint8_t prot; struct ah *ah; #if NBPFILTER > 0 struct ifnet *encif; @@ -1095,17 +1063,16 @@ ah_output(struct mbuf *m, struct tdb *tdb, int skip, int protoff) crda->crd_flags |= CRD_F_ESN; } - /* Allocate IPsec-specific opaque crypto info. */ - tc = malloc(sizeof(*tc) + skip, M_XDATA, M_NOWAIT | M_ZERO); - if (tc == NULL) { - DPRINTF("failed to allocate tdb_crypto"); + ptr = malloc(skip, M_XDATA, M_NOWAIT | M_ZERO); + if (ptr == NULL) { + DPRINTF("failed to allocate buffer"); ahstat_inc(ahs_crypto); error = ENOBUFS; goto drop; } /* Save the skipped portion of the packet. */ - m_copydata(m, 0, skip, tc + 1); + m_copydata(m, 0, skip, ptr); /* * Fix IP header length on the header used for @@ -1114,7 +1081,7 @@ ah_output(struct mbuf *m, struct tdb *tdb, int skip, int protoff) */ switch (tdb->tdb_dst.sa.sa_family) { case AF_INET: - memcpy((caddr_t) &iplen, ((caddr_t)(tc + 1)) + + memcpy((caddr_t) &iplen, ((caddr_t)ptr) + offsetof(struct ip, ip_len), sizeof(u_int16_t)); iplen = htons(ntohs(iplen) + rplen + ahx->authsize); m_copyback(m, offsetof(struct ip, ip_len), @@ -1123,7 +1090,7 @@ ah_output(struct mbuf *m, struct tdb *tdb, int skip, int protoff) #ifdef INET6 case AF_INET6: - memcpy((caddr_t) &iplen, ((caddr_t)(tc + 1)) + + memcpy((caddr_t) &iplen, ((caddr_t)ptr) + offsetof(struct ip6_hdr, ip6_plen), sizeof(u_int16_t)); iplen = htons(ntohs(iplen) + rplen + ahx->authsize); m_copyback(m, offsetof(struct ip6_hdr, ip6_plen), @@ -1133,7 +1100,7 @@ ah_output(struct mbuf *m, struct tdb *tdb, int skip, int protoff) } /* Fix the Next Header field in saved header. */ - ((u_int8_t *) (tc + 1))[protoff] = IPPROTO_AH; + ptr[protoff] = IPPROTO_AH; /* Update the Next Protocol field in the IP header. */ prot = IPPROTO_AH; @@ -1154,14 +1121,6 @@ ah_output(struct mbuf *m, struct tdb *tdb, int skip, int protoff) crp->crp_buf = (caddr_t)m; crp->crp_sid = tdb->tdb_cryptoid; - /* These are passed as-is to the callback. */ - tc->tc_skip = skip; - tc->tc_protoff = protoff; - tc->tc_spi = tdb->tdb_spi; - tc->tc_proto = tdb->tdb_sproto; - tc->tc_rdomain = tdb->tdb_rdomain; - memcpy(&tc->tc_dst, &tdb->tdb_dst, sizeof(union sockaddr_union)); - KERNEL_LOCK(); while ((error = crypto_invoke(crp)) == EAGAIN) { /* Reset the session ID */ @@ -1180,39 +1139,25 @@ ah_output(struct mbuf *m, struct tdb *tdb, int skip, int protoff) /* Release the crypto descriptors */ crypto_freereq(crp); - - return ah_output_cb(tdb, tc, m, ilen, olen); - - drop: - m_freem(m); - crypto_freereq(crp); - free(tc, M_XDATA, 0); - return error; -} - -/* - * AH output callback. - */ -int -ah_output_cb(struct tdb *tdb, struct tdb_crypto *tc, struct mbuf *m, int ilen, - int olen) -{ - int skip = tc->tc_skip; - caddr_t ptr = (caddr_t) (tc + 1); - int error; + crp = NULL; /* * Copy original headers (with the new protocol number) back * in place. */ m_copyback(m, 0, skip, ptr, M_NOWAIT); - - /* No longer needed. */ - free(tc, M_XDATA, 0); + free(ptr, M_XDATA, 0); + ptr = NULL; /* Call the IPsec input callback. */ error = ipsp_process_done(m, tdb); if (error) ahstat_inc(ahs_outfail); return error; + + drop: + free(ptr, M_XDATA, 0); + m_freem(m); + crypto_freereq(crp); + return error; } diff --git a/sys/netinet/ip_ipsp.h b/sys/netinet/ip_ipsp.h index f79d393197b..768ee8519a8 100644 --- a/sys/netinet/ip_ipsp.h +++ b/sys/netinet/ip_ipsp.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_ipsp.h,v 1.215 2021/10/24 18:15:58 tobhe Exp $ */ +/* $OpenBSD: ip_ipsp.h,v 1.216 2021/10/24 22:34:19 tobhe Exp $ */ /* * The authors of this code are John Ioannidis (ji@tla.org), * Angelos D. Keromytis (kermit@csd.uch.gr), @@ -571,10 +571,7 @@ int ah_attach(void); int ah_init(struct tdb *, const struct xformsw *, struct ipsecinit *); int ah_zeroize(struct tdb *); int ah_input(struct mbuf **, struct tdb *, int, int); -int ah_input_cb(struct tdb *, struct tdb_crypto *, struct mbuf **, int); int ah_output(struct mbuf *, struct tdb *, int, int); -int ah_output_cb(struct tdb *, struct tdb_crypto *, struct mbuf *, int, - int); int ah_sysctl(int *, u_int, void *, size_t *, void *, size_t); int ah4_input(struct mbuf **, int *, int, int); -- 2.20.1