mirror of
https://git.rtems.org/rtems-libbsd/
synced 2025-10-14 08:44:27 +08:00
Update to FreeBSD 8.4
This commit is contained in:
@@ -123,7 +123,7 @@ struct ipsecrequest {
|
||||
|
||||
struct secasvar *sav; /* place holder of SA for use */
|
||||
struct secpolicy *sp; /* back pointer to SP */
|
||||
struct mtx lock; /* to interlock updates */
|
||||
struct rwlock lock; /* to interlock updates */
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -132,11 +132,15 @@ struct ipsecrequest {
|
||||
* hard it is to remove this...
|
||||
*/
|
||||
#define IPSECREQUEST_LOCK_INIT(_isr) \
|
||||
mtx_init(&(_isr)->lock, "ipsec request", NULL, MTX_DEF | MTX_RECURSE)
|
||||
#define IPSECREQUEST_LOCK(_isr) mtx_lock(&(_isr)->lock)
|
||||
#define IPSECREQUEST_UNLOCK(_isr) mtx_unlock(&(_isr)->lock)
|
||||
#define IPSECREQUEST_LOCK_DESTROY(_isr) mtx_destroy(&(_isr)->lock)
|
||||
#define IPSECREQUEST_LOCK_ASSERT(_isr) mtx_assert(&(_isr)->lock, MA_OWNED)
|
||||
rw_init_flags(&(_isr)->lock, "ipsec request", RW_RECURSE)
|
||||
#define IPSECREQUEST_LOCK(_isr) rw_rlock(&(_isr)->lock)
|
||||
#define IPSECREQUEST_UNLOCK(_isr) rw_runlock(&(_isr)->lock)
|
||||
#define IPSECREQUEST_WLOCK(_isr) rw_wlock(&(_isr)->lock)
|
||||
#define IPSECREQUEST_WUNLOCK(_isr) rw_wunlock(&(_isr)->lock)
|
||||
#define IPSECREQUEST_UPGRADE(_isr) rw_try_upgrade(&(_isr)->lock)
|
||||
#define IPSECREQUEST_DOWNGRADE(_isr) rw_downgrade(&(_isr)->lock)
|
||||
#define IPSECREQUEST_LOCK_DESTROY(_isr) rw_destroy(&(_isr)->lock)
|
||||
#define IPSECREQUEST_LOCK_ASSERT(_isr) rw_assert(&(_isr)->lock, RA_LOCKED)
|
||||
|
||||
/* security policy in PCB */
|
||||
struct inpcbpolicy {
|
||||
|
@@ -249,7 +249,6 @@ ipsec_process_done(struct mbuf *m, struct ipsecrequest *isr)
|
||||
panic("ipsec_process_done");
|
||||
bad:
|
||||
m_freem(m);
|
||||
KEY_FREESAV(&sav);
|
||||
return (error);
|
||||
}
|
||||
|
||||
@@ -846,7 +845,7 @@ ipsec6_output_tunnel(struct ipsec_output_state *state, struct secpolicy *sp, int
|
||||
dst6->sin6_family = AF_INET6;
|
||||
dst6->sin6_len = sizeof(*dst6);
|
||||
dst6->sin6_addr = ip6->ip6_dst;
|
||||
rtalloc(state->ro);
|
||||
rtalloc_ign_fib(state->ro, 0UL, M_GETFIB(m));
|
||||
}
|
||||
if (state->ro->ro_rt == NULL) {
|
||||
V_ip6stat.ip6s_noroute++;
|
||||
|
@@ -811,6 +811,7 @@ key_checkrequest(struct ipsecrequest *isr, const struct secasindex *saidx)
|
||||
{
|
||||
u_int level;
|
||||
int error;
|
||||
struct secasvar *sav;
|
||||
|
||||
IPSEC_ASSERT(isr != NULL, ("null isr"));
|
||||
IPSEC_ASSERT(saidx != NULL, ("null saidx"));
|
||||
@@ -828,45 +829,31 @@ key_checkrequest(struct ipsecrequest *isr, const struct secasindex *saidx)
|
||||
|
||||
/* get current level */
|
||||
level = ipsec_get_reqlevel(isr);
|
||||
#if 0
|
||||
|
||||
/*
|
||||
* We do allocate new SA only if the state of SA in the holder is
|
||||
* SADB_SASTATE_DEAD. The SA for outbound must be the oldest.
|
||||
*/
|
||||
if (isr->sav != NULL) {
|
||||
if (isr->sav->sah == NULL)
|
||||
panic("%s: sah is null.\n", __func__);
|
||||
if (isr->sav == (struct secasvar *)LIST_FIRST(
|
||||
&isr->sav->sah->savtree[SADB_SASTATE_DEAD])) {
|
||||
KEY_FREESAV(&isr->sav);
|
||||
isr->sav = NULL;
|
||||
}
|
||||
}
|
||||
#else
|
||||
/*
|
||||
* we free any SA stashed in the IPsec request because a different
|
||||
* We check new SA in the IPsec request because a different
|
||||
* SA may be involved each time this request is checked, either
|
||||
* because new SAs are being configured, or this request is
|
||||
* associated with an unconnected datagram socket, or this request
|
||||
* is associated with a system default policy.
|
||||
*
|
||||
* The operation may have negative impact to performance. We may
|
||||
* want to check cached SA carefully, rather than picking new SA
|
||||
* every time.
|
||||
*/
|
||||
if (isr->sav != NULL) {
|
||||
KEY_FREESAV(&isr->sav);
|
||||
isr->sav = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* new SA allocation if no SA found.
|
||||
* key_allocsa_policy should allocate the oldest SA available.
|
||||
* See key_do_allocsa_policy(), and draft-jenkins-ipsec-rekeying-03.txt.
|
||||
*/
|
||||
if (isr->sav == NULL)
|
||||
isr->sav = key_allocsa_policy(saidx);
|
||||
sav = key_allocsa_policy(saidx);
|
||||
if (sav != isr->sav) {
|
||||
/* SA need to be updated. */
|
||||
if (!IPSECREQUEST_UPGRADE(isr)) {
|
||||
/* Kick everyone off. */
|
||||
IPSECREQUEST_UNLOCK(isr);
|
||||
IPSECREQUEST_WLOCK(isr);
|
||||
}
|
||||
if (isr->sav != NULL)
|
||||
KEY_FREESAV(&isr->sav);
|
||||
isr->sav = sav;
|
||||
IPSECREQUEST_DOWNGRADE(isr);
|
||||
} else if (sav != NULL)
|
||||
KEY_FREESAV(&sav);
|
||||
|
||||
/* When there is SA. */
|
||||
if (isr->sav != NULL) {
|
||||
@@ -1241,6 +1228,16 @@ key_freesp_so(struct secpolicy **sp)
|
||||
KEY_FREESP(sp);
|
||||
}
|
||||
|
||||
void
|
||||
key_addrefsa(struct secasvar *sav, const char* where, int tag)
|
||||
{
|
||||
|
||||
IPSEC_ASSERT(sav != NULL, ("null sav"));
|
||||
IPSEC_ASSERT(sav->refcnt > 0, ("refcount must exist"));
|
||||
|
||||
sa_addref(sav);
|
||||
}
|
||||
|
||||
/*
|
||||
* Must be called after calling key_allocsa().
|
||||
* This function is called by key_freesp() to free some SA allocated
|
||||
@@ -1768,6 +1765,7 @@ key_gather_mbuf(m, mhp, ndeep, nitem, va_alist)
|
||||
|
||||
fail:
|
||||
m_freem(result);
|
||||
va_end(ap);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -2297,6 +2295,7 @@ key_spdget(so, m, mhp)
|
||||
}
|
||||
|
||||
n = key_setdumpsp(sp, SADB_X_SPDGET, 0, mhp->msg->sadb_msg_pid);
|
||||
KEY_FREESP(&sp);
|
||||
if (n != NULL) {
|
||||
m_freem(m);
|
||||
return key_sendup_mbuf(so, n, KEY_SENDUP_ONE);
|
||||
@@ -2870,9 +2869,10 @@ key_newsav(m, mhp, sah, errp, where, tag)
|
||||
sa_initref(newsav);
|
||||
newsav->state = SADB_SASTATE_LARVAL;
|
||||
|
||||
/* XXX locking??? */
|
||||
SAHTREE_LOCK();
|
||||
LIST_INSERT_TAIL(&sah->savtree[SADB_SASTATE_LARVAL], newsav,
|
||||
secasvar, chain);
|
||||
SAHTREE_UNLOCK();
|
||||
done:
|
||||
KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
|
||||
printf("DP %s from %s:%u return SP:%p\n", __func__,
|
||||
@@ -5716,8 +5716,8 @@ key_delete(so, m, mhp)
|
||||
}
|
||||
|
||||
key_sa_chgstate(sav, SADB_SASTATE_DEAD);
|
||||
SAHTREE_UNLOCK();
|
||||
KEY_FREESAV(&sav);
|
||||
SAHTREE_UNLOCK();
|
||||
|
||||
{
|
||||
struct mbuf *n;
|
||||
@@ -6105,6 +6105,9 @@ key_getsizes_ah(
|
||||
case SADB_X_AALG_MD5: *min = *max = 16; break;
|
||||
case SADB_X_AALG_SHA: *min = *max = 20; break;
|
||||
case SADB_X_AALG_NULL: *min = 1; *max = 256; break;
|
||||
case SADB_X_AALG_SHA2_256: *min = *max = 32; break;
|
||||
case SADB_X_AALG_SHA2_384: *min = *max = 48; break;
|
||||
case SADB_X_AALG_SHA2_512: *min = *max = 64; break;
|
||||
default:
|
||||
DPRINTF(("%s: unknown AH algorithm %u\n",
|
||||
__func__, alg));
|
||||
@@ -6130,7 +6133,11 @@ key_getcomb_ah()
|
||||
for (i = 1; i <= SADB_AALG_MAX; i++) {
|
||||
#if 1
|
||||
/* we prefer HMAC algorithms, not old algorithms */
|
||||
if (i != SADB_AALG_SHA1HMAC && i != SADB_AALG_MD5HMAC)
|
||||
if (i != SADB_AALG_SHA1HMAC &&
|
||||
i != SADB_AALG_MD5HMAC &&
|
||||
i != SADB_X_AALG_SHA2_256 &&
|
||||
i != SADB_X_AALG_SHA2_384 &&
|
||||
i != SADB_X_AALG_SHA2_512)
|
||||
continue;
|
||||
#endif
|
||||
algo = ah_algorithm_lookup(i);
|
||||
|
@@ -76,10 +76,13 @@ extern void _key_freesp(struct secpolicy **, const char*, int);
|
||||
|
||||
extern struct secasvar *key_allocsa(union sockaddr_union *, u_int, u_int32_t,
|
||||
const char*, int);
|
||||
extern void key_addrefsa(struct secasvar *, const char*, int);
|
||||
extern void key_freesav(struct secasvar **, const char*, int);
|
||||
|
||||
#define KEY_ALLOCSA(dst, proto, spi) \
|
||||
key_allocsa(dst, proto, spi, __FILE__, __LINE__)
|
||||
#define KEY_ADDREFSA(sav) \
|
||||
key_addrefsa(sav, __FILE__, __LINE__)
|
||||
#define KEY_FREESAV(psav) \
|
||||
key_freesav(psav, __FILE__, __LINE__)
|
||||
|
||||
|
@@ -46,6 +46,7 @@
|
||||
#include <opencrypto/xform.h>
|
||||
|
||||
#define AH_HMAC_HASHLEN 12 /* 96 bits of authenticator */
|
||||
#define AH_HMAC_MAXHASHLEN (SHA2_512_HASH_LEN/2) /* Keep this updated */
|
||||
#define AH_HMAC_INITIAL_RPL 1 /* replay counter initial value */
|
||||
|
||||
/*
|
||||
@@ -74,6 +75,7 @@ struct tdb_crypto {
|
||||
int tc_protoff; /* current protocol offset */
|
||||
int tc_skip; /* data offset */
|
||||
caddr_t tc_ptr; /* associated crypto data */
|
||||
struct secasvar *tc_sav; /* related SA */
|
||||
};
|
||||
|
||||
struct secasvar;
|
||||
|
@@ -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;
|
||||
|
@@ -299,7 +299,19 @@ esp_input(struct mbuf *m, struct secasvar *sav, int skip, int protoff)
|
||||
else
|
||||
hlen = sizeof (struct newesp) + sav->ivlen;
|
||||
/* Authenticator hash size */
|
||||
alen = esph ? AH_HMAC_HASHLEN : 0;
|
||||
if (esph != NULL) {
|
||||
switch (esph->type) {
|
||||
case CRYPTO_SHA2_256_HMAC:
|
||||
case CRYPTO_SHA2_384_HMAC:
|
||||
case CRYPTO_SHA2_512_HMAC:
|
||||
alen = esph->hashsize/2;
|
||||
break;
|
||||
default:
|
||||
alen = AH_HMAC_HASHLEN;
|
||||
break;
|
||||
}
|
||||
}else
|
||||
alen = 0;
|
||||
|
||||
/*
|
||||
* Verify payload length is multiple of encryption algorithm
|
||||
@@ -413,6 +425,8 @@ esp_input(struct mbuf *m, struct secasvar *sav, int skip, int protoff)
|
||||
tc->tc_proto = sav->sah->saidx.proto;
|
||||
tc->tc_protoff = protoff;
|
||||
tc->tc_skip = skip;
|
||||
KEY_ADDREFSA(sav);
|
||||
tc->tc_sav = sav;
|
||||
|
||||
/* Decryption descriptor */
|
||||
if (espx) {
|
||||
@@ -452,8 +466,8 @@ esp_input(struct mbuf *m, struct secasvar *sav, int skip, int protoff)
|
||||
static int
|
||||
esp_input_cb(struct cryptop *crp)
|
||||
{
|
||||
u_int8_t lastthree[3], aalg[AH_HMAC_HASHLEN];
|
||||
int hlen, skip, protoff, error;
|
||||
u_int8_t lastthree[3], aalg[AH_HMAC_MAXHASHLEN];
|
||||
int hlen, skip, protoff, error, alen;
|
||||
struct mbuf *m;
|
||||
struct cryptodesc *crd;
|
||||
struct auth_hash *esph;
|
||||
@@ -474,15 +488,8 @@ esp_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_espstat.esps_notdb++;
|
||||
DPRINTF(("%s: SA gone during crypto (SA %s/%08lx proto %u)\n",
|
||||
__func__, ipsec_address(&tc->tc_dst),
|
||||
(u_long) ntohl(tc->tc_spi), tc->tc_proto));
|
||||
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 ||
|
||||
@@ -499,7 +506,6 @@ esp_input_cb(struct cryptop *crp)
|
||||
sav->tdb_cryptoid = crp->crp_sid;
|
||||
|
||||
if (crp->crp_etype == EAGAIN) {
|
||||
KEY_FREESAV(&sav);
|
||||
error = crypto_dispatch(crp);
|
||||
return error;
|
||||
}
|
||||
@@ -521,6 +527,16 @@ esp_input_cb(struct cryptop *crp)
|
||||
|
||||
/* If authentication was performed, check now. */
|
||||
if (esph != NULL) {
|
||||
switch (esph->type) {
|
||||
case CRYPTO_SHA2_256_HMAC:
|
||||
case CRYPTO_SHA2_384_HMAC:
|
||||
case CRYPTO_SHA2_512_HMAC:
|
||||
alen = esph->hashsize/2;
|
||||
break;
|
||||
default:
|
||||
alen = AH_HMAC_HASHLEN;
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* If we have a tag, it means an IPsec-aware NIC did
|
||||
* the verification for us. Otherwise we need to
|
||||
@@ -529,13 +545,13 @@ esp_input_cb(struct cryptop *crp)
|
||||
V_ahstat.ahs_hist[sav->alg_auth]++;
|
||||
if (mtag == NULL) {
|
||||
/* Copy the authenticator from the packet */
|
||||
m_copydata(m, m->m_pkthdr.len - AH_HMAC_HASHLEN,
|
||||
AH_HMAC_HASHLEN, aalg);
|
||||
m_copydata(m, m->m_pkthdr.len - alen,
|
||||
alen, aalg);
|
||||
|
||||
ptr = (caddr_t) (tc + 1);
|
||||
|
||||
/* Verify authenticator */
|
||||
if (bcmp(ptr, aalg, AH_HMAC_HASHLEN) != 0) {
|
||||
if (bcmp(ptr, aalg, alen) != 0) {
|
||||
DPRINTF(("%s: "
|
||||
"authentication hash mismatch for packet in SA %s/%08lx\n",
|
||||
__func__,
|
||||
@@ -548,7 +564,7 @@ esp_input_cb(struct cryptop *crp)
|
||||
}
|
||||
|
||||
/* Remove trailing authenticator */
|
||||
m_adj(m, -AH_HMAC_HASHLEN);
|
||||
m_adj(m, -alen);
|
||||
}
|
||||
|
||||
/* Release the crypto descriptors */
|
||||
@@ -692,7 +708,16 @@ esp_output(
|
||||
plen = rlen + padding; /* Padded payload length. */
|
||||
|
||||
if (esph)
|
||||
switch (esph->type) {
|
||||
case CRYPTO_SHA2_256_HMAC:
|
||||
case CRYPTO_SHA2_384_HMAC:
|
||||
case CRYPTO_SHA2_512_HMAC:
|
||||
alen = esph->hashsize/2;
|
||||
break;
|
||||
default:
|
||||
alen = AH_HMAC_HASHLEN;
|
||||
break;
|
||||
}
|
||||
else
|
||||
alen = 0;
|
||||
|
||||
@@ -848,6 +873,8 @@ esp_output(
|
||||
|
||||
/* Callback parameters */
|
||||
tc->tc_isr = isr;
|
||||
KEY_ADDREFSA(sav);
|
||||
tc->tc_sav = sav;
|
||||
tc->tc_spi = sav->spi;
|
||||
tc->tc_dst = saidx->dst;
|
||||
tc->tc_proto = saidx->proto;
|
||||
@@ -897,8 +924,9 @@ esp_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_espstat.esps_notdb++;
|
||||
DPRINTF(("%s: SA gone during crypto (SA %s/%08lx proto %u)\n",
|
||||
__func__, ipsec_address(&tc->tc_dst),
|
||||
@@ -906,8 +934,6 @@ esp_output_cb(struct cryptop *crp)
|
||||
error = ENOBUFS; /*XXX*/
|
||||
goto bad;
|
||||
}
|
||||
IPSEC_ASSERT(isr->sav == sav,
|
||||
("SA changed was %p now %p\n", isr->sav, sav));
|
||||
|
||||
/* Check for crypto errors. */
|
||||
if (crp->crp_etype) {
|
||||
@@ -916,7 +942,6 @@ esp_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;
|
||||
@@ -946,7 +971,7 @@ esp_output_cb(struct cryptop *crp)
|
||||
#ifdef REGRESSION
|
||||
/* Emulate man-in-the-middle attack when ipsec_integrity is TRUE. */
|
||||
if (V_ipsec_integrity) {
|
||||
static unsigned char ipseczeroes[AH_HMAC_HASHLEN];
|
||||
static unsigned char ipseczeroes[AH_HMAC_MAXHASHLEN];
|
||||
struct auth_hash *esph;
|
||||
|
||||
/*
|
||||
@@ -955,8 +980,20 @@ esp_output_cb(struct cryptop *crp)
|
||||
*/
|
||||
esph = sav->tdb_authalgxform;
|
||||
if (esph != NULL) {
|
||||
m_copyback(m, m->m_pkthdr.len - AH_HMAC_HASHLEN,
|
||||
AH_HMAC_HASHLEN, ipseczeroes);
|
||||
int alen;
|
||||
|
||||
switch (esph->type) {
|
||||
case CRYPTO_SHA2_256_HMAC:
|
||||
case CRYPTO_SHA2_384_HMAC:
|
||||
case CRYPTO_SHA2_512_HMAC:
|
||||
alen = esph->hashsize/2;
|
||||
break;
|
||||
default:
|
||||
alen = AH_HMAC_HASHLEN;
|
||||
break;
|
||||
}
|
||||
m_copyback(m, m->m_pkthdr.len - alen,
|
||||
alen, ipseczeroes);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@@ -39,6 +39,7 @@
|
||||
#include <sys/mbuf.h>
|
||||
#include <rtems/bsd/sys/lock.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/rwlock.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/protosw.h>
|
||||
@@ -143,8 +144,29 @@ ipcomp_input(struct mbuf *m, struct secasvar *sav, int skip, int protoff)
|
||||
struct tdb_crypto *tc;
|
||||
struct cryptodesc *crdc;
|
||||
struct cryptop *crp;
|
||||
struct ipcomp *ipcomp;
|
||||
caddr_t addr;
|
||||
int hlen = IPCOMP_HLENGTH;
|
||||
|
||||
/*
|
||||
* Check that the next header of the IPComp is not IPComp again, before
|
||||
* doing any real work. Given it is not possible to do double
|
||||
* compression it means someone is playing tricks on us.
|
||||
*/
|
||||
if (m->m_len < skip + hlen && (m = m_pullup(m, skip + hlen)) == NULL) {
|
||||
V_ipcompstat.ipcomps_hdrops++; /*XXX*/
|
||||
DPRINTF(("%s: m_pullup failed\n", __func__));
|
||||
return (ENOBUFS);
|
||||
}
|
||||
addr = (caddr_t) mtod(m, struct ip *) + skip;
|
||||
ipcomp = (struct ipcomp *)addr;
|
||||
if (ipcomp->comp_nxt == IPPROTO_IPCOMP) {
|
||||
m_freem(m);
|
||||
V_ipcompstat.ipcomps_pdrops++; /* XXX have our own stats? */
|
||||
DPRINTF(("%s: recursive compression detected\n", __func__));
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
/* Get crypto descriptors */
|
||||
crp = crypto_getreq(1);
|
||||
if (crp == NULL) {
|
||||
@@ -187,6 +209,8 @@ ipcomp_input(struct mbuf *m, struct secasvar *sav, int skip, int protoff)
|
||||
tc->tc_proto = sav->sah->saidx.proto;
|
||||
tc->tc_protoff = protoff;
|
||||
tc->tc_skip = skip;
|
||||
KEY_ADDREFSA(sav);
|
||||
tc->tc_sav = sav;
|
||||
|
||||
return crypto_dispatch(crp);
|
||||
}
|
||||
@@ -230,13 +254,8 @@ ipcomp_input_cb(struct cryptop *crp)
|
||||
mtag = (struct mtag *) 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_ipcompstat.ipcomps_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 ||
|
||||
@@ -250,7 +269,6 @@ ipcomp_input_cb(struct cryptop *crp)
|
||||
sav->tdb_cryptoid = crp->crp_sid;
|
||||
|
||||
if (crp->crp_etype == EAGAIN) {
|
||||
KEY_FREESAV(&sav);
|
||||
return crypto_dispatch(crp);
|
||||
}
|
||||
V_ipcompstat.ipcomps_noxform++;
|
||||
@@ -433,6 +451,8 @@ ipcomp_output(
|
||||
}
|
||||
|
||||
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;
|
||||
@@ -473,14 +493,14 @@ ipcomp_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_ipcompstat.ipcomps_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) {
|
||||
@@ -489,7 +509,6 @@ ipcomp_output_cb(struct cryptop *crp)
|
||||
sav->tdb_cryptoid = crp->crp_sid;
|
||||
|
||||
if (crp->crp_etype == EAGAIN) {
|
||||
KEY_FREESAV(&sav);
|
||||
IPSECREQUEST_UNLOCK(isr);
|
||||
return crypto_dispatch(crp);
|
||||
}
|
||||
|
Reference in New Issue
Block a user