summaryrefslogtreecommitdiffstats
path: root/freebsd/sys/netipsec/xform_ah.c
diff options
context:
space:
mode:
Diffstat (limited to 'freebsd/sys/netipsec/xform_ah.c')
-rw-r--r--freebsd/sys/netipsec/xform_ah.c44
1 files changed, 31 insertions, 13 deletions
diff --git a/freebsd/sys/netipsec/xform_ah.c b/freebsd/sys/netipsec/xform_ah.c
index f5c0929b..98d319ce 100644
--- a/freebsd/sys/netipsec/xform_ah.c
+++ b/freebsd/sys/netipsec/xform_ah.c
@@ -87,8 +87,7 @@
* to use a fixed 16-byte authenticator. The new algorithm use 12-byte
* authenticator.
*/
-#define AUTHSIZE(sav) \
- ((sav->flags & SADB_X_EXT_OLD) ? 16 : AH_HMAC_HASHLEN)
+#define AUTHSIZE(sav) ah_authsize(sav)
VNET_DEFINE(int, ah_enable) = 1; /* control flow of packets with AH */
VNET_DEFINE(int, ah_cleartos) = 1; /* clear ip_tos when doing AH calc */
@@ -107,6 +106,27 @@ static unsigned char ipseczeroes[256]; /* larger than an ip6 extension hdr */
static int ah_input_cb(struct cryptop*);
static int ah_output_cb(struct cryptop*);
+static int
+ah_authsize(struct secasvar *sav)
+{
+
+ IPSEC_ASSERT(sav != NULL, ("%s: sav == NULL", __func__));
+
+ if (sav->flags & SADB_X_EXT_OLD)
+ return 16;
+
+ switch (sav->alg_auth) {
+ case SADB_X_AALG_SHA2_256:
+ return 16;
+ case SADB_X_AALG_SHA2_384:
+ return 24;
+ case SADB_X_AALG_SHA2_512:
+ return 32;
+ default:
+ return AH_HMAC_HASHLEN;
+ }
+ /* NOTREACHED */
+}
/*
* NB: this is public for use by the PF_KEY support.
*/
@@ -697,6 +717,8 @@ ah_input(struct mbuf *m, struct secasvar *sav, int skip, int protoff)
tc->tc_protoff = protoff;
tc->tc_skip = skip;
tc->tc_ptr = (caddr_t) mtag; /* Save the mtag we've identified. */
+ KEY_ADDREFSA(sav);
+ tc->tc_sav = sav;
if (mtag == NULL)
return crypto_dispatch(crp);
@@ -746,13 +768,8 @@ ah_input_cb(struct cryptop *crp)
mtag = (struct m_tag *) tc->tc_ptr;
m = (struct mbuf *) crp->crp_buf;
- sav = KEY_ALLOCSA(&tc->tc_dst, tc->tc_proto, tc->tc_spi);
- if (sav == NULL) {
- V_ahstat.ahs_notdb++;
- DPRINTF(("%s: SA expired while in crypto\n", __func__));
- error = ENOBUFS; /*XXX*/
- goto bad;
- }
+ sav = tc->tc_sav;
+ IPSEC_ASSERT(sav != NULL, ("null SA!"));
saidx = &sav->sah->saidx;
IPSEC_ASSERT(saidx->dst.sa.sa_family == AF_INET ||
@@ -1092,6 +1109,8 @@ ah_output(
/* These are passed as-is to the callback. */
tc->tc_isr = isr;
+ KEY_ADDREFSA(sav);
+ tc->tc_sav = sav;
tc->tc_spi = sav->spi;
tc->tc_dst = sav->sah->saidx.dst;
tc->tc_proto = sav->sah->saidx.proto;
@@ -1128,14 +1147,14 @@ ah_output_cb(struct cryptop *crp)
isr = tc->tc_isr;
IPSECREQUEST_LOCK(isr);
- sav = KEY_ALLOCSA(&tc->tc_dst, tc->tc_proto, tc->tc_spi);
- if (sav == NULL) {
+ sav = tc->tc_sav;
+ /* With the isr lock released SA pointer can be updated. */
+ if (sav != isr->sav) {
V_ahstat.ahs_notdb++;
DPRINTF(("%s: SA expired while in crypto\n", __func__));
error = ENOBUFS; /*XXX*/
goto bad;
}
- IPSEC_ASSERT(isr->sav == sav, ("SA changed\n"));
/* Check for crypto errors. */
if (crp->crp_etype) {
@@ -1143,7 +1162,6 @@ ah_output_cb(struct cryptop *crp)
sav->tdb_cryptoid = crp->crp_sid;
if (crp->crp_etype == EAGAIN) {
- KEY_FREESAV(&sav);
IPSECREQUEST_UNLOCK(isr);
error = crypto_dispatch(crp);
return error;