add the glue between ipsec security associations and sec(4) interfaces.
authordlg <dlg@openbsd.org>
Mon, 7 Aug 2023 03:43:57 +0000 (03:43 +0000)
committerdlg <dlg@openbsd.org>
Mon, 7 Aug 2023 03:43:57 +0000 (03:43 +0000)
if TDBF_IFACE is set on a tdb, the ipsec stack will pass it to the
sec(4) driver to keep track of instead of wiring it up for security
associations to use.

when sec(4) transmits a packet, it will look up it's list of tdbs
to find the right SA to encrypt and send the packet out with.

if an incoming ipsec packet arrives with TDBF_IFACE set, it's passed
to sec(4) to be injected back into the network stack as if it was
received on the sec interface, instead of being reinjected into the
IP stack like normal SA/SPD processing does.

note that this means you do not have to configure tunnel endpoints
on sec(4) interfaces, instead you line the interface unit number
in the ipsec config up with the minor number of the sec(4) interfaces.
the peer IPs used on the SAs are what's used as the traffic endpoints.

support from many including markus@ tobhe@ claudio@ sthen@ patrick@
now is a good time deraadt@

sys/netinet/ip_ipsp.c
sys/netinet/ipsec_input.c

index b76314b..90179f0 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ip_ipsp.c,v 1.275 2022/11/11 18:09:58 cheloha Exp $   */
+/*     $OpenBSD: ip_ipsp.c,v 1.276 2023/08/07 03:43:57 dlg Exp $       */
 /*
  * The authors of this code are John Ioannidis (ji@tla.org),
  * Angelos D. Keromytis (kermit@csd.uch.gr),
@@ -39,6 +39,7 @@
 
 #include "pf.h"
 #include "pfsync.h"
+#include "sec.h"
 
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <net/if_pfsync.h>
 #endif
 
+#if NSEC > 0
+#include <net/if_sec.h>
+#endif
+
 #include <netinet/ip_ipsp.h>
 #include <net/pfkeyv2.h>
 
@@ -852,14 +857,6 @@ puttdb_locked(struct tdb *tdbp)
        tdbp->tdb_hnext = tdbh[hashval];
        tdbh[hashval] = tdbp;
 
-       hashval = tdb_hash(0, &tdbp->tdb_dst, tdbp->tdb_sproto);
-       tdbp->tdb_dnext = tdbdst[hashval];
-       tdbdst[hashval] = tdbp;
-
-       hashval = tdb_hash(0, &tdbp->tdb_src, tdbp->tdb_sproto);
-       tdbp->tdb_snext = tdbsrc[hashval];
-       tdbsrc[hashval] = tdbp;
-
        tdb_count++;
 #ifdef IPSEC
        if ((tdbp->tdb_flags & (TDBF_INVALID|TDBF_TUNNELING)) == TDBF_TUNNELING)
@@ -867,6 +864,21 @@ puttdb_locked(struct tdb *tdbp)
 #endif /* IPSEC */
 
        ipsec_last_added = getuptime();
+
+       if (ISSET(tdbp->tdb_flags, TDBF_IFACE)) {
+#if NSEC > 0
+               sec_tdb_insert(tdbp);
+#endif
+               return;
+       }
+
+       hashval = tdb_hash(0, &tdbp->tdb_dst, tdbp->tdb_sproto);
+       tdbp->tdb_dnext = tdbdst[hashval];
+       tdbdst[hashval] = tdbp;
+
+       hashval = tdb_hash(0, &tdbp->tdb_src, tdbp->tdb_sproto);
+       tdbp->tdb_snext = tdbsrc[hashval];
+       tdbsrc[hashval] = tdbp;
 }
 
 void
@@ -901,6 +913,22 @@ tdb_unlink_locked(struct tdb *tdbp)
 
        tdbp->tdb_hnext = NULL;
 
+       tdb_count--;
+#ifdef IPSEC
+       if ((tdbp->tdb_flags & (TDBF_INVALID|TDBF_TUNNELING)) ==
+           TDBF_TUNNELING) {
+               ipsecstat_dec(ipsec_tunnels);
+               ipsecstat_inc(ipsec_prevtunnels);
+       }
+#endif /* IPSEC */
+
+       if (ISSET(tdbp->tdb_flags, TDBF_IFACE)) {
+#if NSEC > 0
+               sec_tdb_remove(tdbp);
+#endif
+               return;
+       }
+
        hashval = tdb_hash(0, &tdbp->tdb_dst, tdbp->tdb_sproto);
 
        if (tdbdst[hashval] == tdbp) {
@@ -932,14 +960,6 @@ tdb_unlink_locked(struct tdb *tdbp)
        }
 
        tdbp->tdb_snext = NULL;
-       tdb_count--;
-#ifdef IPSEC
-       if ((tdbp->tdb_flags & (TDBF_INVALID|TDBF_TUNNELING)) ==
-           TDBF_TUNNELING) {
-               ipsecstat_dec(ipsec_tunnels);
-               ipsecstat_inc(ipsec_prevtunnels);
-       }
-#endif /* IPSEC */
 }
 
 void
index 5df9a4f..9e3f4de 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ipsec_input.c,v 1.204 2023/05/13 13:35:17 bluhm Exp $ */
+/*     $OpenBSD: ipsec_input.c,v 1.205 2023/08/07 03:43:57 dlg Exp $   */
 /*
  * The authors of this code are John Ioannidis (ji@tla.org),
  * Angelos D. Keromytis (kermit@csd.uch.gr) and
@@ -36,6 +36,7 @@
  */
 
 #include "pf.h"
+#include "sec.h"
 
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <net/pfvar.h>
 #endif
 
+#if NSEC > 0
+#include <net/if_sec.h>
+#endif
+
 #ifdef INET6
 #include <netinet6/in6_var.h>
 #include <netinet/ip6.h>
@@ -545,6 +550,22 @@ ipsec_common_input_cb(struct mbuf **mp, struct tdb *tdbp, int skip, int protoff)
        }
 #endif
 
+       if (ISSET(tdbp->tdb_flags, TDBF_IFACE)) {
+#if NSEC > 0
+               if (ISSET(tdbp->tdb_flags, TDBF_TUNNELING) &&
+                   tdbp->tdb_iface_dir == IPSP_DIRECTION_IN) {
+                       struct sec_softc *sc = sec_get(tdbp->tdb_iface);
+                       if (sc == NULL)
+                               goto baddone;
+
+                       sec_input(sc, af, prot, m);
+                       sec_put(sc);
+                       return IPPROTO_DONE;
+               }
+#endif /* NSEC > 0 */
+               goto baddone;
+       }
+
 #if NPF > 0
        /*
         * The ip_deliver() shortcut avoids running through ip_input() with the