>From d503604d592dac8232780d9442b67c4b051cf602 Mon Sep 17 00:00:00 2001 From: Alex Badea Date: Thu, 18 Jun 2009 17:07:45 +0300 Subject: [PATCH] ipsec: Extended Sequence Numbers support for ESP --- src/include/net/esp.h | 14 ++++++++++++-- src/net/ipv4/esp4.c | 18 +++++++++++++++--- src/net/ipv6/esp6.c | 15 +++++++++++++-- 3 files changed, 40 insertions(+), 7 deletions(-) diff --git a/src/include/net/esp.h b/src/include/net/esp.h index a513d14..d39711c 100644 --- a/src/include/net/esp.h +++ b/src/include/net/esp.h @@ -2,6 +2,7 @@ #define _NET_ESP_H #include +#include struct esp_data { @@ -28,8 +29,10 @@ struct esp_data int icv_trunc_len; void (*icv)(struct esp_data*, struct sk_buff *skb, - int offset, int len, u8 *icv); + int offset, int len, + u32 seq_hi, u8 *icv); struct crypto_tfm *tfm; + unsigned esn:1; /* Extended Sequence Number enabled */ } auth; }; @@ -39,7 +42,7 @@ extern void *pskb_put(struct sk_buff *skb, struct sk_buff *tail, int len); static inline void esp_hmac_digest(struct esp_data *esp, struct sk_buff *skb, int offset, - int len, u8 *auth_data) + int len, u32 seq_hi, u8 *auth_data) { struct crypto_tfm *tfm = esp->auth.tfm; char *icv = esp->auth.work_icv; @@ -47,6 +50,13 @@ esp_hmac_digest(struct esp_data *esp, struct sk_buff *skb, int offset, memset(auth_data, 0, esp->auth.icv_trunc_len); crypto_hmac_init(tfm, esp->auth.key, &esp->auth.key_len); skb_icv_walk(skb, tfm, offset, len, crypto_hmac_update); + if (unlikely(esp->auth.esn)) { + struct scatterlist sg; + sg.page = virt_to_page(&seq_hi); + sg.offset = offset_in_page(&seq_hi); + sg.length = sizeof(u32); + crypto_hmac_update(tfm, &sg, 1); + } crypto_hmac_final(tfm, esp->auth.key, &esp->auth.key_len, icv); memcpy(auth_data, icv, esp->auth.icv_trunc_len); } diff --git a/src/net/ipv4/esp4.c b/src/net/ipv4/esp4.c index 014dd87..6b73373 100644 --- a/src/net/ipv4/esp4.c +++ b/src/net/ipv4/esp4.c @@ -209,6 +209,8 @@ int esp_output(struct sk_buff **pskb) esph->spi = x->id.spi; esph->seq_no = htonl(++x->replay.oseq); + if (unlikely(!x->replay.oseq)) + x->replay_ext.oseq_hi++; if (esp->conf.ivlen) crypto_cipher_set_iv(tfm, esp->conf.ivec, crypto_tfm_alg_ivsize(tfm)); @@ -234,8 +236,11 @@ int esp_output(struct sk_buff **pskb) } if (esp->auth.icv_full_len) { + printk("%s: oseq=%u oseq_hi=%d\n", __FUNCTION__, x->replay.oseq, x->replay_ext.oseq_hi); esp->auth.icv(esp, *pskb, (u8*)esph-(*pskb)->data, - sizeof(struct ip_esp_hdr) + esp->conf.ivlen+clen, trailer->tail); + sizeof(struct ip_esp_hdr) + esp->conf.ivlen+clen, + x->replay_ext.oseq_hi, + trailer->tail); pskb_put(*pskb, trailer, alen); } @@ -286,8 +291,13 @@ int esp_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_bu if (esp->auth.icv_full_len) { u8 sum[esp->auth.icv_full_len]; u8 sum1[alen]; - - esp->auth.icv(esp, skb, 0, skb->len-alen, sum); + + u32 seq_hi = 0; + if (x->props.flags & XFRM_STATE_ESN) { + u32 seq = ((struct ip_esp_hdr *) skb->data)->seq_no; + seq_hi = xfrm_replay_seqhi(x, seq); + } + esp->auth.icv(esp, skb, 0, skb->len-alen, seq_hi, sum); if (skb_copy_bits(skb, skb->len-alen, sum1, alen)) BUG(); @@ -539,6 +549,8 @@ int esp_init_state(struct xfrm_state *x, void *args) if (esp->auth.tfm == NULL) goto error; esp->auth.icv = esp_hmac_digest; + if (x->props.flags & XFRM_STATE_ESN) + esp->auth.esn = 1; aalg_desc = xfrm_aalg_get_byname(x->aalg->alg_name); BUG_ON(!aalg_desc); diff --git a/src/net/ipv6/esp6.c b/src/net/ipv6/esp6.c index 6ad9c12..6b9a27e 100644 --- a/src/net/ipv6/esp6.c +++ b/src/net/ipv6/esp6.c @@ -163,6 +163,8 @@ int esp6_output(struct sk_buff **pskb) esph->spi = x->id.spi; esph->seq_no = htonl(++x->replay.oseq); + if (unlikely(!x->replay.oseq)) + x->replay_ext.oseq_hi++; if (esp->conf.ivlen) crypto_cipher_set_iv(tfm, esp->conf.ivec, crypto_tfm_alg_ivsize(tfm)); @@ -189,7 +191,9 @@ int esp6_output(struct sk_buff **pskb) if (esp->auth.icv_full_len) { esp->auth.icv(esp, *pskb, (u8*)esph-(*pskb)->data, - sizeof(struct ipv6_esp_hdr) + esp->conf.ivlen+clen, trailer->tail); + sizeof(struct ipv6_esp_hdr) + esp->conf.ivlen+clen, + x->replay_ext.oseq_hi, + trailer->tail); pskb_put(*pskb, trailer, alen); } @@ -248,7 +252,12 @@ int esp6_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_b u8 sum[esp->auth.icv_full_len]; u8 sum1[alen]; - esp->auth.icv(esp, skb, 0, skb->len-alen, sum); + u32 seq_hi = 0; + if (x->props.flags & XFRM_STATE_ESN) { + u32 seq = ((struct ipv6_esp_hdr *) skb->data)->seq_no; + seq_hi = xfrm_replay_seqhi(x, seq); + } + esp->auth.icv(esp, skb, 0, skb->len-alen, seq_hi, sum); if (skb_copy_bits(skb, skb->len-alen, sum1, alen)) BUG(); @@ -409,6 +418,8 @@ int esp6_init_state(struct xfrm_state *x, void *args) if (esp->auth.tfm == NULL) goto error; esp->auth.icv = esp_hmac_digest; + if (x->props.flags & XFRM_STATE_ESN) + esp->auth.esn = 1; aalg_desc = xfrm_aalg_get_byname(x->aalg->alg_name); BUG_ON(!aalg_desc); -- 1.5.4.3