Refactor ah_input() and ah_output() for new crypto API.
authortobhe <tobhe@openbsd.org>
Sun, 24 Oct 2021 22:34:19 +0000 (22:34 +0000)
committertobhe <tobhe@openbsd.org>
Sun, 24 Oct 2021 22:34:19 +0000 (22:34 +0000)
ok bluhm@

sys/netinet/ip_ah.c
sys/netinet/ip_ipsp.h

index 40347ee..0a9a4fb 100644 (file)
@@ -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;
 }
index f79d393..768ee85 100644 (file)
@@ -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);