aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/ah4.c
diff options
context:
space:
mode:
authorFan Du <fan.du@windriver.com>2014-01-17 20:54:25 -0500
committerSteffen Klassert <steffen.klassert@secunet.com>2014-02-12 01:02:10 -0500
commitd8b2a8600b0ea002985d65bba4a94642a01bfe4c (patch)
treee376ed01fc0e38439a2d262693b87e772f48651a /net/ipv4/ah4.c
parentd4d573d0334d07341beffdcf97e2b85d3955d8ae (diff)
{IPv4,xfrm} Add ESN support for AH ingress part
This patch add esn support for AH input stage by attaching upper 32bits sequence number right after packet payload as specified by RFC 4302. Then the ICV value will guard upper 32bits sequence number as well when packet getting in. Signed-off-by: Fan Du <fan.du@windriver.com> Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
Diffstat (limited to 'net/ipv4/ah4.c')
-rw-r--r--net/ipv4/ah4.c27
1 files changed, 22 insertions, 5 deletions
diff --git a/net/ipv4/ah4.c b/net/ipv4/ah4.c
index c6accacc3a2b..54b965ddcb19 100644
--- a/net/ipv4/ah4.c
+++ b/net/ipv4/ah4.c
@@ -309,6 +309,10 @@ static int ah_input(struct xfrm_state *x, struct sk_buff *skb)
309 struct ip_auth_hdr *ah; 309 struct ip_auth_hdr *ah;
310 struct ah_data *ahp; 310 struct ah_data *ahp;
311 int err = -ENOMEM; 311 int err = -ENOMEM;
312 int seqhi_len = 0;
313 __be32 *seqhi;
314 int sglists = 0;
315 struct scatterlist *seqhisg;
312 316
313 if (!pskb_may_pull(skb, sizeof(*ah))) 317 if (!pskb_may_pull(skb, sizeof(*ah)))
314 goto out; 318 goto out;
@@ -349,14 +353,22 @@ static int ah_input(struct xfrm_state *x, struct sk_buff *skb)
349 iph = ip_hdr(skb); 353 iph = ip_hdr(skb);
350 ihl = ip_hdrlen(skb); 354 ihl = ip_hdrlen(skb);
351 355
352 work_iph = ah_alloc_tmp(ahash, nfrags, ihl + ahp->icv_trunc_len); 356 if (x->props.flags & XFRM_STATE_ESN) {
357 sglists = 1;
358 seqhi_len = sizeof(*seqhi);
359 }
360
361 work_iph = ah_alloc_tmp(ahash, nfrags + sglists, ihl +
362 ahp->icv_trunc_len + seqhi_len);
353 if (!work_iph) 363 if (!work_iph)
354 goto out; 364 goto out;
355 365
356 auth_data = ah_tmp_auth(work_iph, ihl); 366 seqhi = (__be32 *)((char *)work_iph + ihl);
367 auth_data = ah_tmp_auth(seqhi, seqhi_len);
357 icv = ah_tmp_icv(ahash, auth_data, ahp->icv_trunc_len); 368 icv = ah_tmp_icv(ahash, auth_data, ahp->icv_trunc_len);
358 req = ah_tmp_req(ahash, icv); 369 req = ah_tmp_req(ahash, icv);
359 sg = ah_req_sg(ahash, req); 370 sg = ah_req_sg(ahash, req);
371 seqhisg = sg + nfrags;
360 372
361 memcpy(work_iph, iph, ihl); 373 memcpy(work_iph, iph, ihl);
362 memcpy(auth_data, ah->auth_data, ahp->icv_trunc_len); 374 memcpy(auth_data, ah->auth_data, ahp->icv_trunc_len);
@@ -375,10 +387,15 @@ static int ah_input(struct xfrm_state *x, struct sk_buff *skb)
375 387
376 skb_push(skb, ihl); 388 skb_push(skb, ihl);
377 389
378 sg_init_table(sg, nfrags); 390 sg_init_table(sg, nfrags + sglists);
379 skb_to_sgvec(skb, sg, 0, skb->len); 391 skb_to_sgvec_nomark(skb, sg, 0, skb->len);
380 392
381 ahash_request_set_crypt(req, sg, icv, skb->len); 393 if (x->props.flags & XFRM_STATE_ESN) {
394 /* Attach seqhi sg right after packet payload */
395 *seqhi = XFRM_SKB_CB(skb)->seq.input.hi;
396 sg_set_buf(seqhisg, seqhi, seqhi_len);
397 }
398 ahash_request_set_crypt(req, sg, icv, skb->len + seqhi_len);
382 ahash_request_set_callback(req, 0, ah_input_done, skb); 399 ahash_request_set_callback(req, 0, ah_input_done, skb);
383 400
384 AH_SKB_CB(skb)->tmp = work_iph; 401 AH_SKB_CB(skb)->tmp = work_iph;