>From 8c573d0716e88e514a7064991838f6a482e861f4 Mon Sep 17 00:00:00 2001 From: Alex Badea Date: Thu, 18 Jun 2009 17:12:23 +0300 Subject: [PATCH] ipsec: Extended Sequence Numbers support for AH --- src/include/net/ah.h | 14 ++++++++++++-- src/net/ipv4/ah4.c | 12 ++++++++++-- src/net/ipv6/ah6.c | 12 ++++++++++-- 3 files changed, 32 insertions(+), 6 deletions(-) diff --git a/src/include/net/ah.h b/src/include/net/ah.h index ceff00a..9b7b4fb 100644 --- a/src/include/net/ah.h +++ b/src/include/net/ah.h @@ -2,6 +2,7 @@ #define _NET_AH_H #include +#include /* This is the maximum truncated ICV length that we know of. */ #define MAX_AH_AUTH_LEN 12 @@ -15,19 +16,28 @@ struct ah_data int icv_trunc_len; void (*icv)(struct ah_data*, - struct sk_buff *skb, u8 *icv); + struct sk_buff *skb, + u32 seq_hi, u8 *icv); struct crypto_tfm *tfm; + unsigned esn:1; }; static inline void -ah_hmac_digest(struct ah_data *ahp, struct sk_buff *skb, u8 *auth_data) +ah_hmac_digest(struct ah_data *ahp, struct sk_buff *skb, u32 seq_hi, u8 *auth_data) { struct crypto_tfm *tfm = ahp->tfm; memset(auth_data, 0, ahp->icv_trunc_len); crypto_hmac_init(tfm, ahp->key, &ahp->key_len); skb_icv_walk(skb, tfm, 0, skb->len, crypto_hmac_update); + if (unlikely(ahp->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, ahp->key, &ahp->key_len, ahp->work_icv); memcpy(auth_data, ahp->work_icv, ahp->icv_trunc_len); } diff --git a/src/net/ipv4/ah4.c b/src/net/ipv4/ah4.c index 0d62398..c0cc4b1 100644 --- a/src/net/ipv4/ah4.c +++ b/src/net/ipv4/ah4.c @@ -121,7 +121,9 @@ static int ah_output(struct sk_buff **pskb) ah->reserved = 0; ah->spi = x->id.spi; ah->seq_no = htonl(++x->replay.oseq); - ahp->icv(ahp, *pskb, ah->auth_data); + if (unlikely(!x->replay.oseq)) + x->replay_ext.oseq_hi++; + ahp->icv(ahp, *pskb, x->replay_ext.oseq_hi, ah->auth_data); top_iph->tos = iph->tos; top_iph->ttl = iph->ttl; if (x->props.mode) { @@ -202,9 +204,13 @@ int ah_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buf { u8 auth_data[MAX_AH_AUTH_LEN]; + u32 seq_hi = 0; + if (x->props.flags & XFRM_STATE_ESN) + seq_hi = xfrm_replay_seqhi(x, ah->seq_no); + memcpy(auth_data, ah->auth_data, ahp->icv_trunc_len); skb_push(skb, skb->data - skb->nh.raw); - ahp->icv(ahp, skb, ah->auth_data); + ahp->icv(ahp, skb, seq_hi, ah->auth_data); if (memcmp(ah->auth_data, auth_data, ahp->icv_trunc_len)) { x->stats.integrity_failed++; goto out; @@ -265,6 +271,8 @@ static int ah_init_state(struct xfrm_state *x, void *args) if (!ahp->tfm) goto error; ahp->icv = ah_hmac_digest; + if (x->props.flags & XFRM_STATE_ESN) + ahp->esn = 1; /* * Lookup the algorithm description maintained by xfrm_algo, diff --git a/src/net/ipv6/ah6.c b/src/net/ipv6/ah6.c index 185092c..67db5c2 100644 --- a/src/net/ipv6/ah6.c +++ b/src/net/ipv6/ah6.c @@ -213,7 +213,9 @@ int ah6_output(struct sk_buff **pskb) ah->reserved = 0; ah->spi = x->id.spi; ah->seq_no = htonl(++x->replay.oseq); - ahp->icv(ahp, *pskb, ah->auth_data); + if (unlikely(!x->replay.oseq)) + x->replay_ext.oseq_hi++; + ahp->icv(ahp, *pskb, x->replay_ext.oseq_hi, ah->auth_data); if (x->props.mode) { (*pskb)->nh.ipv6h->hop_limit = iph->hop_limit; @@ -320,10 +322,14 @@ int ah6_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_bu { u8 auth_data[MAX_AH_AUTH_LEN]; + u32 seq_hi = 0; + if (x->props.flags & XFRM_STATE_ESN) + seq_hi = xfrm_replay_seqhi(x, ah->seq_no); + memcpy(auth_data, ah->auth_data, ahp->icv_trunc_len); memset(ah->auth_data, 0, ahp->icv_trunc_len); skb_push(skb, skb->data - skb->nh.raw); - ahp->icv(ahp, skb, ah->auth_data); + ahp->icv(ahp, skb, seq_hi, ah->auth_data); if (memcmp(ah->auth_data, auth_data, ahp->icv_trunc_len)) { LIMIT_NETDEBUG( printk(KERN_WARNING "ipsec ah authentication error\n")); @@ -402,6 +408,8 @@ static int ah6_init_state(struct xfrm_state *x, void *args) if (!ahp->tfm) goto error; ahp->icv = ah_hmac_digest; + if (x->props.flags & XFRM_STATE_ESN) + ahp->esn = 1; /* * Lookup the algorithm description maintained by xfrm_algo, -- 1.5.4.3