Page MenuHomeFreeBSD

D22445.id.diff
No OneTemporary

D22445.id.diff

Index: lib/libipsec/pfkey.c
===================================================================
--- lib/libipsec/pfkey.c
+++ lib/libipsec/pfkey.c
@@ -1825,6 +1825,7 @@
case SADB_X_EXT_SA_REPLAY:
case SADB_X_EXT_NEW_ADDRESS_SRC:
case SADB_X_EXT_NEW_ADDRESS_DST:
+ case SADB_X_EXT_SA_TFC_LENGTH:
mhp[ext->sadb_ext_type] = (caddr_t)ext;
break;
default:
Index: lib/libipsec/pfkey_dump.c
===================================================================
--- lib/libipsec/pfkey_dump.c
+++ lib/libipsec/pfkey_dump.c
@@ -205,6 +205,7 @@
struct sadb_ident *m_sid, *m_did;
struct sadb_sens *m_sens;
struct sadb_x_sa_replay *m_sa_replay;
+ struct sadb_x_sa_tfc_length *m_sa_tfc_length;
struct sadb_x_nat_t_type *natt_type;
struct sadb_x_nat_t_port *natt_sport, *natt_dport;
struct sadb_address *natt_oai, *natt_oar;
@@ -233,6 +234,7 @@
m_did = (struct sadb_ident *)mhp[SADB_EXT_IDENTITY_DST];
m_sens = (struct sadb_sens *)mhp[SADB_EXT_SENSITIVITY];
m_sa_replay = (struct sadb_x_sa_replay *)mhp[SADB_X_EXT_SA_REPLAY];
+ m_sa_tfc_length = (struct sadb_x_sa_tfc_length *)mhp[SADB_X_EXT_SA_TFC_LENGTH];
natt_type = (struct sadb_x_nat_t_type *)mhp[SADB_X_EXT_NAT_T_TYPE];
natt_sport = (struct sadb_x_nat_t_port *)mhp[SADB_X_EXT_NAT_T_SPORT];
natt_dport = (struct sadb_x_nat_t_port *)mhp[SADB_X_EXT_NAT_T_DPORT];
@@ -325,6 +327,10 @@
m_sa->sadb_sa_replay,
m_sa->sadb_sa_flags);
+ /* tfc padding length */
+ printf("tfcpadding=%d ", m_sa_tfc_length ?
+ m_sa_tfc_length->sadb_x_sa_tfc_length_length : 0);
+
/* state */
printf("state=");
GETMSGSTR(str_state, m_sa->sadb_sa_state);
Index: sys/net/pfkeyv2.h
===================================================================
--- sys/net/pfkeyv2.h
+++ sys/net/pfkeyv2.h
@@ -297,6 +297,14 @@
};
_Static_assert(sizeof(struct sadb_x_sa_replay) == 8, "struct size mismatch");
+/* TFC padding length */
+struct sadb_x_sa_tfc_length {
+ u_int16_t sadb_x_sa_tfc_length_len;
+ u_int16_t sadb_x_sa_tfc_length_exttype;
+ int32_t sadb_x_sa_tfc_length_length;
+};
+_Static_assert(sizeof(struct sadb_x_sa_tfc_length) == 8, "struct size mismatch");
+
#define SADB_EXT_RESERVED 0
#define SADB_EXT_SA 1
#define SADB_EXT_LIFETIME_CURRENT 2
@@ -327,7 +335,8 @@
#define SADB_X_EXT_SA_REPLAY 26 /* Replay window override. */
#define SADB_X_EXT_NEW_ADDRESS_SRC 27
#define SADB_X_EXT_NEW_ADDRESS_DST 28
-#define SADB_EXT_MAX 28
+#define SADB_X_EXT_SA_TFC_LENGTH 29
+#define SADB_EXT_MAX 29
#define SADB_SATYPE_UNSPEC 0
#define SADB_SATYPE_AH 2
Index: sys/netipsec/ipsec_mbuf.c
===================================================================
--- sys/netipsec/ipsec_mbuf.c
+++ sys/netipsec/ipsec_mbuf.c
@@ -215,7 +215,15 @@
if (pad > M_TRAILINGSPACE(m0)) {
/* Add an mbuf to the chain. */
- MGET(m1, M_NOWAIT, MT_DATA);
+ if (pad > MCLBYTES) {
+ m_freem(m0);
+ DPRINTF(("%s: padding is too big (%d, max %d)\n", __func__, pad, MCLBYTES));
+ return NULL;
+ }
+ if (pad > MHLEN)
+ m1 = m_getcl(M_NOWAIT, MT_DATA, 0);
+ else
+ MGET(m1, M_NOWAIT, MT_DATA);
if (m1 == NULL) {
m_freem(m0);
DPRINTF(("%s: unable to get extra mbuf\n", __func__));
Index: sys/netipsec/key.c
===================================================================
--- sys/netipsec/key.c
+++ sys/netipsec/key.c
@@ -385,6 +385,7 @@
sizeof(struct sadb_x_sa_replay), /* SADB_X_EXT_SA_REPLAY */
sizeof(struct sadb_address), /* SADB_X_EXT_NEW_ADDRESS_SRC */
sizeof(struct sadb_address), /* SADB_X_EXT_NEW_ADDRESS_DST */
+ sizeof(struct sadb_x_sa_tfc_length),/* SADB_X_EXT_SA_TFC_LENGTH */
};
_Static_assert(sizeof(minsize)/sizeof(int) == SADB_EXT_MAX + 1, "minsize size mismatch");
@@ -418,6 +419,7 @@
sizeof(struct sadb_x_sa_replay), /* SADB_X_EXT_SA_REPLAY */
0, /* SADB_X_EXT_NEW_ADDRESS_SRC */
0, /* SADB_X_EXT_NEW_ADDRESS_DST */
+ sizeof(struct sadb_x_sa_tfc_length),/* SADB_X_EXT_SA_TFC_LENGTH */
};
_Static_assert(sizeof(maxsize)/sizeof(int) == SADB_EXT_MAX + 1, "minsize size mismatch");
@@ -666,6 +668,7 @@
static struct mbuf *key_setsadbxtype(u_int16_t);
static struct mbuf *key_setsadbxsa2(u_int8_t, u_int32_t, u_int32_t);
static struct mbuf *key_setsadbxsareplay(u_int32_t);
+static struct mbuf *key_setsadbxsatfclength(int32_t);
static struct mbuf *key_setsadbxpolicy(u_int16_t, u_int8_t,
u_int32_t, u_int32_t);
static struct seckey *key_dup_keymsg(const struct sadb_key *, size_t,
@@ -3377,6 +3380,45 @@
}
}
+ /* TFC padding */
+ sav->tfc = 0;
+ if (!SADB_CHECKHDR(mhp, SADB_X_EXT_SA_TFC_LENGTH)) {
+ int maxpacketsize;
+ if (SADB_CHECKLEN(mhp, SADB_X_EXT_SA_TFC_LENGTH)) {
+ error = EINVAL;
+ goto fail;
+ }
+ error = 0;
+ sav->tfc = ((const struct sadb_x_sa_tfc_length*)
+ mhp->ext[SADB_X_EXT_SA_TFC_LENGTH])->sadb_x_sa_tfc_length_length;
+ switch (sav->sah->saidx.dst.sa.sa_family)
+ {
+#ifdef INET
+ case AF_INET:
+ maxpacketsize = IP_MAXPACKET;
+ break;
+#endif /* INET */
+#ifdef INET6
+ case AF_INET6:
+ maxpacketsize = IPV6_MAXPACKET;
+ break;
+#endif /* INET6 */
+ default:
+ DPRINTF(("%s: unknown/unsupported protocol "
+ "family %d, SA %s/%08lx\n", __func__,
+ saidx->dst.sa.sa_family, ipsec_address(&saidx->dst,
+ buf, sizeof(buf)), (u_long) ntohl(sav->spi)));
+ error = EPFNOSUPPORT;
+ goto fail;
+ }
+ if (sav->tfc > maxpacketsize) {
+ ipseclog((LOG_DEBUG, "%s: invalid tfc value.\n",
+ __func__));
+ error = EINVAL;
+ goto fail;
+ }
+ }
+
/* Authentication keys */
if (!SADB_CHECKHDR(mhp, SADB_EXT_KEY_AUTH)) {
if (SADB_CHECKLEN(mhp, SADB_EXT_KEY_AUTH)) {
@@ -3560,7 +3602,7 @@
SADB_X_EXT_NAT_T_TYPE,
SADB_X_EXT_NAT_T_SPORT, SADB_X_EXT_NAT_T_DPORT,
SADB_X_EXT_NAT_T_OAI, SADB_X_EXT_NAT_T_OAR,
- SADB_X_EXT_NAT_T_FRAG,
+ SADB_X_EXT_NAT_T_FRAG, SADB_X_EXT_SA_TFC_LENGTH,
};
uint32_t replay_count;
@@ -3598,6 +3640,15 @@
goto fail;
break;
+ case SADB_X_EXT_SA_TFC_LENGTH:
+ if (sav->tfc <= 0)
+ continue;
+
+ m = key_setsadbxsatfclength(sav->tfc);
+ if (!m)
+ goto fail;
+ break;
+
case SADB_EXT_ADDRESS_SRC:
m = key_setsadbaddr(SADB_EXT_ADDRESS_SRC,
&sav->sah->saidx.src.sa,
@@ -3921,6 +3972,32 @@
return m;
}
+/*
+ * Set data into sadb_x_sa_tfc_length
+ */
+static struct mbuf *
+key_setsadbxsatfclength(int32_t tfc_length)
+{
+ struct mbuf *m;
+ struct sadb_x_sa_tfc_length *p;
+ size_t len;
+
+ len = PFKEY_ALIGN8(sizeof(struct sadb_x_sa_tfc_length));
+ m = m_get2(len, M_NOWAIT, MT_DATA, 0);
+ if (m == NULL)
+ return (NULL);
+ m_align(m, len);
+ m->m_len = len;
+ p = mtod(m, struct sadb_x_sa_tfc_length *);
+
+ bzero(p, len);
+ p->sadb_x_sa_tfc_length_len = PFKEY_UNIT64(len);
+ p->sadb_x_sa_tfc_length_exttype = SADB_X_EXT_SA_TFC_LENGTH;
+ p->sadb_x_sa_tfc_length_length = tfc_length;
+
+ return m;
+}
+
/*
* Set a type in sadb_x_nat_t_type.
*/
@@ -5840,6 +5917,14 @@
}
sav->natt->cksum = cksum;
}
+
+ if (sav->tfc > 0) {
+ if (sav->tfc > sizeof(struct ip) + sizeof(struct udphdr))
+ sav->tfc -= sizeof(struct ip) + sizeof(struct udphdr);
+ else
+ sav->tfc = 0;
+ }
+
return (0);
}
@@ -8069,6 +8154,7 @@
case SADB_X_EXT_SA_REPLAY:
case SADB_X_EXT_NEW_ADDRESS_SRC:
case SADB_X_EXT_NEW_ADDRESS_DST:
+ case SADB_X_EXT_SA_TFC_LENGTH:
/* duplicate check */
/*
* XXX Are there duplication payloads of either
Index: sys/netipsec/key_debug.c
===================================================================
--- sys/netipsec/key_debug.c
+++ sys/netipsec/key_debug.c
@@ -78,6 +78,7 @@
static void kdebug_sadb_x_sa2(struct sadb_ext *);
static void kdebug_sadb_x_sa_replay(struct sadb_ext *);
static void kdebug_sadb_x_natt(struct sadb_ext *);
+static void kdebug_sadb_x_sa_tfc_length(struct sadb_ext *);
#ifndef _KERNEL
#define panic(fmt, ...) { printf(fmt, ## __VA_ARGS__); exit(-1); }
@@ -253,6 +254,9 @@
case SADB_X_EXT_NAT_T_DPORT:
kdebug_sadb_x_natt(ext);
break;
+ case SADB_X_EXT_SA_TFC_LENGTH:
+ kdebug_sadb_x_sa_tfc_length(ext);
+ break;
default:
printf("%s: invalid ext_type %u\n", __func__,
ext->sadb_ext_type);
@@ -519,6 +523,20 @@
}
}
+static void
+kdebug_sadb_x_sa_tfc_length(struct sadb_ext *ext)
+{
+ struct sadb_x_sa_tfc_length *tfc_length;
+
+ /* sanity check */
+ if (ext == NULL)
+ panic("%s: NULL pointer was passed.\n", __func__);
+
+ tfc_length = (struct sadb_x_sa_tfc_length *)ext;
+ printf("sadb_x_sa_tfc_length{ length=%d }\n",
+ tfc_length->sadb_x_sa_tfc_length_length);
+}
+
void
kdebug_sadb_x_policy(struct sadb_ext *ext)
{
Index: sys/netipsec/keydb.h
===================================================================
--- sys/netipsec/keydb.h
+++ sys/netipsec/keydb.h
@@ -185,6 +185,8 @@
uint64_t cntr; /* counter for GCM and CTR */
volatile u_int refcnt; /* reference count */
+
+ int32_t tfc; /* TFC padding length (ESPv3) */
};
#define SECASVAR_LOCK(_sav) mtx_lock((_sav)->lock)
Index: sys/netipsec/xform_esp.c
===================================================================
--- sys/netipsec/xform_esp.c
+++ sys/netipsec/xform_esp.c
@@ -59,6 +59,7 @@
#include <netinet/ip.h>
#include <netinet/ip_ecn.h>
#include <netinet/ip6.h>
+#include <netinet/udp.h>
#include <netipsec/ipsec.h>
#include <netipsec/ah.h>
@@ -637,9 +638,10 @@
uint8_t *ivp;
uint64_t cntr;
crypto_session_t cryptoid;
- int hlen, rlen, padding, blks, alen, i, roff;
- int error, maxpacketsize;
+ int hlen, rlen, padding, blks, alen, i, j, roff;
+ int error, maxpacketsize, tfclen;
uint8_t prot;
+ int pktlen;
IPSEC_ASSERT(sav != NULL, ("null SA"));
esph = sav->tdb_authalgxform;
@@ -657,9 +659,6 @@
*/
blks = MAX(4, espx->blocksize); /* Cipher blocksize */
- /* XXX clamp padding length a la KAME??? */
- padding = ((blks - ((rlen + 2) % blks)) % blks) + 2;
-
alen = xform_ah_authsize(esph);
ESPSTAT_INC(esps_output);
@@ -686,15 +685,32 @@
error = EPFNOSUPPORT;
goto bad;
}
+
+ pktlen = skip + hlen + rlen + alen;
+ if (sav->tfc > 0 && sav->tfc > pktlen) {
+ tfclen = sav->tfc - pktlen;
+ /* XXX clamp padding length a la KAME??? */
+ padding = ((blks - ((rlen + tfclen + 2) % blks)) % blks) + 2;
+ pktlen += padding + tfclen;
+ if (pktlen > maxpacketsize && tfclen > blks)
+ tfclen -= blks;
+ }
+ else {
+ tfclen = 0;
+ /* XXX clamp padding length a la KAME??? */
+ padding = ((blks - ((rlen + 2) % blks)) % blks) + 2;
+ pktlen += padding;
+ }
+
/*
DPRINTF(("%s: skip %d hlen %d rlen %d padding %d alen %d blksd %d\n",
__func__, skip, hlen, rlen, padding, alen, blks)); */
- if (skip + hlen + rlen + padding + alen > maxpacketsize) {
+ if (pktlen > maxpacketsize) {
DPRINTF(("%s: packet in SA %s/%08lx got too big "
"(len %u, max len %u)\n", __func__,
ipsec_address(&saidx->dst, buf, sizeof(buf)),
(u_long) ntohl(sav->spi),
- skip + hlen + rlen + padding + alen, maxpacketsize));
+ pktlen, maxpacketsize));
ESPSTAT_INC(esps_toobig);
error = EMSGSIZE;
goto bad;
@@ -746,6 +762,35 @@
cntr = sav->cntr++;
SECASVAR_UNLOCK(sav);
+ /*
+ * Add TFC padding
+ */
+ for (i = 0; i < tfclen; i += MCLBYTES) {
+ int pad_len = MIN(tfclen - i, MCLBYTES);
+ pad = (u_char*) m_pad(m, pad_len);
+ if (pad == NULL) {
+ DPRINTF(("%s: m_pad failed for SA %s/%08lx\n", __func__,
+ ipsec_address(&saidx->dst, buf, sizeof(buf)),
+ (u_long) ntohl(sav->spi)));
+ m = NULL; /* NB: free'd by m_pad */
+ error = ENOBUFS;
+ goto bad;
+ }
+
+ switch (sav->flags & SADB_X_EXT_PMASK) {
+ case SADB_X_EXT_PRAND:
+ (void) read_random(pad, pad_len);
+ break;
+ case SADB_X_EXT_PZERO:
+ bzero(pad, pad_len);
+ break;
+ case SADB_X_EXT_PSEQ:
+ for (j = 0; j < pad_len; j++)
+ pad[j] = i + j + 1;
+ break;
+ }
+ }
+
/*
* Add padding -- better to do it ourselves than use the crypto engine,
* although if/when we support compression, we'd have to do that.

File Metadata

Mime Type
text/plain
Expires
Tue, Jul 21, 7:32 AM (20 m, 54 s)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
35308732
Default Alt Text
D22445.id.diff (11 KB)

Event Timeline