2010-12-08 14:39:15

by Martin Willi

[permalink] [raw]
Subject: [PATCH 0/3] xfrm: ESP Traffic Flow Confidentiality padding (v3)

The following patchset adds Traffic Flow Confidentiality padding. The
first patch introduces a new Netlink XFRM attribute to configure TFC via
userspace. Patch two and three implement the padding logic in IPv4 and
IPv6 ESP. Padding is always done using the RFC4303 format an is clamped
to the PMTU.

Changes from v2:
- Remove unused flag field in attribute, use a plain u32 as attribute payload
- Reject installation of TFC padding on non-tunnel SAs

Martin Willi (3):
xfrm: Add Traffic Flow Confidentiality padding XFRM attribute
xfrm: Traffic Flow Confidentiality for IPv4 ESP
xfrm: Traffic Flow Confidentiality for IPv6 ESP

include/linux/xfrm.h | 1 +
include/net/xfrm.h | 1 +
net/ipv4/esp4.c | 32 ++++++++++++++++++++++++--------
net/ipv6/esp6.c | 32 ++++++++++++++++++++++++--------
net/xfrm/xfrm_user.c | 19 +++++++++++++++++--
5 files changed, 67 insertions(+), 18 deletions(-)


2010-12-08 14:39:15

by Martin Willi

[permalink] [raw]
Subject: [PATCH 3/3] xfrm: Traffic Flow Confidentiality for IPv6 ESP

Add TFC padding to all packets smaller than the boundary configured
on the xfrm state. If the boundary is larger than the PMTU, limit
padding to the PMTU.

Signed-off-by: Martin Willi <[email protected]>
---
net/ipv6/esp6.c | 32 ++++++++++++++++++++++++--------
1 files changed, 24 insertions(+), 8 deletions(-)

diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c
index ee9b93b..1b5c982 100644
--- a/net/ipv6/esp6.c
+++ b/net/ipv6/esp6.c
@@ -49,6 +49,8 @@ struct esp_skb_cb {

#define ESP_SKB_CB(__skb) ((struct esp_skb_cb *)&((__skb)->cb[0]))

+static u32 esp6_get_mtu(struct xfrm_state *x, int mtu);
+
/*
* Allocate an AEAD request structure with extra space for SG and IV.
*
@@ -140,6 +142,8 @@ static int esp6_output(struct xfrm_state *x, struct sk_buff *skb)
int blksize;
int clen;
int alen;
+ int plen;
+ int tfclen;
int nfrags;
u8 *iv;
u8 *tail;
@@ -148,18 +152,26 @@ static int esp6_output(struct xfrm_state *x, struct sk_buff *skb)
/* skb is pure payload to encrypt */
err = -ENOMEM;

- /* Round to block size */
- clen = skb->len;
-
aead = esp->aead;
alen = crypto_aead_authsize(aead);

+ tfclen = 0;
+ if (x->tfcpad) {
+ struct xfrm_dst *dst = (struct xfrm_dst *)skb_dst(skb);
+ u32 padto;
+
+ padto = min(x->tfcpad, esp6_get_mtu(x, dst->child_mtu_cached));
+ if (skb->len < padto)
+ tfclen = padto - skb->len;
+ }
blksize = ALIGN(crypto_aead_blocksize(aead), 4);
- clen = ALIGN(clen + 2, blksize);
+ clen = ALIGN(skb->len + 2 + tfclen, blksize);
if (esp->padlen)
clen = ALIGN(clen, esp->padlen);
+ plen = clen - skb->len - tfclen;

- if ((err = skb_cow_data(skb, clen - skb->len + alen, &trailer)) < 0)
+ err = skb_cow_data(skb, tfclen + plen + alen, &trailer);
+ if (err < 0)
goto error;
nfrags = err;

@@ -174,13 +186,17 @@ static int esp6_output(struct xfrm_state *x, struct sk_buff *skb)

/* Fill padding... */
tail = skb_tail_pointer(trailer);
+ if (tfclen) {
+ memset(tail, 0, tfclen);
+ tail += tfclen;
+ }
do {
int i;
- for (i=0; i<clen-skb->len - 2; i++)
+ for (i = 0; i < plen - 2; i++)
tail[i] = i + 1;
} while (0);
- tail[clen-skb->len - 2] = (clen - skb->len) - 2;
- tail[clen - skb->len - 1] = *skb_mac_header(skb);
+ tail[plen - 2] = plen - 2;
+ tail[plen - 1] = *skb_mac_header(skb);
pskb_put(skb, trailer, clen - skb->len + alen);

skb_push(skb, -skb_network_offset(skb));
--
1.7.1

2010-12-08 14:39:15

by Martin Willi

[permalink] [raw]
Subject: [PATCH 2/3] xfrm: Traffic Flow Confidentiality for IPv4 ESP

Add TFC padding to all packets smaller than the boundary configured
on the xfrm state. If the boundary is larger than the PMTU, limit
padding to the PMTU.

Signed-off-by: Martin Willi <[email protected]>
---
net/ipv4/esp4.c | 32 ++++++++++++++++++++++++--------
1 files changed, 24 insertions(+), 8 deletions(-)

diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c
index 14ca1f1..e42a905 100644
--- a/net/ipv4/esp4.c
+++ b/net/ipv4/esp4.c
@@ -23,6 +23,8 @@ struct esp_skb_cb {

#define ESP_SKB_CB(__skb) ((struct esp_skb_cb *)&((__skb)->cb[0]))

+static u32 esp4_get_mtu(struct xfrm_state *x, int mtu);
+
/*
* Allocate an AEAD request structure with extra space for SG and IV.
*
@@ -117,25 +119,35 @@ static int esp_output(struct xfrm_state *x, struct sk_buff *skb)
int blksize;
int clen;
int alen;
+ int plen;
+ int tfclen;
int nfrags;

/* skb is pure payload to encrypt */

err = -ENOMEM;

- /* Round to block size */
- clen = skb->len;
-
esp = x->data;
aead = esp->aead;
alen = crypto_aead_authsize(aead);

+ tfclen = 0;
+ if (x->tfcpad) {
+ struct xfrm_dst *dst = (struct xfrm_dst *)skb_dst(skb);
+ u32 padto;
+
+ padto = min(x->tfcpad, esp4_get_mtu(x, dst->child_mtu_cached));
+ if (skb->len < padto)
+ tfclen = padto - skb->len;
+ }
blksize = ALIGN(crypto_aead_blocksize(aead), 4);
- clen = ALIGN(clen + 2, blksize);
+ clen = ALIGN(skb->len + 2 + tfclen, blksize);
if (esp->padlen)
clen = ALIGN(clen, esp->padlen);
+ plen = clen - skb->len - tfclen;

- if ((err = skb_cow_data(skb, clen - skb->len + alen, &trailer)) < 0)
+ err = skb_cow_data(skb, tfclen + plen + alen, &trailer);
+ if (err < 0)
goto error;
nfrags = err;

@@ -150,13 +162,17 @@ static int esp_output(struct xfrm_state *x, struct sk_buff *skb)

/* Fill padding... */
tail = skb_tail_pointer(trailer);
+ if (tfclen) {
+ memset(tail, 0, tfclen);
+ tail += tfclen;
+ }
do {
int i;
- for (i=0; i<clen-skb->len - 2; i++)
+ for (i = 0; i < plen - 2; i++)
tail[i] = i + 1;
} while (0);
- tail[clen - skb->len - 2] = (clen - skb->len) - 2;
- tail[clen - skb->len - 1] = *skb_mac_header(skb);
+ tail[plen - 2] = plen - 2;
+ tail[plen - 1] = *skb_mac_header(skb);
pskb_put(skb, trailer, clen - skb->len + alen);

skb_push(skb, -skb_network_offset(skb));
--
1.7.1

2010-12-08 14:37:49

by Martin Willi

[permalink] [raw]
Subject: [PATCH 1/3] xfrm: Add Traffic Flow Confidentiality padding XFRM attribute

The XFRMA_TFCPAD attribute for XFRM state installation configures
Traffic Flow Confidentiality by padding ESP packets to a specified
length.

Signed-off-by: Martin Willi <[email protected]>
---
include/linux/xfrm.h | 1 +
include/net/xfrm.h | 1 +
net/xfrm/xfrm_user.c | 19 +++++++++++++++++--
3 files changed, 19 insertions(+), 2 deletions(-)

diff --git a/include/linux/xfrm.h b/include/linux/xfrm.h
index b971e38..930fdd2 100644
--- a/include/linux/xfrm.h
+++ b/include/linux/xfrm.h
@@ -283,6 +283,7 @@ enum xfrm_attr_type_t {
XFRMA_KMADDRESS, /* struct xfrm_user_kmaddress */
XFRMA_ALG_AUTH_TRUNC, /* struct xfrm_algo_auth */
XFRMA_MARK, /* struct xfrm_mark */
+ XFRMA_TFCPAD, /* __u32 */
__XFRMA_MAX

#define XFRMA_MAX (__XFRMA_MAX - 1)
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index bcfb6b2..bdcade7 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -143,6 +143,7 @@ struct xfrm_state {
struct xfrm_id id;
struct xfrm_selector sel;
struct xfrm_mark mark;
+ u32 tfcpad;

u32 genid;

diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index 8bae6b2..8eb8895 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -148,7 +148,8 @@ static int verify_newsa_info(struct xfrm_usersa_info *p,
!attrs[XFRMA_ALG_AUTH_TRUNC]) ||
attrs[XFRMA_ALG_AEAD] ||
attrs[XFRMA_ALG_CRYPT] ||
- attrs[XFRMA_ALG_COMP])
+ attrs[XFRMA_ALG_COMP] ||
+ attrs[XFRMA_TFCPAD])
goto out;
break;

@@ -165,6 +166,9 @@ static int verify_newsa_info(struct xfrm_usersa_info *p,
attrs[XFRMA_ALG_CRYPT]) &&
attrs[XFRMA_ALG_AEAD])
goto out;
+ if (attrs[XFRMA_TFCPAD] &&
+ p->mode != XFRM_MODE_TUNNEL)
+ goto out;
break;

case IPPROTO_COMP:
@@ -172,7 +176,8 @@ static int verify_newsa_info(struct xfrm_usersa_info *p,
attrs[XFRMA_ALG_AEAD] ||
attrs[XFRMA_ALG_AUTH] ||
attrs[XFRMA_ALG_AUTH_TRUNC] ||
- attrs[XFRMA_ALG_CRYPT])
+ attrs[XFRMA_ALG_CRYPT] ||
+ attrs[XFRMA_TFCPAD])
goto out;
break;

@@ -186,6 +191,7 @@ static int verify_newsa_info(struct xfrm_usersa_info *p,
attrs[XFRMA_ALG_CRYPT] ||
attrs[XFRMA_ENCAP] ||
attrs[XFRMA_SEC_CTX] ||
+ attrs[XFRMA_TFCPAD] ||
!attrs[XFRMA_COADDR])
goto out;
break;
@@ -439,6 +445,9 @@ static struct xfrm_state *xfrm_state_construct(struct net *net,
goto error;
}

+ if (attrs[XFRMA_TFCPAD])
+ x->tfcpad = nla_get_u32(attrs[XFRMA_TFCPAD]);
+
if (attrs[XFRMA_COADDR]) {
x->coaddr = kmemdup(nla_data(attrs[XFRMA_COADDR]),
sizeof(*x->coaddr), GFP_KERNEL);
@@ -688,6 +697,9 @@ static int copy_to_user_state_extra(struct xfrm_state *x,
if (x->encap)
NLA_PUT(skb, XFRMA_ENCAP, sizeof(*x->encap), x->encap);

+ if (x->tfcpad)
+ NLA_PUT_U32(skb, XFRMA_TFCPAD, x->tfcpad);
+
if (xfrm_mark_put(skb, &x->mark))
goto nla_put_failure;

@@ -2122,6 +2134,7 @@ static const struct nla_policy xfrma_policy[XFRMA_MAX+1] = {
[XFRMA_MIGRATE] = { .len = sizeof(struct xfrm_user_migrate) },
[XFRMA_KMADDRESS] = { .len = sizeof(struct xfrm_user_kmaddress) },
[XFRMA_MARK] = { .len = sizeof(struct xfrm_mark) },
+ [XFRMA_TFCPAD] = { .type = NLA_U32 },
};

static struct xfrm_link {
@@ -2301,6 +2314,8 @@ static inline size_t xfrm_sa_len(struct xfrm_state *x)
l += nla_total_size(sizeof(*x->calg));
if (x->encap)
l += nla_total_size(sizeof(*x->encap));
+ if (x->tfcpad)
+ l += nla_total_size(sizeof(x->tfcpad));
if (x->security)
l += nla_total_size(sizeof(struct xfrm_user_sec_ctx) +
x->security->ctx_len);
--
1.7.1


2010-12-09 12:47:34

by Herbert Xu

[permalink] [raw]
Subject: Re: [PATCH 0/3] xfrm: ESP Traffic Flow Confidentiality padding (v3)

On Wed, Dec 08, 2010 at 03:37:48PM +0100, Martin Willi wrote:
> The following patchset adds Traffic Flow Confidentiality padding. The
> first patch introduces a new Netlink XFRM attribute to configure TFC via
> userspace. Patch two and three implement the padding logic in IPv4 and
> IPv6 ESP. Padding is always done using the RFC4303 format an is clamped
> to the PMTU.
>
> Changes from v2:
> - Remove unused flag field in attribute, use a plain u32 as attribute payload
> - Reject installation of TFC padding on non-tunnel SAs

Looks good to me. Thanks for the hard work Martin!

Acked-by: Herbert Xu <[email protected]>

Cheers,
--
Email: Herbert Xu <[email protected]>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt

2010-12-10 22:44:22

by David Miller

[permalink] [raw]
Subject: Re: [PATCH 0/3] xfrm: ESP Traffic Flow Confidentiality padding (v3)

From: Herbert Xu <[email protected]>
Date: Thu, 9 Dec 2010 20:47:32 +0800

> On Wed, Dec 08, 2010 at 03:37:48PM +0100, Martin Willi wrote:
>> The following patchset adds Traffic Flow Confidentiality padding. The
>> first patch introduces a new Netlink XFRM attribute to configure TFC via
>> userspace. Patch two and three implement the padding logic in IPv4 and
>> IPv6 ESP. Padding is always done using the RFC4303 format an is clamped
>> to the PMTU.
>>
>> Changes from v2:
>> - Remove unused flag field in attribute, use a plain u32 as attribute payload
>> - Reject installation of TFC padding on non-tunnel SAs
>
> Looks good to me. Thanks for the hard work Martin!
>
> Acked-by: Herbert Xu <[email protected]>

All applied, thanks everyone!