MFC: sys/netipsec/key.c

sys/netipsec/xform_ah.c
	sys/netipsec/xform_esp.c
	sys/netipsec/xform_ipcomp.c

- Allow to use fast_ipsec(4) on debug.mpsafenet=0 and INVARIANTS-enabled
  systems. Without the change it will panic on assertions.
- Update the code after opencrypto changes.
This commit is contained in:
pjd 2006-09-04 15:17:50 +00:00
parent f276329193
commit 1d18621829
4 changed files with 89 additions and 42 deletions

View File

@ -54,6 +54,7 @@
#include <sys/errno.h>
#include <sys/proc.h>
#include <sys/queue.h>
#include <sys/refcount.h>
#include <sys/syslog.h>
#include <net/if.h>
@ -495,14 +496,26 @@ static const char *key_getuserfqdn __P((void));
static void key_sa_chgstate __P((struct secasvar *, u_int8_t));
static struct mbuf *key_alloc_mbuf __P((int));
#define SA_ADDREF(p) do { \
(p)->refcnt++; \
IPSEC_ASSERT((p)->refcnt != 0, ("SA refcnt overflow")); \
} while (0)
#define SA_DELREF(p) do { \
IPSEC_ASSERT((p)->refcnt > 0, ("SA refcnt underflow")); \
(p)->refcnt--; \
} while (0)
static __inline void
sa_initref(struct secasvar *sav)
{
refcount_init(&sav->refcnt, 1);
}
static __inline void
sa_addref(struct secasvar *sav)
{
refcount_acquire(&sav->refcnt);
IPSEC_ASSERT(sav->refcnt != 0, ("SA refcnt overflow"));
}
static __inline int
sa_delref(struct secasvar *sav)
{
IPSEC_ASSERT(sav->refcnt > 0, ("SA refcnt underflow"));
return (refcount_release(&sav->refcnt));
}
#define SP_ADDREF(p) do { \
(p)->refcnt++; \
@ -993,7 +1006,7 @@ key_do_allocsa_policy(struct secashead *sah, u_int state)
}
}
if (candidate) {
SA_ADDREF(candidate);
sa_addref(candidate);
KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
printf("DP %s cause refcnt++:%d SA:%p\n",
__func__, candidate->refcnt, candidate));
@ -1072,7 +1085,7 @@ key_allocsa(
/* check dst address */
if (key_sockaddrcmp(&dst->sa, &sav->sah->saidx.dst.sa, 0) != 0)
continue;
SA_ADDREF(sav);
sa_addref(sav);
goto done;
}
}
@ -1191,16 +1204,16 @@ key_freesav(struct secasvar **psav, const char* where, int tag)
IPSEC_ASSERT(sav != NULL, ("null sav"));
/* XXX unguarded? */
SA_DELREF(sav);
KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
printf("DP %s SA:%p (SPI %u) from %s:%u; refcnt now %u\n",
__func__, sav, ntohl(sav->spi), where, tag, sav->refcnt));
if (sav->refcnt == 0) {
if (sa_delref(sav)) {
KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
printf("DP %s SA:%p (SPI %u) from %s:%u; refcnt now %u\n",
__func__, sav, ntohl(sav->spi), where, tag, sav->refcnt));
*psav = NULL;
key_delsav(sav);
} else {
KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
printf("DP %s SA:%p (SPI %u) from %s:%u; refcnt now %u\n",
__func__, sav, ntohl(sav->spi), where, tag, sav->refcnt));
}
}
@ -2757,7 +2770,7 @@ key_newsav(m, mhp, sah, errp, where, tag)
/* add to satree */
newsav->sah = sah;
newsav->refcnt = 1;
sa_initref(newsav);
newsav->state = SADB_SASTATE_LARVAL;
/* XXX locking??? */
@ -4776,7 +4789,7 @@ key_getsavbyseq(sah, seq)
KEY_CHKSASTATE(state, sav->state, __func__);
if (sav->seq == seq) {
SA_ADDREF(sav);
sa_addref(sav);
KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
printf("DP %s cause refcnt++:%d SA:%p\n",
__func__, sav->refcnt, sav));

View File

@ -81,11 +81,11 @@
sizeof (struct ah) : sizeof (struct ah) + sizeof (u_int32_t))
/*
* Return authenticator size in bytes. The old protocol is known
* to use a fixed 16-byte authenticator. The new algorithm gets
* this size from the xform but is (currently) always 12.
* to use a fixed 16-byte authenticator. The new algorithm use 12-byte
* authenticator.
*/
#define AUTHSIZE(sav) \
((sav->flags & SADB_X_EXT_OLD) ? 16 : (sav)->tdb_authalgxform->authsize)
((sav->flags & SADB_X_EXT_OLD) ? 16 : AH_HMAC_HASHLEN)
int ah_enable = 1; /* control flow of packets with AH */
int ah_cleartos = 1; /* clear ip_tos when doing AH calc */
@ -116,11 +116,11 @@ ah_algorithm_lookup(int alg)
case SADB_X_AALG_NULL:
return &auth_hash_null;
case SADB_AALG_MD5HMAC:
return &auth_hash_hmac_md5_96;
return &auth_hash_hmac_md5;
case SADB_AALG_SHA1HMAC:
return &auth_hash_hmac_sha1_96;
return &auth_hash_hmac_sha1;
case SADB_X_AALG_RIPEMD160HMAC:
return &auth_hash_hmac_ripemd_160_96;
return &auth_hash_hmac_ripemd_160;
case SADB_X_AALG_MD5:
return &auth_hash_key_md5;
case SADB_X_AALG_SHA:
@ -202,6 +202,7 @@ ah_init0(struct secasvar *sav, struct xformsw *xsp, struct cryptoini *cria)
cria->cri_alg = sav->tdb_authalgxform->type;
cria->cri_klen = _KEYBITS(sav->key_auth);
cria->cri_key = _KEYBUF(sav->key_auth);
cria->cri_mlen = AUTHSIZE(sav);
return 0;
}
@ -734,6 +735,8 @@ ah_input_cb(struct cryptop *crp)
caddr_t ptr;
int authsize;
NET_LOCK_GIANT();
crd = crp->crp_desc;
tc = (struct tdb_crypto *) crp->crp_opaque;
@ -764,8 +767,11 @@ ah_input_cb(struct cryptop *crp)
if (sav->tdb_cryptoid != 0)
sav->tdb_cryptoid = crp->crp_sid;
if (crp->crp_etype == EAGAIN)
return crypto_dispatch(crp);
if (crp->crp_etype == EAGAIN) {
error = crypto_dispatch(crp);
NET_UNLOCK_GIANT();
return error;
}
ahstat.ahs_noxform++;
DPRINTF(("%s: crypto error %d\n", __func__, crp->crp_etype));
@ -857,7 +863,7 @@ ah_input_cb(struct cryptop *crp)
IPSEC_COMMON_INPUT_CB(m, sav, skip, protoff, mtag);
KEY_FREESAV(&sav);
NET_UNLOCK_GIANT();
return error;
bad:
if (sav)
@ -868,6 +874,7 @@ bad:
free(tc, M_XDATA);
if (crp != NULL)
crypto_freereq(crp);
NET_UNLOCK_GIANT();
return error;
}
@ -1114,6 +1121,8 @@ ah_output_cb(struct cryptop *crp)
caddr_t ptr;
int err;
NET_LOCK_GIANT();
tc = (struct tdb_crypto *) crp->crp_opaque;
IPSEC_ASSERT(tc != NULL, ("null opaque data area!"));
skip = tc->tc_skip;
@ -1140,7 +1149,9 @@ ah_output_cb(struct cryptop *crp)
if (crp->crp_etype == EAGAIN) {
KEY_FREESAV(&sav);
IPSECREQUEST_UNLOCK(isr);
return crypto_dispatch(crp);
error = crypto_dispatch(crp);
NET_UNLOCK_GIANT();
return error;
}
ahstat.ahs_noxform++;
@ -1172,7 +1183,7 @@ ah_output_cb(struct cryptop *crp)
err = ipsec_process_done(m, isr);
KEY_FREESAV(&sav);
IPSECREQUEST_UNLOCK(isr);
NET_UNLOCK_GIANT();
return err;
bad:
if (sav)
@ -1182,6 +1193,7 @@ bad:
m_freem(m);
free(tc, M_XDATA);
crypto_freereq(crp);
NET_UNLOCK_GIANT();
return error;
}

View File

@ -329,7 +329,7 @@ esp_input(struct mbuf *m, struct secasvar *sav, int skip, int protoff)
}
/* Update the counters */
espstat.esps_ibytes += m->m_pkthdr.len - skip - hlen - alen;
espstat.esps_ibytes += m->m_pkthdr.len - (skip + hlen + alen);
/* Find out if we've already done crypto */
for (mtag = m_tag_find(m, PACKET_TAG_IPSEC_IN_CRYPTO_DONE, NULL);
@ -460,6 +460,8 @@ esp_input_cb(struct cryptop *crp)
struct secasindex *saidx;
caddr_t ptr;
NET_LOCK_GIANT();
crd = crp->crp_desc;
IPSEC_ASSERT(crd != NULL, ("null crypto descriptor!"));
@ -496,7 +498,9 @@ esp_input_cb(struct cryptop *crp)
if (crp->crp_etype == EAGAIN) {
KEY_FREESAV(&sav);
return crypto_dispatch(crp);
error = crypto_dispatch(crp);
NET_UNLOCK_GIANT();
return error;
}
espstat.esps_noxform++;
@ -524,13 +528,13 @@ esp_input_cb(struct cryptop *crp)
ahstat.ahs_hist[sav->alg_auth]++;
if (mtag == NULL) {
/* Copy the authenticator from the packet */
m_copydata(m, m->m_pkthdr.len - esph->authsize,
esph->authsize, aalg);
m_copydata(m, m->m_pkthdr.len - AH_HMAC_HASHLEN,
AH_HMAC_HASHLEN, aalg);
ptr = (caddr_t) (tc + 1);
/* Verify authenticator */
if (bcmp(ptr, aalg, esph->authsize) != 0) {
if (bcmp(ptr, aalg, AH_HMAC_HASHLEN) != 0) {
DPRINTF(("%s: "
"authentication hash mismatch for packet in SA %s/%08lx\n",
__func__,
@ -543,7 +547,7 @@ esp_input_cb(struct cryptop *crp)
}
/* Remove trailing authenticator */
m_adj(m, -(esph->authsize));
m_adj(m, -AH_HMAC_HASHLEN);
}
/* Release the crypto descriptors */
@ -625,6 +629,7 @@ esp_input_cb(struct cryptop *crp)
IPSEC_COMMON_INPUT_CB(m, sav, skip, protoff, mtag);
KEY_FREESAV(&sav);
NET_UNLOCK_GIANT();
return error;
bad:
if (sav)
@ -635,6 +640,7 @@ bad:
free(tc, M_XDATA);
if (crp != NULL)
crypto_freereq(crp);
NET_UNLOCK_GIANT();
return error;
}
@ -881,6 +887,8 @@ esp_output_cb(struct cryptop *crp)
struct mbuf *m;
int err, error;
NET_LOCK_GIANT();
tc = (struct tdb_crypto *) crp->crp_opaque;
IPSEC_ASSERT(tc != NULL, ("null opaque data area!"));
m = (struct mbuf *) crp->crp_buf;
@ -908,7 +916,9 @@ esp_output_cb(struct cryptop *crp)
if (crp->crp_etype == EAGAIN) {
KEY_FREESAV(&sav);
IPSECREQUEST_UNLOCK(isr);
return crypto_dispatch(crp);
error = crypto_dispatch(crp);
NET_UNLOCK_GIANT();
return error;
}
espstat.esps_noxform++;
@ -936,7 +946,7 @@ esp_output_cb(struct cryptop *crp)
err = ipsec_process_done(m, isr);
KEY_FREESAV(&sav);
IPSECREQUEST_UNLOCK(isr);
NET_UNLOCK_GIANT();
return err;
bad:
if (sav)
@ -946,6 +956,7 @@ bad:
m_freem(m);
free(tc, M_XDATA);
crypto_freereq(crp);
NET_UNLOCK_GIANT();
return error;
}

View File

@ -219,6 +219,8 @@ ipcomp_input_cb(struct cryptop *crp)
u_int8_t nproto;
caddr_t addr;
NET_LOCK_GIANT();
crd = crp->crp_desc;
tc = (struct tdb_crypto *) crp->crp_opaque;
@ -249,7 +251,9 @@ ipcomp_input_cb(struct cryptop *crp)
if (crp->crp_etype == EAGAIN) {
KEY_FREESAV(&sav);
return crypto_dispatch(crp);
error = crypto_dispatch(crp);
NET_UNLOCK_GIANT();
return error;
}
ipcompstat.ipcomps_noxform++;
@ -302,6 +306,7 @@ ipcomp_input_cb(struct cryptop *crp)
IPSEC_COMMON_INPUT_CB(m, sav, skip, protoff, NULL);
KEY_FREESAV(&sav);
NET_UNLOCK_GIANT();
return error;
bad:
if (sav)
@ -312,6 +317,7 @@ bad:
free(tc, M_XDATA);
if (crp)
crypto_freereq(crp);
NET_UNLOCK_GIANT();
return error;
}
@ -493,6 +499,8 @@ ipcomp_output_cb(struct cryptop *crp)
struct mbuf *m;
int error, skip, rlen;
NET_LOCK_GIANT();
tc = (struct tdb_crypto *) crp->crp_opaque;
IPSEC_ASSERT(tc != NULL, ("null opaque data area!"));
m = (struct mbuf *) crp->crp_buf;
@ -519,7 +527,9 @@ ipcomp_output_cb(struct cryptop *crp)
if (crp->crp_etype == EAGAIN) {
KEY_FREESAV(&sav);
IPSECREQUEST_UNLOCK(isr);
return crypto_dispatch(crp);
error = crypto_dispatch(crp);
NET_UNLOCK_GIANT();
return error;
}
ipcompstat.ipcomps_noxform++;
DPRINTF(("%s: crypto error %d\n", __func__, crp->crp_etype));
@ -572,7 +582,7 @@ ipcomp_output_cb(struct cryptop *crp)
error = ipsec_process_done(m, isr);
KEY_FREESAV(&sav);
IPSECREQUEST_UNLOCK(isr);
NET_UNLOCK_GIANT();
return error;
bad:
if (sav)
@ -582,6 +592,7 @@ bad:
m_freem(m);
free(tc, M_XDATA);
crypto_freereq(crp);
NET_UNLOCK_GIANT();
return error;
}