Add IPsec extended (64-bit) sequence numbers
Subsystems (4)
Steffen Klassert
maintainerv2 cover Add IPsec extended (64-bit) sequence numbers
This patchset adds support for IPsec extended (64-bit) sequence numbers for esp as defined in RFC 4303. Also it adds support for anti-replay windows bigger than 32 packets. To make use of big anti-replay windows and extended sequence numbers, new userspace tools are needed. An example patch for iproute2 is provided with this patchset.
Known issues:
- Not tested against another implementation of IPsec extended sequence numbers.
Changes from v1:
- Use a SG list with three 4 byte entries for the associated data.
- Fix the sequence number to be in network byte order when using AEAD algorithms.
- Rebased to net-next-2.6 current.
The patchset is also available at branch 'net-next-esn' of
git://git.kernel.org/pub/scm/linux/kernel/git/klassert/linux-2.6-stk.git
Steffen
Steffen Klassert
maintainerRFC PATCH v2 1/9 crypto: authencesn - Add algorithm to handle IPsec extended sequence numbers
ESP with separate encryption/authentication algorithms needs a special treatment for the associated data. This patch add a new algorithm that handles esp with extended sequence numbers.
--- crypto/Makefile | 2 +- crypto/authencesn.c | 835 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 836 insertions(+), 1 deletions(-) create mode 100644 crypto/authencesn.c
crypto/Makefile +1 -1
@@ -78,7 +78,7 @@ obj-$(CONFIG_CRYPTO_DEFLATE) += deflate.o obj-$(CONFIG_CRYPTO_ZLIB) += zlib.o obj-$(CONFIG_CRYPTO_MICHAEL_MIC) += michael_mic.o obj-$(CONFIG_CRYPTO_CRC32C) += crc32c.o -obj-$(CONFIG_CRYPTO_AUTHENC) += authenc.o +obj-$(CONFIG_CRYPTO_AUTHENC) += authenc.o authencesn.o obj-$(CONFIG_CRYPTO_LZO) += lzo.o obj-$(CONFIG_CRYPTO_RNG2) += rng.o obj-$(CONFIG_CRYPTO_RNG2) += krng.o
crypto/authencesn.c new file +835 -0
835 lines not on this page · raw message
Signature · 1 line
1.7.0.4
Herbert Xu
maintainerRe: [RFC v2 PATCH 1/9] crypto: authencesn - Add algorithm to handle IPsec extended sequence numbers
crypto/authencesn.c line 512
Quoted 2 lines · Steffen Klassert
crypto/authencesn.c new file +1
-0+return crypto_authenc_esn_genicv (req, iv,CRYPTO_TFM_REQ_MAY_SLEEP );
BTW, we should get rid of these MAY_SLEEP flags. Originally I included them for the IPsec encryption path because that happens to be sleepable. We should instead be getting it from the request itself.
Also, as soon as we enter the async path it becomes unsleepable.
Of course this affects the existing authenc file as well.
Cheers,
Signature · 3 lines
Email: Herbert Xu <[email protected]> Home Page: http://gondor.apana.org.au/~herbert/ PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
Steffen Klassert
maintainerRe: [RFC v2 PATCH 1/9] crypto: authencesn - Add algorithm to handle IPsec extended sequence numbers
Quoted 9 lines · Herbert Xu
crypto/authencesn.c line 512
Quoted 2 lines · Steffen Klassert
crypto/authencesn.c new file +1
-0+return crypto_authenc_esn_genicv (req, iv,CRYPTO_TFM_REQ_MAY_SLEEP );BTW, we should get rid of these
MAY_SLEEPflags. Originally I included them for the IPsec encryption path because that happens to be sleepable. We should instead be getting it from the request itself.
Not sure if I get you right, but we do not set this flag here. We use it to mask the flags we got from the request, so we pass this flag to the ahash algorithm just if it was set by the original aead request.
Herbert Xu
maintainerRe: [RFC v2 PATCH 1/9] crypto: authencesn - Add algorithm to handle IPsec extended sequence numbers
Quoted 11 lines · Steffen Klassert
Quoted 9 lines · Herbert Xu
crypto/authencesn.c line 512
Quoted 2 lines · Steffen Klassert
crypto/authencesn.c new file +1
-0+return crypto_authenc_esn_genicv (req, iv,CRYPTO_TFM_REQ_MAY_SLEEP );BTW, we should get rid of these
MAY_SLEEPflags. Originally I included them for the IPsec encryption path because that happens to be sleepable. We should instead be getting it from the request itself.
Quoted 4 lines
Not sure if I get you right, but we do not set this flag here. We use it to mask the flags we got from the request, so we pass this flag to the ahash algorithm just if it was set by the original aead request.
Indeed you are right. As long as it is only a mask and only used on the sync path it should be OK.
Thanks,
Signature · 3 lines
Email: Herbert Xu <[email protected]> Home Page: http://gondor.apana.org.au/~herbert/ PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
Steffen Klassert
maintainerRe: [RFC v2 PATCH 1/9] crypto: authencesn - Add algorithm to handle IPsec extended sequence numbers
Quoted 9 lines · Herbert Xu
Quoted 5 lines
Not sure if I get you right, but we do not set this flag here. We use it to mask the flags we got from the request, so we pass this flag to the ahash algorithm just if it was set by the original aead request.
Indeed you are right. As long as it is only a mask and only used on the sync path it should be OK.
Yes, that's how it is used in both, authenc and authencesn.
Steffen Klassert
maintainerRFC PATCH v2 2/9 xfrm: Add basic infrastructure to support IPsec extended sequence numbers
In reply to Steffen KlassertThis patch adds the struct xfrm_replay_state_esn which will be used to support IPsec extended sequence numbers and anti replay windows bigger than 32 packets. Also we add a function that returns the actual size of the xfrm_replay_state_esn, a xfrm netlink atribute and a xfrm state flag for the use of extended sequence numbers.
--- include/linux/xfrm.h | 12 ++++++++++++ include/net/xfrm.h | 7 +++++++ 2 files changed, 19 insertions(+), 0 deletions(-)
include/linux/xfrm.h +12 -0
@@ -84,6 +84,16 @@ struct xfrm_replay_state {__u32 bitmap; }; +struct xfrm_replay_state_esn { +unsigned int bmp_len; +__u32 oseq; +__u32 seq; +__u32 oseq_hi; +__u32 seq_hi; +__u32 replay_window; +__u32 bmp[0 ]; +}; +struct xfrm_algo {char alg_name[64 ];unsigned int alg_key_len;/* in bits */
@@ -284,6 +294,7 @@ enum xfrm_attr_type_t {XFRMA_ALG_AUTH_TRUNC ,/* struct xfrm_algo_auth */ XFRMA_MARK ,/* struct xfrm_mark */ XFRMA_TFCPAD ,/* __u32 */ +XFRMA_REPLAY_ESN_VAL ,/* struct xfrm_replay_esn */ __XFRMA_MAX#define XFRMA_MAX (__XFRMA_MAX - 1)
@@ -351,6 +362,7 @@ struct xfrm_usersa_info {#define XFRM_STATE_ICMP 16#define XFRM_STATE_AF_UNSPEC 32#define XFRM_STATE_ALIGN4 64 +#define XFRM_STATE_ESN 128 };struct xfrm_usersa_id {
include/net/xfrm.h +7 -0
@@ -186,9 +186,11 @@ struct xfrm_state {/* State for replay detection */ struct xfrm_replay_state replay; +struct xfrm_replay_state_esn *replay_esn;/* Replay detection state at the time we sent the last notification */ struct xfrm_replay_state preplay; +struct xfrm_replay_state_esn *preplay_esn;/* internal flag that only holds state for delayed aevent at the * moment
@@ -1569,6 +1571,11 @@ static inline int xfrm_alg_auth_len(const struct xfrm_algo_auth *alg)return sizeof (*alg) + ((alg->alg_key_len +7 ) /8 ); } +static inline int xfrm_replay_state_esn_len (struct xfrm_replay_state_esn *replay_esn) +{ +return sizeof (*replay_esn) + replay_esn->bmp_len *sizeof (__u32); +} +#ifdef CONFIG_XFRM_MIGRATE static inline struct xfrm_algo *xfrm_algo_clone (struct xfrm_algo *orig) {
Signature · 1 line
1.7.0.4
Herbert Xu
maintainerRe: [RFC v2 PATCH 2/9] xfrm: Add basic infrastructure to support IPsec extended sequence numbers
Quoted 7 lines · Steffen Klassert
This patch adds the struct
xfrm_replay_state_esnwhich will be used to support IPsec extended sequence numbers and anti replay windows bigger than 32 packets. Also we add a function that returns the actual size of thexfrm_replay_state_esn, a xfrm netlink atribute and a xfrm state flag for the use of extended sequence numbers.Signed-off-by Steffen Klassert <[email protected]>
All the remaining eight patches look good to me.
Dave, how would you like to handle this patch-set? As Steffen's first crypto patch is completely self-contained, perhaps you could just include it along with the rest of the series in your tree?
Thanks,
Signature · 3 lines
Email: Herbert Xu <[email protected]> Home Page: http://gondor.apana.org.au/~herbert/ PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
David Miller
maintainerRe: [RFC v2 PATCH 2/9] xfrm: Add basic infrastructure to support IPsec extended sequence numbers
From: Herbert Xu <[email protected]>
Date: Sun, 13 Mar 2011 14:44:57 +0800
Quoted 7 lines · Steffen Klassert
Quoted 6 lines
This patch adds the struct
xfrm_replay_state_esnwhich will be used to support IPsec extended sequence numbers and anti replay windows bigger than 32 packets. Also we add a function that returns the actual size of thexfrm_replay_state_esn, a xfrm netlink atribute and a xfrm state flag for the use of extended sequence numbers.
Quoted 7 lines
Quoted 1 line
Signed-off-by Steffen Klassert <[email protected]>All the remaining eight patches look good to me.
Dave, how would you like to handle this patch-set? As Steffen's first crypto patch is completely self-contained, perhaps you could just include it along with the rest of the series in your tree?
Sure, I can do that.
Can I add your ACK to all of the patches?
Re: [RFC v2 PATCH 2/9] xfrm: Add basic infrastructure to support IPsec extended sequence numbers
Quoted 2 lines · David Miller
Sure, I can do that.
Thanks!
Quoted 1 line
Can I add your ACK to all of the patches?
Of course:
Cheers,
Signature · 3 lines
Email: Herbert Xu <[email protected]> Home Page: http://gondor.apana.org.au/~herbert/ PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
Steffen Klassert
maintainerRFC PATCH v2 3/9 xfrm: Use separate low and high order bits of the sequence numbers in xfrm_skb_cb
In reply to Steffen KlassertTo support IPsec extended sequence numbers, we split the output sequence numbers of xfrm_skb_cb in low and high order 32 bits and we add the high order 32 bits to the input sequence numbers. All users are updated accordingly.
--- include/net/xfrm.h | 10 ++++++++-- net/ipv4/ah4.c | 2 +- net/ipv4/esp4.c | 4 ++-- net/ipv6/ah6.c | 2 +- net/ipv6/esp6.c | 4 ++-- net/xfrm/xfrm_input.c | 4 ++-- net/xfrm/xfrm_output.c | 2 +- 7 files changed, 17 insertions(+), 11 deletions(-)
include/net/xfrm.h +8 -2
@@ -582,8 +582,14 @@ struct xfrm_skb_cb {/* Sequence number for replay protection. */ union { -u64 output; -__be32 input; +struct { +__u32 low; +__u32 hi; + } output; +struct { +__be32 low; +__be32 hi; + } input; } seq; };
net/ipv4/ah4.c +1 -1
@@ -208,7 +208,7 @@ static int ah_output(struct xfrm_state *x, struct sk_buff *skb) ah->reserved =0 ; ah->spi = x->id.spi; - ah->seq_no =htonl (XFRM_SKB_CB (skb)->seq.output); + ah->seq_no =htonl (XFRM_SKB_CB (skb)->seq.output.low);sg_init_table (sg, nfrags);skb_to_sgvec (skb, sg,0 , skb->len);
net/ipv4/esp4.c +2 -2
@@ -215,7 +215,7 @@ static int esp_output(struct xfrm_state *x, struct sk_buff *skb) } esph->spi = x->id.spi; - esph->seq_no =htonl (XFRM_SKB_CB (skb)->seq.output); + esph->seq_no =htonl (XFRM_SKB_CB (skb)->seq.output.low);sg_init_table (sg, nfrags); skb_to_sgvec(skb, sg,
@@ -227,7 +227,7 @@ static int esp_output(struct xfrm_state *x, struct sk_buff *skb)aead_givcrypt_set_crypt (req, sg, sg, clen, iv);aead_givcrypt_set_assoc (req, asg,sizeof (*esph));aead_givcrypt_set_giv (req, esph->enc_data, -XFRM_SKB_CB (skb)->seq.output); +XFRM_SKB_CB (skb)->seq.output.low);ESP_SKB_CB (skb)->tmp = tmp; err =crypto_aead_givencrypt (req);
net/ipv6/ah6.c +1 -1
@@ -409,7 +409,7 @@ static int ah6_output(struct xfrm_state *x, struct sk_buff *skb) ah->reserved =0 ; ah->spi = x->id.spi; - ah->seq_no =htonl (XFRM_SKB_CB (skb)->seq.output); + ah->seq_no =htonl (XFRM_SKB_CB (skb)->seq.output.low);sg_init_table (sg, nfrags);skb_to_sgvec (skb, sg,0 , skb->len);
net/ipv6/esp6.c +2 -2
@@ -204,7 +204,7 @@ static int esp6_output(struct xfrm_state *x, struct sk_buff *skb) *skb_mac_header (skb) =IPPROTO_ESP ; esph->spi = x->id.spi; - esph->seq_no =htonl (XFRM_SKB_CB (skb)->seq.output); + esph->seq_no =htonl (XFRM_SKB_CB (skb)->seq.output.low);sg_init_table (sg, nfrags); skb_to_sgvec(skb, sg,
@@ -216,7 +216,7 @@ static int esp6_output(struct xfrm_state *x, struct sk_buff *skb)aead_givcrypt_set_crypt (req, sg, sg, clen, iv);aead_givcrypt_set_assoc (req, asg,sizeof (*esph));aead_givcrypt_set_giv (req, esph->enc_data, -XFRM_SKB_CB (skb)->seq.output); +XFRM_SKB_CB (skb)->seq.output.low);ESP_SKB_CB (skb)->tmp = tmp; err =crypto_aead_givencrypt (req);
net/xfrm/xfrm_input.c +2 -2
@@ -118,7 +118,7 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)if (encap_type <0 ) { async =1 ; x =xfrm_input_state (skb); - seq =XFRM_SKB_CB (skb)->seq.input; + seq =XFRM_SKB_CB (skb)->seq.input.low; goto resume; }
@@ -184,7 +184,7 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)spin_unlock (&x->lock); -XFRM_SKB_CB (skb)->seq.input = seq; +XFRM_SKB_CB (skb)->seq.input.low = seq; nexthdr = x->type->input (x, skb);
net/xfrm/xfrm_output.c +1 -1
@@ -68,7 +68,7 @@ static int xfrm_output_one(struct sk_buff *skb, int err) }if (x->type->flags &XFRM_TYPE_REPLAY_PROT ) { -XFRM_SKB_CB (skb)->seq.output = ++x->replay.oseq; +XFRM_SKB_CB (skb)->seq.output.low = ++x->replay.oseq;if (unlikely (x->replay.oseq ==0 )) {XFRM_INC_STATS (net,LINUX_MIB_XFRMOUTSTATESEQERROR ); x->replay.oseq--;
Signature · 1 line
1.7.0.4
Steffen Klassert
maintainerRFC PATCH v2 4/9 esp4: Add support for IPsec extended sequence numbers
In reply to Steffen KlassertThis patch adds IPsec extended sequence numbers support to esp4. We use the authencesn crypto algorithm to handle esp with separate encryption/authentication algorithms.
--- net/ipv4/esp4.c | 100 +++++++++++++++++++++++++++++++++++++++++++++---------- 1 files changed, 82 insertions(+), 18 deletions(-)
net/ipv4/esp4.c +82 -18
@@ -33,11 +33,14 @@ static u32 esp4_get_mtu(struct xfrm_state *x, int mtu);* * TODO: Use spare space in skb for this where possible. */ -static void *esp_alloc_tmp (struct crypto_aead *aead,int nfrags) +static void *esp_alloc_tmp (struct crypto_aead *aead,int nfrags,int seqhilen) {unsigned int len; - len =crypto_aead_ivsize (aead); + len = seqhilen; + + len +=crypto_aead_ivsize (aead); +if (len) { len +=crypto_aead_alignmask (aead) & ~(crypto_tfm_ctx_alignment () -1 );
@@ -52,10 +55,15 @@ static void *esp_alloc_tmp(struct crypto_aead *aead, int nfrags)return kmalloc (len,GFP_ATOMIC ); } -static inline u8 *esp_tmp_iv (struct crypto_aead *aead,void *tmp) +static inline __be32 *esp_tmp_seqhi (void *tmp) +{ +return PTR_ALIGN ((__be32 *)tmp, __alignof__(__be32 )); +} +static inline u8 *esp_tmp_iv (struct crypto_aead *aead,void *tmp,int seqhilen) {return crypto_aead_ivsize (aead) ? -PTR_ALIGN ((u8 *)tmp,crypto_aead_alignmask (aead) +1 ) : tmp; +PTR_ALIGN ((u8 *)tmp + seqhilen, +crypto_aead_alignmask (aead) +1 ) : tmp + seqhilen; } static inline struct aead_givcrypt_request *esp_tmp_givreq(
@@ -122,6 +130,10 @@ static int esp_output(struct xfrm_state *x, struct sk_buff *skb)int plen;int tfclen;int nfrags; +int assoclen; +int sglists; +int seqhilen; +__be32 *seqhi;/* skb is pure payload to encrypt */
@@ -151,14 +163,25 @@ static int esp_output(struct xfrm_state *x, struct sk_buff *skb) goto error; nfrags = err; - tmp =esp_alloc_tmp (aead, nfrags +1 ); + assoclen =sizeof (*esph); + sglists =1 ; + seqhilen =0 ; + +if (x->props.flags &XFRM_STATE_ESN ) { + sglists +=2 ; + seqhilen +=sizeof (__be32); + assoclen += seqhilen; + } + + tmp =esp_alloc_tmp (aead, nfrags + sglists, seqhilen);if (!tmp) goto error; - iv =esp_tmp_iv (aead, tmp); + seqhi =esp_tmp_seqhi (tmp); + iv =esp_tmp_iv (aead, tmp, seqhilen); req =esp_tmp_givreq (aead, iv); asg =esp_givreq_sg (aead, req); - sg = asg +1 ; + sg = asg + sglists;/* Fill padding... */ tail =skb_tail_pointer (trailer);
@@ -221,11 +244,19 @@ static int esp_output(struct xfrm_state *x, struct sk_buff *skb)skb_to_sgvec (skb, sg, esph->enc_data +crypto_aead_ivsize (aead) - skb->data, clen + alen); -sg_init_one (asg, esph,sizeof (*esph)); + +if ((x->props.flags &XFRM_STATE_ESN )) { +sg_init_table (asg,3 ); +sg_set_buf (asg, &esph->spi,sizeof (__be32)); + *seqhi =htonl (XFRM_SKB_CB (skb)->seq.output.hi); +sg_set_buf (asg +1 , seqhi, seqhilen); +sg_set_buf (asg +2 , &esph->seq_no,sizeof (__be32)); + }else +sg_init_one (asg, esph,sizeof (*esph));aead_givcrypt_set_callback (req,0 , esp_output_done, skb);aead_givcrypt_set_crypt (req, sg, sg, clen, iv); -aead_givcrypt_set_assoc (req, asg,sizeof (*esph)); +aead_givcrypt_set_assoc (req, asg, assoclen);aead_givcrypt_set_giv (req, esph->enc_data,XFRM_SKB_CB (skb)->seq.output.low);
@@ -346,6 +377,10 @@ static int esp_input(struct xfrm_state *x, struct sk_buff *skb)struct sk_buff *trailer;int elen = skb->len -sizeof (*esph) -crypto_aead_ivsize (aead);int nfrags; +int assoclen; +int sglists; +int seqhilen; +__be32 *seqhi;void *tmp;u8 *iv;struct scatterlist *sg;
@@ -362,16 +397,27 @@ static int esp_input(struct xfrm_state *x, struct sk_buff *skb) goto out; nfrags = err; + assoclen =sizeof (*esph); + sglists =1 ; + seqhilen =0 ; + +if (x->props.flags &XFRM_STATE_ESN ) { + sglists +=2 ; + seqhilen +=sizeof (__be32); + assoclen += seqhilen; + } + err = -ENOMEM ; - tmp =esp_alloc_tmp (aead, nfrags +1 ); + tmp =esp_alloc_tmp (aead, nfrags + sglists, seqhilen);if (!tmp) goto out;ESP_SKB_CB (skb)->tmp = tmp; - iv =esp_tmp_iv (aead, tmp); + seqhi =esp_tmp_seqhi (tmp); + iv =esp_tmp_iv (aead, tmp, seqhilen); req =esp_tmp_req (aead, iv); asg =esp_req_sg (aead, req); - sg = asg +1 ; + sg = asg + sglists; skb->ip_summed =CHECKSUM_NONE ;
@@ -382,11 +428,19 @@ static int esp_input(struct xfrm_state *x, struct sk_buff *skb)sg_init_table (sg, nfrags);skb_to_sgvec (skb, sg,sizeof (*esph) +crypto_aead_ivsize (aead), elen); -sg_init_one (asg, esph,sizeof (*esph)); + +if ((x->props.flags &XFRM_STATE_ESN )) { +sg_init_table (asg,3 ); +sg_set_buf (asg, &esph->spi,sizeof (__be32)); + *seqhi =XFRM_SKB_CB (skb)->seq.input.hi; +sg_set_buf (asg +1 , seqhi, seqhilen); +sg_set_buf (asg +2 , &esph->seq_no,sizeof (__be32)); + }else +sg_init_one (asg, esph,sizeof (*esph));aead_request_set_callback (req,0 , esp_input_done, skb);aead_request_set_crypt (req, sg, sg, elen, iv); -aead_request_set_assoc (req, asg,sizeof (*esph)); +aead_request_set_assoc (req, asg, assoclen); err =crypto_aead_decrypt (req);if (err == -EINPROGRESS )
@@ -500,10 +554,20 @@ static int esp_init_authenc(struct xfrm_state *x) goto error; err = -ENAMETOOLONG ; -if (snprintf (authenc_name,CRYPTO_MAX_ALG_NAME ,"authenc(%s,%s)" , - x->aalg ? x->aalg->alg_name :"digest_null" , - x->ealg->alg_name) >=CRYPTO_MAX_ALG_NAME ) - goto error; + +if ((x->props.flags &XFRM_STATE_ESN )) { +if (snprintf (authenc_name,CRYPTO_MAX_ALG_NAME , +"authencesn(%s,%s)" , + x->aalg ? x->aalg->alg_name :"digest_null" , + x->ealg->alg_name) >=CRYPTO_MAX_ALG_NAME ) + goto error; + }else { +if (snprintf (authenc_name,CRYPTO_MAX_ALG_NAME , +"authenc(%s,%s)" , + x->aalg ? x->aalg->alg_name :"digest_null" , + x->ealg->alg_name) >=CRYPTO_MAX_ALG_NAME ) + goto error; + } aead =crypto_alloc_aead (authenc_name,0 ,0 ); err =PTR_ERR (aead);
Signature · 1 line
1.7.0.4
Steffen Klassert
maintainerRFC PATCH v2 5/9 esp6: Add support for IPsec extended sequence numbers
In reply to Steffen KlassertThis patch adds IPsec extended sequence numbers support to esp6. We use the authencesn crypto algorithm to handle esp with separate encryption/authentication algorithms.
--- net/ipv6/esp6.c | 105 +++++++++++++++++++++++++++++++++++++++++++++---------- 1 files changed, 86 insertions(+), 19 deletions(-)
net/ipv6/esp6.c +86 -19
@@ -54,16 +54,20 @@ static u32 esp6_get_mtu(struct xfrm_state *x, int mtu);/* * Allocate an AEAD request structure with extra space for SG and IV. * -* For alignment considerations the IV is placed at the front, followed -* by the request and finally the SG list. +* For alignment considerations the upper 32 bits of the sequence number are +* placed at the front, if present. Followed by the IV, the request and finally +* the SG list. * * TODO: Use spare space in skb for this where possible. */ -static void *esp_alloc_tmp (struct crypto_aead *aead,int nfrags) +static void *esp_alloc_tmp (struct crypto_aead *aead,int nfrags,int seqihlen) {unsigned int len; - len =crypto_aead_ivsize (aead); + len = seqihlen; + + len +=crypto_aead_ivsize (aead); +if (len) { len +=crypto_aead_alignmask (aead) & ~(crypto_tfm_ctx_alignment () -1 );
@@ -78,10 +82,16 @@ static void *esp_alloc_tmp(struct crypto_aead *aead, int nfrags)return kmalloc (len,GFP_ATOMIC ); } -static inline u8 *esp_tmp_iv (struct crypto_aead *aead,void *tmp) +static inline __be32 *esp_tmp_seqhi (void *tmp) +{ +return PTR_ALIGN ((__be32 *)tmp, __alignof__(__be32 )); +} + +static inline u8 *esp_tmp_iv (struct crypto_aead *aead,void *tmp,int seqhilen) {return crypto_aead_ivsize (aead) ? -PTR_ALIGN ((u8 *)tmp,crypto_aead_alignmask (aead) +1 ) : tmp; +PTR_ALIGN ((u8 *)tmp + seqhilen, +crypto_aead_alignmask (aead) +1 ) : tmp + seqhilen; } static inline struct aead_givcrypt_request *esp_tmp_givreq(
@@ -145,8 +155,12 @@ static int esp6_output(struct xfrm_state *x, struct sk_buff *skb)int plen;int tfclen;int nfrags; +int assoclen; +int sglists; +int seqhilen;u8 *iv;u8 *tail; +__be32 *seqhi;struct esp_data *esp = x->data;/* skb is pure payload to encrypt */
@@ -175,14 +189,25 @@ static int esp6_output(struct xfrm_state *x, struct sk_buff *skb) goto error; nfrags = err; - tmp =esp_alloc_tmp (aead, nfrags +1 ); + assoclen =sizeof (*esph); + sglists =1 ; + seqhilen =0 ; + +if (x->props.flags &XFRM_STATE_ESN ) { + sglists +=2 ; + seqhilen +=sizeof (__be32); + assoclen += seqhilen; + } + + tmp =esp_alloc_tmp (aead, nfrags + sglists, seqhilen);if (!tmp) goto error; - iv =esp_tmp_iv (aead, tmp); + seqhi =esp_tmp_seqhi (tmp); + iv =esp_tmp_iv (aead, tmp, seqhilen); req =esp_tmp_givreq (aead, iv); asg =esp_givreq_sg (aead, req); - sg = asg +1 ; + sg = asg + sglists;/* Fill padding... */ tail =skb_tail_pointer (trailer);
@@ -210,11 +235,19 @@ static int esp6_output(struct xfrm_state *x, struct sk_buff *skb)skb_to_sgvec (skb, sg, esph->enc_data +crypto_aead_ivsize (aead) - skb->data, clen + alen); -sg_init_one (asg, esph,sizeof (*esph)); + +if ((x->props.flags &XFRM_STATE_ESN )) { +sg_init_table (asg,3 ); +sg_set_buf (asg, &esph->spi,sizeof (__be32)); + *seqhi =htonl (XFRM_SKB_CB (skb)->seq.output.hi); +sg_set_buf (asg +1 , seqhi, seqhilen); +sg_set_buf (asg +2 , &esph->seq_no,sizeof (__be32)); + }else +sg_init_one (asg, esph,sizeof (*esph));aead_givcrypt_set_callback (req,0 , esp_output_done, skb);aead_givcrypt_set_crypt (req, sg, sg, clen, iv); -aead_givcrypt_set_assoc (req, asg,sizeof (*esph)); +aead_givcrypt_set_assoc (req, asg, assoclen);aead_givcrypt_set_giv (req, esph->enc_data,XFRM_SKB_CB (skb)->seq.output.low);
@@ -292,8 +325,12 @@ static int esp6_input(struct xfrm_state *x, struct sk_buff *skb)struct sk_buff *trailer;int elen = skb->len -sizeof (*esph) -crypto_aead_ivsize (aead);int nfrags; +int assoclen; +int sglists; +int seqhilen;int ret =0 ;void *tmp; +__be32 *seqhi;u8 *iv;struct scatterlist *sg;struct scatterlist *asg;
@@ -314,12 +351,24 @@ static int esp6_input(struct xfrm_state *x, struct sk_buff *skb) } ret = -ENOMEM ; - tmp =esp_alloc_tmp (aead, nfrags +1 ); + + assoclen =sizeof (*esph); + sglists =1 ; + seqhilen =0 ; + +if (x->props.flags &XFRM_STATE_ESN ) { + sglists +=2 ; + seqhilen +=sizeof (__be32); + assoclen += seqhilen; + } + + tmp =esp_alloc_tmp (aead, nfrags + sglists, seqhilen);if (!tmp) goto out;ESP_SKB_CB (skb)->tmp = tmp; - iv =esp_tmp_iv (aead, tmp); + seqhi =esp_tmp_seqhi (tmp); + iv =esp_tmp_iv (aead, tmp, seqhilen); req =esp_tmp_req (aead, iv); asg =esp_req_sg (aead, req); sg = asg +1 ;
@@ -333,11 +382,19 @@ static int esp6_input(struct xfrm_state *x, struct sk_buff *skb)sg_init_table (sg, nfrags);skb_to_sgvec (skb, sg,sizeof (*esph) +crypto_aead_ivsize (aead), elen); -sg_init_one (asg, esph,sizeof (*esph)); + +if ((x->props.flags &XFRM_STATE_ESN )) { +sg_init_table (asg,3 ); +sg_set_buf (asg, &esph->spi,sizeof (__be32)); + *seqhi =XFRM_SKB_CB (skb)->seq.input.hi; +sg_set_buf (asg +1 , seqhi, seqhilen); +sg_set_buf (asg +2 , &esph->seq_no,sizeof (__be32)); + }else +sg_init_one (asg, esph,sizeof (*esph));aead_request_set_callback (req,0 , esp_input_done, skb);aead_request_set_crypt (req, sg, sg, elen, iv); -aead_request_set_assoc (req, asg,sizeof (*esph)); +aead_request_set_assoc (req, asg, assoclen); ret =crypto_aead_decrypt (req);if (ret == -EINPROGRESS )
@@ -443,10 +500,20 @@ static int esp_init_authenc(struct xfrm_state *x) goto error; err = -ENAMETOOLONG ; -if (snprintf (authenc_name,CRYPTO_MAX_ALG_NAME ,"authenc(%s,%s)" , - x->aalg ? x->aalg->alg_name :"digest_null" , - x->ealg->alg_name) >=CRYPTO_MAX_ALG_NAME ) - goto error; + +if ((x->props.flags &XFRM_STATE_ESN )) { +if (snprintf (authenc_name,CRYPTO_MAX_ALG_NAME , +"authencesn(%s,%s)" , + x->aalg ? x->aalg->alg_name :"digest_null" , + x->ealg->alg_name) >=CRYPTO_MAX_ALG_NAME ) + goto error; + }else { +if (snprintf (authenc_name,CRYPTO_MAX_ALG_NAME , +"authenc(%s,%s)" , + x->aalg ? x->aalg->alg_name :"digest_null" , + x->ealg->alg_name) >=CRYPTO_MAX_ALG_NAME ) + goto error; + } aead =crypto_alloc_aead (authenc_name,0 ,0 ); err =PTR_ERR (aead);
Signature · 1 line
1.7.0.4
Steffen Klassert
maintainerRFC PATCH v2 6/9 xfrm: Move IPsec replay detection functions to a separate file
In reply to Steffen KlassertTo support multiple versions of replay detection, we move the replay detection functions to a separate file and make them accessible via function pointers contained in the struct xfrm_replay.
--- include/net/xfrm.h | 24 +++++++-- net/xfrm/Makefile | 2 +- net/xfrm/xfrm_input.c | 5 +- net/xfrm/xfrm_output.c | 15 ++---- net/xfrm/xfrm_replay.c | 141 ++++++++++++++++++++++++++++++++++++++++++++++++ net/xfrm/xfrm_state.c | 111 +------------------------------------ net/xfrm/xfrm_user.c | 4 +- 7 files changed, 174 insertions(+), 128 deletions(-) create mode 100644 net/xfrm/xfrm_replay.c
include/net/xfrm.h +20 -4
@@ -192,6 +192,9 @@ struct xfrm_state {struct xfrm_replay_state preplay;struct xfrm_replay_state_esn *preplay_esn; +/* The functions for replay detection. */ +struct xfrm_replay *repl; +/* internal flag that only holds state for delayed aevent at the * moment */
@@ -261,6 +264,15 @@ struct km_event {struct net *net; }; +struct xfrm_replay { +void (*advance)(struct xfrm_state *x,__be32 net_seq); +int (*check)(struct xfrm_state *x, +struct sk_buff *skb, +__be32 net_seq); +void (*notify)(struct xfrm_state *x,int event); +int (*overflow)(struct xfrm_state *x,struct sk_buff *skb); +}; +struct net_device ;struct xfrm_type ;struct xfrm_dst ;
@@ -693,6 +705,8 @@ extern void xfrm_audit_state_delete(struct xfrm_state *x, int result, u32 auid, u32 ses, u32 secid);extern void xfrm_audit_state_replay_overflow (struct xfrm_state *x,struct sk_buff *skb); +extern void xfrm_audit_state_replay (struct xfrm_state *x, +struct sk_buff *skb,__be32 net_seq);extern void xfrm_audit_state_notfound_simple (struct sk_buff *skb,u16 family);extern void xfrm_audit_state_notfound (struct sk_buff *skb,u16 family,__be32 net_spi,__be32 net_seq);
@@ -725,6 +739,11 @@ static inline void xfrm_audit_state_replay_overflow(struct xfrm_state *x, { } +static inline void xfrm_audit_state_replay (struct xfrm_state *x, +struct sk_buff *skb,__be32 net_seq) +{ +} +static inline void xfrm_audit_state_notfound_simple (struct sk_buff *skb,u16 family) {
@@ -1408,10 +1427,7 @@ extern int xfrm_state_delete(struct xfrm_state *x);extern int xfrm_state_flush (struct net *net,u8 proto,struct xfrm_audit *audit_info);extern void xfrm_sad_getinfo (struct net *net,struct xfrmk_sadinfo *si);extern void xfrm_spd_getinfo (struct net *net,struct xfrmk_spdinfo *si); -extern int xfrm_replay_check (struct xfrm_state *x, -struct sk_buff *skb,__be32 seq); -extern void xfrm_replay_advance (struct xfrm_state *x,__be32 seq); -extern void xfrm_replay_notify (struct xfrm_state *x,int event); +extern int xfrm_init_replay (struct xfrm_state *x);extern int xfrm_state_mtu (struct xfrm_state *x,int mtu);extern int xfrm_init_state (struct xfrm_state *x);extern int xfrm_prepare_input (struct xfrm_state *x,struct sk_buff *skb);
net/xfrm/Makefile +1 -1
@@ -4,7 +4,7 @@ obj-$(CONFIG_XFRM) := xfrm_policy.o xfrm_state.o xfrm_hash.o \ xfrm_input.o xfrm_output.o xfrm_algo.o \ - xfrm_sysctl.o + xfrm_sysctl.o xfrm_replay.o obj-$(CONFIG_XFRM_STATISTICS) += xfrm_proc.o obj-$(CONFIG_XFRM_USER) += xfrm_user.o obj-$(CONFIG_XFRM_IPCOMP) += xfrm_ipcomp.o
net/xfrm/xfrm_input.c +2 -3
@@ -172,7 +172,7 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type) goto drop_unlock; } -if (x->props.replay_window &&xfrm_replay_check (x, skb, seq)) { +if (x->props.replay_window && x->repl->check (x, skb, seq)) {XFRM_INC_STATS (net,LINUX_MIB_XFRMINSTATESEQERROR ); goto drop_unlock; }
@@ -206,8 +206,7 @@ resume:/* only the first xfrm gets the encap type */ encap_type =0 ; -if (x->props.replay_window) -xfrm_replay_advance (x, seq); + x->repl->advance (x, seq); x->curlft.bytes += skb->len; x->curlft.packets++;
net/xfrm/xfrm_output.c +4 -11
@@ -67,17 +67,10 @@ static int xfrm_output_one(struct sk_buff *skb, int err) goto error; } -if (x->type->flags &XFRM_TYPE_REPLAY_PROT ) { -XFRM_SKB_CB (skb)->seq.output.low = ++x->replay.oseq; -if (unlikely (x->replay.oseq ==0 )) { -XFRM_INC_STATS (net,LINUX_MIB_XFRMOUTSTATESEQERROR ); - x->replay.oseq--; -xfrm_audit_state_replay_overflow (x, skb); - err = -EOVERFLOW ; - goto error; - } -if (xfrm_aevent_is_on (net)) -xfrm_replay_notify (x,XFRM_REPLAY_UPDATE ); + err = x->repl->overflow (x, skb); +if (err) { +XFRM_INC_STATS (net,LINUX_MIB_XFRMOUTSTATESEQERROR ); + goto error; } x->curlft.bytes += skb->len;
net/xfrm/xfrm_replay.c new file +141 -0
141 lines not on this page · raw message
net/xfrm/xfrm_state.c +3 -108
147 lines not on this page · raw message
net/xfrm/xfrm_user.c +3 -1
@@ -475,8 +475,10 @@ static struct xfrm_state *xfrm_state_construct(struct net *net, x->preplay.seq = x->replay.seq+x->replay_maxdiff; x->preplay.oseq = x->replay.oseq +x->replay_maxdiff; -/* override default values from above */ +if ((err =xfrm_init_replay (x))) + goto error; +/* override default values from above */ xfrm_update_ae_params (x, attrs);return x;
Signature · 1 line
1.7.0.4
Steffen Klassert
maintainerRFC PATCH v2 7/9 xfrm: Support anti-replay window size bigger than 32 packets
In reply to Steffen KlassertAs it is, the anti-replay bitmap in struct xfrm_replay_state can only accomodate 32 packets. Even though it is possible to configure anti-replay window sizes up to 255 packets from userspace. So we reject any packet with a sequence number within the configured window but outside the bitmap. With this patch, we represent the anti-replay window as a bitmap of variable length that can be accessed via the new struct xfrm_replay_state_esn. Thus, we have no limit on the window size anymore. To use the new anti-replay window implementantion, new userspace tools are required. We leave the old implementation untouched to stay in sync with old userspace tools.
--- net/xfrm/xfrm_replay.c | 207 +++++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 206 insertions(+), 1 deletions(-)
net/xfrm/xfrm_replay.c +206 -1
@@ -1,5 +1,21 @@/* * xfrm_replay.c - xfrm replay detection, derived from xfrm_state.c. +* +* Copyright (C) 2010 secunet Security Networks AG +* Copyright (C) 2010 Steffen Klassert <[email protected]> +* +* This program is free software; you can redistribute it and/or modify it +* under the terms and conditions of the GNU General Public License, +* version 2, as published by the Free Software Foundation. +* +* This program is distributed in the hope it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program; if not, write to the Free Software Foundation, Inc., +* 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. */ #include <net/xfrm.h>
@@ -125,6 +141,178 @@ static void xfrm_replay_advance(struct xfrm_state *x, __be32 net_seq)xfrm_replay_notify (x,XFRM_REPLAY_UPDATE ); } +static int xfrm_replay_overflow_bmp (struct xfrm_state *x,struct sk_buff *skb) +{ +int err =0 ; +struct xfrm_replay_state_esn *replay_esn = x->replay_esn; +struct net *net =xs_net (x); + +if (x->type->flags &XFRM_TYPE_REPLAY_PROT ) { +XFRM_SKB_CB (skb)->seq.output.low = ++replay_esn->oseq; +if (unlikely (replay_esn->oseq ==0 )) { + replay_esn->oseq--; +xfrm_audit_state_replay_overflow (x, skb); + err = -EOVERFLOW ; + +return err; + } +if (xfrm_aevent_is_on (net)) + x->repl->notify (x,XFRM_REPLAY_UPDATE ); + } + +return err; +} + +static int xfrm_replay_check_bmp (struct xfrm_state *x, +struct sk_buff *skb,__be32 net_seq) +{ +unsigned int bitnr, nr; +struct xfrm_replay_state_esn *replay_esn = x->replay_esn; +u32 seq =ntohl (net_seq); +u32 diff = replay_esn->seq - seq; +u32 pos = (replay_esn->seq -1 ) % replay_esn->replay_window; + +if (unlikely (seq ==0 )) + goto err; + +if (likely (seq > replay_esn->seq)) +return 0 ; + +if (diff >= replay_esn->replay_window) { + x->stats.replay_window++; + goto err; + } + +if (pos >= diff) { + bitnr = (pos - diff) % replay_esn->replay_window; + nr = bitnr >>5 ; + bitnr = bitnr &0x1F ; +if (replay_esn->bmp[nr] & (1U << bitnr)) + goto err_replay; + }else { + bitnr = replay_esn->replay_window - (diff - pos); + nr = bitnr >>5 ; + bitnr = bitnr &0x1F ; +if (replay_esn->bmp[nr] & (1U << bitnr)) + goto err_replay; + } +return 0 ; + +err_replay: + x->stats.replay++; +err: +xfrm_audit_state_replay (x, skb, net_seq); +return -EINVAL ; +} + +static void xfrm_replay_advance_bmp (struct xfrm_state *x,__be32 net_seq) +{ +unsigned int bitnr, nr, i; +u32 diff; +struct xfrm_replay_state_esn *replay_esn = x->replay_esn; +u32 seq =ntohl (net_seq); +u32 pos = (replay_esn->seq -1 ) % replay_esn->replay_window; + +if (!replay_esn->replay_window) +return ; + +if (seq > replay_esn->seq) { + diff = seq - replay_esn->seq; + +if (diff < replay_esn->replay_window) { +for (i =1 ; i < diff; i++) { + bitnr = (pos + i) % replay_esn->replay_window; + nr = bitnr >>5 ; + bitnr = bitnr &0x1F ; + replay_esn->bmp[nr] &= ~(1U << bitnr); + } + + bitnr = (pos + diff) % replay_esn->replay_window; + nr = bitnr >>5 ; + bitnr = bitnr &0x1F ; + replay_esn->bmp[nr] |= (1U << bitnr); + }else { + nr = replay_esn->replay_window >>5 ; +for (i =0 ; i <= nr; i++) + replay_esn->bmp[i] =0 ; + + bitnr = (pos + diff) % replay_esn->replay_window; + nr = bitnr >>5 ; + bitnr = bitnr &0x1F ; + replay_esn->bmp[nr] |= (1U << bitnr); + } + + replay_esn->seq = seq; + }else { + diff = replay_esn->seq - seq; + +if (pos >= diff) { + bitnr = (pos - diff) % replay_esn->replay_window; + nr = bitnr >>5 ; + bitnr = bitnr &0x1F ; + replay_esn->bmp[nr] |= (1U << bitnr); + }else { + bitnr = replay_esn->replay_window - (diff - pos); + nr = bitnr >>5 ; + bitnr = bitnr &0x1F ; + replay_esn->bmp[nr] |= (1U << bitnr); + } + } + +if (xfrm_aevent_is_on (xs_net (x))) +xfrm_replay_notify (x,XFRM_REPLAY_UPDATE ); +} + +static void xfrm_replay_notify_bmp (struct xfrm_state *x,int event) +{ +struct km_event c; +struct xfrm_replay_state_esn *replay_esn = x->replay_esn; +struct xfrm_replay_state_esn *preplay_esn = x->preplay_esn; + +/* we send notify messages in case +* 1. we updated on of the sequence numbers, and the seqno difference +* is at least x->replay_maxdiff, in this case we also update the +* timeout of our timer function +* 2. if x->replay_maxage has elapsed since last update, +* and there were changes +* +* The state structure must be locked! +*/ + +switch (event) { +case XFRM_REPLAY_UPDATE : +if (x->replay_maxdiff && + (replay_esn->seq - preplay_esn->seq < x->replay_maxdiff) && + (replay_esn->oseq - preplay_esn->oseq < x->replay_maxdiff)) { +if (x->xflags &XFRM_TIME_DEFER ) + event =XFRM_REPLAY_TIMEOUT ; +else +return ; + } + +break ; + +case XFRM_REPLAY_TIMEOUT : +if (memcmp (x->replay_esn, x->preplay_esn, +xfrm_replay_state_esn_len (replay_esn)) ==0 ) { + x->xflags |=XFRM_TIME_DEFER ; +return ; + } + +break ; + } + +memcpy (x->preplay_esn, x->replay_esn, +xfrm_replay_state_esn_len (replay_esn)); + c.event =XFRM_MSG_NEWAE ; + c.data.aevent = event; +km_state_notify (x, &c); + +if (x->replay_maxage && + !mod_timer (&x->rtimer, jiffies + x->replay_maxage)) + x->xflags &= ~XFRM_TIME_DEFER ; +} +static struct xfrm_replay xfrm_replay_legacy = { .advance = xfrm_replay_advance, .check = xfrm_replay_check,
@@ -132,9 +320,26 @@ static struct xfrm_replay xfrm_replay_legacy = { .overflow = xfrm_replay_overflow, }; +static struct xfrm_replay xfrm_replay_bmp = { + .advance = xfrm_replay_advance_bmp, + .check = xfrm_replay_check_bmp, + .notify = xfrm_replay_notify_bmp, + .overflow = xfrm_replay_overflow_bmp, +}; +int xfrm_init_replay (struct xfrm_state *x) { - x->repl = &xfrm_replay_legacy; +struct xfrm_replay_state_esn *replay_esn = x->replay_esn; + +if (replay_esn) { +if (replay_esn->replay_window > + replay_esn->bmp_len *sizeof (__u32)) +return -EINVAL ; + + x->repl = &xfrm_replay_bmp; + }else + x->repl = &xfrm_replay_legacy; +return 0 ; }
Signature · 1 line
1.7.0.4
Steffen Klassert
maintainerRFC PATCH v2 8/9 xfrm: Add support for IPsec extended sequence numbers
In reply to Steffen KlassertThis patch adds support for IPsec extended sequence numbers (esn) as defined in RFC 4303. The bits to manage the anti-replay window are based on a patch from Alex Badea.
--- include/net/xfrm.h | 1 + net/xfrm/xfrm_input.c | 4 + net/xfrm/xfrm_replay.c | 190 +++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 194 insertions(+), 1 deletions(-)
include/net/xfrm.h +1 -0
@@ -1427,6 +1427,7 @@ extern int xfrm_state_delete(struct xfrm_state *x);extern int xfrm_state_flush (struct net *net,u8 proto,struct xfrm_audit *audit_info);extern void xfrm_sad_getinfo (struct net *net,struct xfrmk_sadinfo *si);extern void xfrm_spd_getinfo (struct net *net,struct xfrmk_spdinfo *si); +extern u32 xfrm_replay_seqhi (struct xfrm_state *x,__be32 net_seq);extern int xfrm_init_replay (struct xfrm_state *x);extern int xfrm_state_mtu (struct xfrm_state *x,int mtu);extern int xfrm_init_state (struct xfrm_state *x);
net/xfrm/xfrm_input.c +4 -0
@@ -107,6 +107,7 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)struct net *net =dev_net (skb->dev);int err;__be32 seq; +__be32 seq_hi;struct xfrm_state *x;xfrm_address_t *daddr;struct xfrm_mode *inner_mode;
@@ -184,7 +185,10 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)spin_unlock (&x->lock); + seq_hi =htonl (xfrm_replay_seqhi (x, seq)); +XFRM_SKB_CB (skb)->seq.input.low = seq; +XFRM_SKB_CB (skb)->seq.input.hi = seq_hi; nexthdr = x->type->input (x, skb);
net/xfrm/xfrm_replay.c +189 -1
218 lines not on this page · raw message
Signature · 1 line
1.7.0.4
Steffen Klassert
maintainerRFC PATCH v2 9/9 xfrm: Add user interface for esn and big anti-replay windows
In reply to Steffen KlassertThis patch adds a netlink based user interface to configure esn and big anti-replay windows. The new netlink attribute XFRMA_REPLAY_ESN_VAL is used to configure the new implementation. If the XFRM_STATE_ESN flag is set, we use esn and support for big anti-replay windows for the configured state. If this flag is not set we use the new implementation with 32 bit sequence numbers. A big anti-replay window can be configured in this case anyway.
--- net/xfrm/xfrm_state.c | 2 + net/xfrm/xfrm_user.c | 99 ++++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 87 insertions(+), 14 deletions(-)
net/xfrm/xfrm_state.c +2 -0
@@ -356,6 +356,8 @@ static void xfrm_state_gc_destroy(struct xfrm_state *x)kfree (x->calg);kfree (x->encap);kfree (x->coaddr); +kfree (x->replay_esn); +kfree (x->preplay_esn);if (x->inner_mode)xfrm_put_mode (x->inner_mode);if (x->inner_mode_iaf)
net/xfrm/xfrm_user.c +85 -14
193 lines not on this page · raw message
Signature · 1 line
1.7.0.4
Steffen Klassert
maintainerRFC PATCH 1/1 iproute2: Add IPsec extended sequence number support
In reply to Steffen Klassert---
The patch is based on branch 'net-next' ofgit://git.kernel.org/pub/scm/linux/kernel/git/shemminger/iproute2.git
include/linux/xfrm.h | 12 ++++++++++++ ip/ipxfrm.c | 8 +++++++- ip/xfrm_state.c | 35 ++++++++++++++++++++++++++++------- 3 files changed, 47 insertions(+), 8 deletions(-)
include/linux/xfrm.h +12 -0
@@ -84,6 +84,16 @@ struct xfrm_replay_state {__u32 bitmap; }; +struct xfrm_replay_state_esn { +unsigned int bmp_len; +__u32 oseq; +__u32 seq; +__u32 oseq_hi; +__u32 seq_hi; +__u32 replay_window; +__u32 bmp[0 ]; +}; +struct xfrm_algo {char alg_name[64 ];unsigned int alg_key_len;/* in bits */
@@ -284,6 +294,7 @@ enum xfrm_attr_type_t {XFRMA_ALG_AUTH_TRUNC ,/* struct xfrm_algo_auth */ XFRMA_MARK ,/* struct xfrm_mark */ XFRMA_TFCPAD ,/* __u32 */ +XFRMA_REPLAY_ESN_VAL ,/* struct xfrm_replay_esn */ __XFRMA_MAX#define XFRMA_MAX (__XFRMA_MAX - 1)
@@ -351,6 +362,7 @@ struct xfrm_usersa_info {#define XFRM_STATE_ICMP 16#define XFRM_STATE_AF_UNSPEC 32#define XFRM_STATE_ALIGN4 64 +#define XFRM_STATE_ESN 128 };struct xfrm_usersa_id {
ip/ipxfrm.c +7 -1
@@ -691,6 +691,12 @@ done:void xfrm_xfrma_print (struct rtattr *tb[],__u16 family,FILE *fp,const char *prefix) { + +if (tb[XFRMA_REPLAY_ESN_VAL ]) { +struct rtattr *rta = tb[XFRMA_REPLAY_ESN_VAL ]; +struct xfrm_replay_state_esn *repl = (struct xfrm_replay_state_esn *)RTA_DATA (rta); +fprintf (fp,"\treplay-window %u\n" , repl->replay_window); + }if (tb[XFRMA_MARK ]) {struct rtattr *rta = tb[XFRMA_MARK ];struct xfrm_mark *m = (struct xfrm_mark *)RTA_DATA (rta);
@@ -841,7 +847,6 @@ void xfrm_state_info_print(struct xfrm_usersa_info *xsinfo,STRBUF_CAT (buf,"\t" );fputs (buf, fp); -fprintf (fp,"replay-window %u " , xsinfo->replay_window);if (show_stats >0 )fprintf (fp,"seq 0x%08u " , xsinfo->seq);if (show_stats >0 || xsinfo->flags) {
@@ -855,6 +860,7 @@ void xfrm_state_info_print(struct xfrm_usersa_info *xsinfo,XFRM_FLAG_PRINT (fp, flags,XFRM_STATE_ICMP ,"icmp" );XFRM_FLAG_PRINT (fp, flags,XFRM_STATE_AF_UNSPEC ,"af-unspec" );XFRM_FLAG_PRINT (fp, flags,XFRM_STATE_ALIGN4 ,"align4" ); +XFRM_FLAG_PRINT (fp, flags,XFRM_STATE_ESN ,"replay-esn" );if (flags)fprintf (fp,"%x" , flags); }
ip/xfrm_state.c +28 -7
@@ -51,6 +51,7 @@#define RTA_BUF_SIZE 2048#define XFRM_ALGO_KEY_BUF_SIZE 512#define CTX_BUF_SIZE 256 +#define XFRM_REPLAY_BMP_SIZE_U32 16static void usage (void ) __attribute__((noreturn));
@@ -59,7 +60,7 @@ static void usage(void)fprintf (stderr,"Usage: ip xfrm state { add | update } ID [ XFRM_OPT ] [ ctx SEC_CTX ] [ mode MODE ]\n" );fprintf (stderr," [ reqid REQID ] [ seq SEQ ] [ replay-window SIZE ] [ flag FLAG-LIST ]\n" );fprintf (stderr," [ encap ENCAP ] [ sel SELECTOR ] [ replay-seq SEQ ]\n" ); -fprintf (stderr," [ replay-oseq SEQ ] [ LIMIT-LIST ]\n" ); +fprintf (stderr," [ replay-oseq SEQ ] [ replay-seqhi SEQ ] [ replay-oseqhi SEQ ] [ LIMIT-LIST ]\n" );fprintf (stderr,"Usage: ip xfrm state allocspi ID [ mode MODE ] [ reqid REQID ] [ seq SEQ ]\n" );fprintf (stderr," [ min SPI max SPI ]\n" );fprintf (stderr,"Usage: ip xfrm state { delete | get } ID\n" );
@@ -218,6 +219,8 @@ static int xfrm_state_flag_parse(__u8 *flags, int *argcp, char ***argvp) *flags |=XFRM_STATE_AF_UNSPEC ; else if (strcmp(*argv, "align4") == 0) *flags |= XFRM_STATE_ALIGN4; + else if (strcmp(*argv, "replay-esn") == 0) + *flags |=XFRM_STATE_ESN ; else {PREV_ARG ();/* back track */ break ;
@@ -243,7 +246,11 @@ static int xfrm_state_modify(int cmd, unsigned flags, int argc, char **argv)struct xfrm_usersa_info xsinfo;char buf[RTA_BUF_SIZE ]; } req; -struct xfrm_replay_state replay; +struct { +struct xfrm_replay_state_esn state; +__u32 bmp[XFRM_REPLAY_BMP_SIZE_U32 ]; + } replay; +char *idp =NULL ;char *aeadop =NULL ;char *ealgop =NULL ;
@@ -258,9 +265,12 @@ static int xfrm_state_modify(int cmd, unsigned flags, int argc, char **argv) } ctx;memset (&req,0 ,sizeof (req)); +memset (&replay,0 ,sizeof (replay));memset (&ctx,0 ,sizeof (ctx)); + replay.state.bmp_len =XFRM_REPLAY_BMP_SIZE_U32 ; + req.n.nlmsg_len =NLMSG_LENGTH (sizeof (req.xsinfo)); req.n.nlmsg_flags =NLM_F_REQUEST |flags; req.n.nlmsg_type = cmd;
@@ -285,16 +295,24 @@ static int xfrm_state_modify(int cmd, unsigned flags, int argc, char **argv)xfrm_seq_parse (&req.xsinfo.seq, &argc, &argv); }else if (strcmp (*argv,"replay-window" ) ==0 ) {NEXT_ARG (); -if (get_u8 (&req.xsinfo.replay_window, *argv,0 )) +if (get_u32 (&replay.state.replay_window, *argv,0 ))invarg ("\"replay-window\" value is invalid" , *argv); }else if (strcmp (*argv,"replay-seq" ) ==0 ) {NEXT_ARG (); -if (get_u32 (&replay.seq, *argv,0 )) +if (get_u32 (&replay.state.seq, *argv,0 ))invarg ("\"replay-seq\" value is invalid" , *argv); }else if (strcmp (*argv,"replay-oseq" ) ==0 ) {NEXT_ARG (); -if (get_u32 (&replay.oseq, *argv,0 )) +if (get_u32 (&replay.state.oseq, *argv,0 ))invarg ("\"replay-oseq\" value is invalid" , *argv); + }else if (strcmp (*argv,"replay-seqhi" ) ==0 ) { +NEXT_ARG (); +if (get_u32 (&replay.state.seq_hi, *argv,0 )) +invarg ("\"replay-seqhi\" value is invalid" , *argv); + }else if (strcmp (*argv,"replay-oseqhi" ) ==0 ) { +NEXT_ARG (); +if (get_u32 (&replay.state.oseq_hi, *argv,0 )) +invarg ("\"replay-oseqhi\" value is invalid" , *argv); }else if (strcmp (*argv,"flag" ) ==0 ) {NEXT_ARG ();xfrm_state_flag_parse (&req.xsinfo.flags, &argc, &argv);
@@ -472,9 +490,12 @@ static int xfrm_state_modify(int cmd, unsigned flags, int argc, char **argv) argc--; argv++; } -if (replay.seq || replay.oseq) -addattr_l (&req.n,sizeof (req.buf),XFRMA_REPLAY_VAL , +if (replay.state.replay_window || replay.state.seq || replay.state.oseq || + replay.state.seq_hi || replay.state.oseq_hi ) { + +addattr_l (&req.n,sizeof (req.buf),XFRMA_REPLAY_ESN_VAL , (void *)&replay,sizeof (replay)); + }if (!idp) {fprintf (stderr,"Not enough information: \"ID\" is required\n" );
Signature · 1 line
1.7.0.4