1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Copyright (C)2002 USAGI/WIDE Project 4 * 5 * Authors 6 * 7 * Mitsuru KANDA @USAGI : IPv6 Support 8 * Kazunori MIYAZAWA @USAGI : 9 * Kunihiro Ishiguro <kunihiro@ipinfusion.com> 10 * 11 * This file is derived from net/ipv4/ah.c. 12 */ 13 14 #define pr_fmt(fmt) "IPv6: " fmt 15 16 #include <crypto/hash.h> 17 #include <crypto/utils.h> 18 #include <linux/module.h> 19 #include <linux/slab.h> 20 #include <net/ip.h> 21 #include <net/ah.h> 22 #include <linux/crypto.h> 23 #include <linux/pfkeyv2.h> 24 #include <linux/string.h> 25 #include <linux/scatterlist.h> 26 #include <net/ip6_route.h> 27 #include <net/icmp.h> 28 #include <net/ipv6.h> 29 #include <net/protocol.h> 30 #include <net/xfrm.h> 31 32 #define IPV6HDR_BASELEN 8 33 34 struct tmp_ext { 35 #if IS_ENABLED(CONFIG_IPV6_MIP6) 36 struct in6_addr saddr; 37 #endif 38 struct in6_addr daddr; 39 char hdrs[]; 40 }; 41 42 struct ah_skb_cb { 43 struct xfrm_skb_cb xfrm; 44 void *tmp; 45 }; 46 47 #define AH_SKB_CB(__skb) ((struct ah_skb_cb *)&((__skb)->cb[0])) 48 49 /* Helper to save IPv6 addresses and extension headers to temporary storage */ 50 static inline void ah6_save_hdrs(struct tmp_ext *iph_ext, 51 struct ipv6hdr *top_iph, int extlen) 52 { 53 if (!extlen) 54 return; 55 56 #if IS_ENABLED(CONFIG_IPV6_MIP6) 57 iph_ext->saddr = top_iph->saddr; 58 #endif 59 iph_ext->daddr = top_iph->daddr; 60 memcpy(&iph_ext->hdrs, top_iph + 1, extlen - sizeof(*iph_ext)); 61 } 62 63 /* Helper to restore IPv6 addresses and extension headers from temporary storage */ 64 static inline void ah6_restore_hdrs(struct ipv6hdr *top_iph, 65 struct tmp_ext *iph_ext, int extlen) 66 { 67 if (!extlen) 68 return; 69 70 #if IS_ENABLED(CONFIG_IPV6_MIP6) 71 top_iph->saddr = iph_ext->saddr; 72 #endif 73 top_iph->daddr = iph_ext->daddr; 74 memcpy(top_iph + 1, &iph_ext->hdrs, extlen - sizeof(*iph_ext)); 75 } 76 77 static void *ah_alloc_tmp(struct crypto_ahash *ahash, int nfrags, 78 unsigned int size) 79 { 80 unsigned int len; 81 82 len = size + crypto_ahash_digestsize(ahash); 83 84 len = ALIGN(len, crypto_tfm_ctx_alignment()); 85 86 len += sizeof(struct ahash_request) + crypto_ahash_reqsize(ahash); 87 len = ALIGN(len, __alignof__(struct scatterlist)); 88 89 len += sizeof(struct scatterlist) * nfrags; 90 91 return kmalloc(len, GFP_ATOMIC); 92 } 93 94 static inline struct tmp_ext *ah_tmp_ext(void *base) 95 { 96 return base + IPV6HDR_BASELEN; 97 } 98 99 static inline u8 *ah_tmp_auth(u8 *tmp, unsigned int offset) 100 { 101 return tmp + offset; 102 } 103 104 static inline u8 *ah_tmp_icv(void *tmp, unsigned int offset) 105 { 106 return tmp + offset; 107 } 108 109 static inline struct ahash_request *ah_tmp_req(struct crypto_ahash *ahash, 110 u8 *icv) 111 { 112 struct ahash_request *req; 113 114 req = (void *)PTR_ALIGN(icv + crypto_ahash_digestsize(ahash), 115 crypto_tfm_ctx_alignment()); 116 117 ahash_request_set_tfm(req, ahash); 118 119 return req; 120 } 121 122 static inline struct scatterlist *ah_req_sg(struct crypto_ahash *ahash, 123 struct ahash_request *req) 124 { 125 return (void *)ALIGN((unsigned long)(req + 1) + 126 crypto_ahash_reqsize(ahash), 127 __alignof__(struct scatterlist)); 128 } 129 130 static bool zero_out_mutable_opts(struct ipv6_opt_hdr *opthdr) 131 { 132 u8 *opt = (u8 *)opthdr; 133 int len = ipv6_optlen(opthdr); 134 int off = 0; 135 int optlen = 0; 136 137 off += 2; 138 len -= 2; 139 140 while (len > 0) { 141 142 switch (opt[off]) { 143 144 case IPV6_TLV_PAD1: 145 optlen = 1; 146 break; 147 default: 148 if (len < 2) 149 goto bad; 150 optlen = opt[off+1]+2; 151 if (len < optlen) 152 goto bad; 153 if (opt[off] & 0x20) 154 memset(&opt[off+2], 0, opt[off+1]); 155 break; 156 } 157 158 off += optlen; 159 len -= optlen; 160 } 161 if (len == 0) 162 return true; 163 164 bad: 165 return false; 166 } 167 168 #if IS_ENABLED(CONFIG_IPV6_MIP6) 169 /** 170 * ipv6_rearrange_destopt - rearrange IPv6 destination options header 171 * @iph: IPv6 header 172 * @destopt: destionation options header 173 */ 174 static void ipv6_rearrange_destopt(struct ipv6hdr *iph, struct ipv6_opt_hdr *destopt) 175 { 176 u8 *opt = (u8 *)destopt; 177 int len = ipv6_optlen(destopt); 178 int off = 0; 179 int optlen = 0; 180 181 off += 2; 182 len -= 2; 183 184 while (len > 0) { 185 186 switch (opt[off]) { 187 188 case IPV6_TLV_PAD1: 189 optlen = 1; 190 break; 191 default: 192 if (len < 2) 193 goto bad; 194 optlen = opt[off+1]+2; 195 if (len < optlen) 196 goto bad; 197 198 /* Rearrange the source address in @iph and the 199 * addresses in home address option for final source. 200 * See 11.3.2 of RFC 3775 for details. 201 */ 202 if (opt[off] == IPV6_TLV_HAO) { 203 struct ipv6_destopt_hao *hao; 204 205 hao = (struct ipv6_destopt_hao *)&opt[off]; 206 if (hao->length != sizeof(hao->addr)) { 207 net_warn_ratelimited("destopt hao: invalid header length: %u\n", 208 hao->length); 209 goto bad; 210 } 211 swap(hao->addr, iph->saddr); 212 } 213 break; 214 } 215 216 off += optlen; 217 len -= optlen; 218 } 219 /* Note: ok if len == 0 */ 220 bad: 221 return; 222 } 223 #else 224 static void ipv6_rearrange_destopt(struct ipv6hdr *iph, struct ipv6_opt_hdr *destopt) {} 225 #endif 226 227 /** 228 * ipv6_rearrange_rthdr - rearrange IPv6 routing header 229 * @iph: IPv6 header 230 * @rthdr: routing header 231 * 232 * Rearrange the destination address in @iph and the addresses in @rthdr 233 * so that they appear in the order they will at the final destination. 234 * See Appendix A2 of RFC 2402 for details. 235 * 236 * Return: 0 on success, -EINVAL if segments_left exceeds the number of 237 * addresses described by hdrlen. 238 */ 239 static int ipv6_rearrange_rthdr(struct ipv6hdr *iph, struct ipv6_rt_hdr *rthdr) 240 { 241 unsigned int segments, segments_left; 242 struct in6_addr *addrs; 243 struct in6_addr final_addr; 244 245 segments_left = rthdr->segments_left; 246 if (segments_left == 0) 247 return 0; 248 249 /* Raw locally generated packets can reach AH6 without the invariant 250 * required by the rt0-style address rearrangement below. 251 */ 252 segments = rthdr->hdrlen >> 1; 253 if (segments_left > segments) 254 return -EINVAL; 255 256 rthdr->segments_left = 0; 257 258 addrs = ((struct rt0_hdr *)rthdr)->addr; 259 final_addr = addrs[segments - 1]; 260 261 addrs += segments - segments_left; 262 memmove(addrs + 1, addrs, (segments_left - 1) * sizeof(*addrs)); 263 264 addrs[0] = iph->daddr; 265 iph->daddr = final_addr; 266 267 return 0; 268 } 269 270 static int ipv6_clear_mutable_options(struct ipv6hdr *iph, int len, int dir) 271 { 272 union { 273 struct ipv6hdr *iph; 274 struct ipv6_opt_hdr *opth; 275 struct ipv6_rt_hdr *rth; 276 char *raw; 277 } exthdr = { .iph = iph }; 278 char *end = exthdr.raw + len; 279 int nexthdr = iph->nexthdr; 280 int err; 281 282 exthdr.iph++; 283 284 while (exthdr.raw < end) { 285 switch (nexthdr) { 286 case NEXTHDR_DEST: 287 if (dir == XFRM_POLICY_OUT) 288 ipv6_rearrange_destopt(iph, exthdr.opth); 289 fallthrough; 290 case NEXTHDR_HOP: 291 if (!zero_out_mutable_opts(exthdr.opth)) { 292 net_dbg_ratelimited("overrun %sopts\n", 293 nexthdr == NEXTHDR_HOP ? 294 "hop" : "dest"); 295 return -EINVAL; 296 } 297 break; 298 299 case NEXTHDR_ROUTING: 300 err = ipv6_rearrange_rthdr(iph, exthdr.rth); 301 if (err) 302 return err; 303 break; 304 305 default: 306 return 0; 307 } 308 309 nexthdr = exthdr.opth->nexthdr; 310 exthdr.raw += ipv6_optlen(exthdr.opth); 311 } 312 313 return 0; 314 } 315 316 static void ah6_output_done(void *data, int err) 317 { 318 int extlen; 319 u8 *iph_base; 320 u8 *icv; 321 struct sk_buff *skb = data; 322 struct xfrm_state *x = skb_dst(skb)->xfrm; 323 struct ah_data *ahp = x->data; 324 struct ipv6hdr *top_iph = ipv6_hdr(skb); 325 struct ip_auth_hdr *ah = ip_auth_hdr(skb); 326 struct tmp_ext *iph_ext; 327 int seqhi_len = 0; 328 __be32 *seqhi; 329 330 extlen = skb_network_header_len(skb) - sizeof(struct ipv6hdr); 331 if (extlen) 332 extlen += sizeof(*iph_ext); 333 334 if (x->props.flags & XFRM_STATE_ESN) 335 seqhi_len = sizeof(*seqhi); 336 iph_base = AH_SKB_CB(skb)->tmp; 337 iph_ext = ah_tmp_ext(iph_base); 338 seqhi = (__be32 *)((char *)iph_ext + extlen); 339 icv = ah_tmp_icv(seqhi, seqhi_len); 340 341 memcpy(ah->auth_data, icv, ahp->icv_trunc_len); 342 memcpy(top_iph, iph_base, IPV6HDR_BASELEN); 343 344 ah6_restore_hdrs(top_iph, iph_ext, extlen); 345 346 kfree(AH_SKB_CB(skb)->tmp); 347 xfrm_output_resume(skb_to_full_sk(skb), skb, err); 348 } 349 350 static int ah6_output(struct xfrm_state *x, struct sk_buff *skb) 351 { 352 int err; 353 int nfrags; 354 int extlen; 355 u8 *iph_base; 356 u8 *icv; 357 u8 nexthdr; 358 struct sk_buff *trailer; 359 struct crypto_ahash *ahash; 360 struct ahash_request *req; 361 struct scatterlist *sg; 362 struct ipv6hdr *top_iph; 363 struct ip_auth_hdr *ah; 364 struct ah_data *ahp; 365 struct tmp_ext *iph_ext; 366 int seqhi_len = 0; 367 __be32 *seqhi; 368 int sglists = 0; 369 struct scatterlist *seqhisg; 370 371 ahp = x->data; 372 ahash = ahp->ahash; 373 374 err = skb_cow_data(skb, 0, &trailer); 375 if (err < 0) 376 goto out; 377 nfrags = err; 378 379 skb_push(skb, -skb_network_offset(skb)); 380 extlen = skb_network_header_len(skb) - sizeof(struct ipv6hdr); 381 if (extlen) 382 extlen += sizeof(*iph_ext); 383 384 if (x->props.flags & XFRM_STATE_ESN) { 385 sglists = 1; 386 seqhi_len = sizeof(*seqhi); 387 } 388 err = -ENOMEM; 389 iph_base = ah_alloc_tmp(ahash, nfrags + sglists, IPV6HDR_BASELEN + 390 extlen + seqhi_len); 391 if (!iph_base) 392 goto out; 393 394 iph_ext = ah_tmp_ext(iph_base); 395 seqhi = (__be32 *)((char *)iph_ext + extlen); 396 icv = ah_tmp_icv(seqhi, seqhi_len); 397 req = ah_tmp_req(ahash, icv); 398 sg = ah_req_sg(ahash, req); 399 seqhisg = sg + nfrags; 400 401 ah = ip_auth_hdr(skb); 402 memset(ah->auth_data, 0, ahp->icv_trunc_len); 403 404 top_iph = ipv6_hdr(skb); 405 top_iph->payload_len = htons(skb->len - sizeof(*top_iph)); 406 407 nexthdr = *skb_mac_header(skb); 408 *skb_mac_header(skb) = IPPROTO_AH; 409 410 /* When there are no extension headers, we only need to save the first 411 * 8 bytes of the base IP header. 412 */ 413 memcpy(iph_base, top_iph, IPV6HDR_BASELEN); 414 415 ah6_save_hdrs(iph_ext, top_iph, extlen); 416 if (extlen) { 417 err = ipv6_clear_mutable_options(top_iph, 418 extlen - sizeof(*iph_ext) + 419 sizeof(*top_iph), 420 XFRM_POLICY_OUT); 421 if (err) 422 goto out_free; 423 } 424 425 ah->nexthdr = nexthdr; 426 427 top_iph->priority = 0; 428 top_iph->flow_lbl[0] = 0; 429 top_iph->flow_lbl[1] = 0; 430 top_iph->flow_lbl[2] = 0; 431 top_iph->hop_limit = 0; 432 433 ah->hdrlen = (XFRM_ALIGN8(sizeof(*ah) + ahp->icv_trunc_len) >> 2) - 2; 434 435 ah->reserved = 0; 436 ah->spi = x->id.spi; 437 ah->seq_no = htonl(XFRM_SKB_CB(skb)->seq.output.low); 438 439 sg_init_table(sg, nfrags + sglists); 440 err = skb_to_sgvec_nomark(skb, sg, 0, skb->len); 441 if (unlikely(err < 0)) 442 goto out_free; 443 444 if (x->props.flags & XFRM_STATE_ESN) { 445 /* Attach seqhi sg right after packet payload */ 446 *seqhi = htonl(XFRM_SKB_CB(skb)->seq.output.hi); 447 sg_set_buf(seqhisg, seqhi, seqhi_len); 448 } 449 ahash_request_set_crypt(req, sg, icv, skb->len + seqhi_len); 450 ahash_request_set_callback(req, 0, ah6_output_done, skb); 451 452 AH_SKB_CB(skb)->tmp = iph_base; 453 454 err = crypto_ahash_digest(req); 455 if (err) { 456 if (err == -EINPROGRESS) 457 goto out; 458 459 if (err == -ENOSPC) 460 err = NET_XMIT_DROP; 461 goto out_free; 462 } 463 464 memcpy(ah->auth_data, icv, ahp->icv_trunc_len); 465 memcpy(top_iph, iph_base, IPV6HDR_BASELEN); 466 467 ah6_restore_hdrs(top_iph, iph_ext, extlen); 468 469 out_free: 470 kfree(iph_base); 471 out: 472 return err; 473 } 474 475 static void ah6_input_done(void *data, int err) 476 { 477 u8 *auth_data; 478 u8 *icv; 479 u8 *work_iph; 480 struct sk_buff *skb = data; 481 struct xfrm_state *x = xfrm_input_state(skb); 482 struct ah_data *ahp = x->data; 483 struct ip_auth_hdr *ah = ip_auth_hdr(skb); 484 int hdr_len = skb_network_header_len(skb); 485 int ah_hlen = ipv6_authlen(ah); 486 int seqhi_len = 0; 487 __be32 *seqhi; 488 489 if (err) 490 goto out; 491 492 if (x->props.flags & XFRM_STATE_ESN) 493 seqhi_len = sizeof(*seqhi); 494 work_iph = AH_SKB_CB(skb)->tmp; 495 auth_data = ah_tmp_auth(work_iph, hdr_len); 496 seqhi = (__be32 *)(auth_data + ahp->icv_trunc_len); 497 icv = ah_tmp_icv(seqhi, seqhi_len); 498 499 err = crypto_memneq(icv, auth_data, ahp->icv_trunc_len) ? -EBADMSG : 0; 500 if (err) 501 goto out; 502 503 err = ah->nexthdr; 504 505 skb->network_header += ah_hlen; 506 memcpy(skb_network_header(skb), work_iph, hdr_len); 507 __skb_pull(skb, ah_hlen + hdr_len); 508 if (x->props.mode == XFRM_MODE_TUNNEL) 509 skb_reset_transport_header(skb); 510 else 511 skb_set_transport_header(skb, -hdr_len); 512 out: 513 kfree(AH_SKB_CB(skb)->tmp); 514 xfrm_input_resume(skb, err); 515 } 516 517 518 519 static int ah6_input(struct xfrm_state *x, struct sk_buff *skb) 520 { 521 /* 522 * Before process AH 523 * [IPv6][Ext1][Ext2][AH][Dest][Payload] 524 * |<-------------->| hdr_len 525 * 526 * To erase AH: 527 * Keeping copy of cleared headers. After AH processing, 528 * Moving the pointer of skb->network_header by using skb_pull as long 529 * as AH header length. Then copy back the copy as long as hdr_len 530 * If destination header following AH exists, copy it into after [Ext2]. 531 * 532 * |<>|[IPv6][Ext1][Ext2][Dest][Payload] 533 * There is offset of AH before IPv6 header after the process. 534 */ 535 536 u8 *auth_data; 537 u8 *icv; 538 u8 *work_iph; 539 struct sk_buff *trailer; 540 struct crypto_ahash *ahash; 541 struct ahash_request *req; 542 struct scatterlist *sg; 543 struct ip_auth_hdr *ah; 544 struct ipv6hdr *ip6h; 545 struct ah_data *ahp; 546 u16 hdr_len; 547 u16 ah_hlen; 548 int nexthdr; 549 int nfrags; 550 int err = -ENOMEM; 551 int seqhi_len = 0; 552 __be32 *seqhi; 553 int sglists = 0; 554 struct scatterlist *seqhisg; 555 556 if (!pskb_may_pull(skb, sizeof(struct ip_auth_hdr))) 557 goto out; 558 559 /* We are going to _remove_ AH header to keep sockets happy, 560 * so... Later this can change. */ 561 if (skb_unclone(skb, GFP_ATOMIC)) 562 goto out; 563 564 skb->ip_summed = CHECKSUM_NONE; 565 566 hdr_len = skb_network_header_len(skb); 567 ah = (struct ip_auth_hdr *)skb->data; 568 ahp = x->data; 569 ahash = ahp->ahash; 570 571 nexthdr = ah->nexthdr; 572 ah_hlen = ipv6_authlen(ah); 573 574 if (ah_hlen != XFRM_ALIGN8(sizeof(*ah) + ahp->icv_full_len) && 575 ah_hlen != XFRM_ALIGN8(sizeof(*ah) + ahp->icv_trunc_len)) 576 goto out; 577 578 if (!pskb_may_pull(skb, ah_hlen)) 579 goto out; 580 581 err = skb_cow_data(skb, 0, &trailer); 582 if (err < 0) 583 goto out; 584 nfrags = err; 585 586 ah = (struct ip_auth_hdr *)skb->data; 587 ip6h = ipv6_hdr(skb); 588 589 skb_push(skb, hdr_len); 590 591 if (x->props.flags & XFRM_STATE_ESN) { 592 sglists = 1; 593 seqhi_len = sizeof(*seqhi); 594 } 595 596 work_iph = ah_alloc_tmp(ahash, nfrags + sglists, hdr_len + 597 ahp->icv_trunc_len + seqhi_len); 598 if (!work_iph) { 599 err = -ENOMEM; 600 goto out; 601 } 602 603 auth_data = ah_tmp_auth((u8 *)work_iph, hdr_len); 604 seqhi = (__be32 *)(auth_data + ahp->icv_trunc_len); 605 icv = ah_tmp_icv(seqhi, seqhi_len); 606 req = ah_tmp_req(ahash, icv); 607 sg = ah_req_sg(ahash, req); 608 seqhisg = sg + nfrags; 609 610 memcpy(work_iph, ip6h, hdr_len); 611 memcpy(auth_data, ah->auth_data, ahp->icv_trunc_len); 612 memset(ah->auth_data, 0, ahp->icv_trunc_len); 613 614 err = ipv6_clear_mutable_options(ip6h, hdr_len, XFRM_POLICY_IN); 615 if (err) 616 goto out_free; 617 618 ip6h->priority = 0; 619 ip6h->flow_lbl[0] = 0; 620 ip6h->flow_lbl[1] = 0; 621 ip6h->flow_lbl[2] = 0; 622 ip6h->hop_limit = 0; 623 624 sg_init_table(sg, nfrags + sglists); 625 err = skb_to_sgvec_nomark(skb, sg, 0, skb->len); 626 if (unlikely(err < 0)) 627 goto out_free; 628 629 if (x->props.flags & XFRM_STATE_ESN) { 630 /* Attach seqhi sg right after packet payload */ 631 *seqhi = XFRM_SKB_CB(skb)->seq.input.hi; 632 sg_set_buf(seqhisg, seqhi, seqhi_len); 633 } 634 635 ahash_request_set_crypt(req, sg, icv, skb->len + seqhi_len); 636 ahash_request_set_callback(req, 0, ah6_input_done, skb); 637 638 AH_SKB_CB(skb)->tmp = work_iph; 639 640 err = crypto_ahash_digest(req); 641 if (err) { 642 if (err == -EINPROGRESS) 643 goto out; 644 645 goto out_free; 646 } 647 648 err = crypto_memneq(icv, auth_data, ahp->icv_trunc_len) ? -EBADMSG : 0; 649 if (err) 650 goto out_free; 651 652 skb->network_header += ah_hlen; 653 memcpy(skb_network_header(skb), work_iph, hdr_len); 654 __skb_pull(skb, ah_hlen + hdr_len); 655 656 if (x->props.mode == XFRM_MODE_TUNNEL) 657 skb_reset_transport_header(skb); 658 else 659 skb_set_transport_header(skb, -hdr_len); 660 661 err = nexthdr; 662 663 out_free: 664 kfree(work_iph); 665 out: 666 return err; 667 } 668 669 static int ah6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, 670 u8 type, u8 code, int offset, __be32 info) 671 { 672 struct net *net = dev_net(skb->dev); 673 struct ipv6hdr *iph = (struct ipv6hdr *)skb->data; 674 struct ip_auth_hdr *ah = (struct ip_auth_hdr *)(skb->data+offset); 675 struct xfrm_state *x; 676 677 if (type != ICMPV6_PKT_TOOBIG && 678 type != NDISC_REDIRECT) 679 return 0; 680 681 x = xfrm_state_lookup(net, skb->mark, (xfrm_address_t *)&iph->daddr, ah->spi, IPPROTO_AH, AF_INET6); 682 if (!x) 683 return 0; 684 685 if (type == NDISC_REDIRECT) 686 ip6_redirect(skb, net, skb->dev->ifindex, 0, 687 sock_net_uid(net, NULL)); 688 else 689 ip6_update_pmtu(skb, net, info, 0, 0, sock_net_uid(net, NULL)); 690 xfrm_state_put(x); 691 692 return 0; 693 } 694 695 static int ah6_init_state(struct xfrm_state *x, struct netlink_ext_ack *extack) 696 { 697 struct ah_data *ahp = NULL; 698 struct xfrm_algo_desc *aalg_desc; 699 struct crypto_ahash *ahash; 700 701 if (!x->aalg) { 702 NL_SET_ERR_MSG(extack, "AH requires a state with an AUTH algorithm"); 703 goto error; 704 } 705 706 if (x->encap) { 707 NL_SET_ERR_MSG(extack, "AH is not compatible with encapsulation"); 708 goto error; 709 } 710 711 ahp = kzalloc_obj(*ahp); 712 if (!ahp) 713 return -ENOMEM; 714 715 ahash = crypto_alloc_ahash(x->aalg->alg_name, 0, 0); 716 if (IS_ERR(ahash)) { 717 NL_SET_ERR_MSG(extack, "Kernel was unable to initialize cryptographic operations"); 718 goto error; 719 } 720 721 ahp->ahash = ahash; 722 if (crypto_ahash_setkey(ahash, x->aalg->alg_key, 723 (x->aalg->alg_key_len + 7) / 8)) { 724 NL_SET_ERR_MSG(extack, "Kernel was unable to initialize cryptographic operations"); 725 goto error; 726 } 727 728 /* 729 * Lookup the algorithm description maintained by xfrm_algo, 730 * verify crypto transform properties, and store information 731 * we need for AH processing. This lookup cannot fail here 732 * after a successful crypto_alloc_hash(). 733 */ 734 aalg_desc = xfrm_aalg_get_byname(x->aalg->alg_name, 0); 735 BUG_ON(!aalg_desc); 736 737 if (aalg_desc->uinfo.auth.icv_fullbits/8 != 738 crypto_ahash_digestsize(ahash)) { 739 NL_SET_ERR_MSG(extack, "Kernel was unable to initialize cryptographic operations"); 740 goto error; 741 } 742 743 ahp->icv_full_len = aalg_desc->uinfo.auth.icv_fullbits/8; 744 ahp->icv_trunc_len = x->aalg->alg_trunc_len/8; 745 746 x->props.header_len = XFRM_ALIGN8(sizeof(struct ip_auth_hdr) + 747 ahp->icv_trunc_len); 748 switch (x->props.mode) { 749 case XFRM_MODE_BEET: 750 case XFRM_MODE_TRANSPORT: 751 break; 752 case XFRM_MODE_TUNNEL: 753 x->props.header_len += sizeof(struct ipv6hdr); 754 break; 755 default: 756 NL_SET_ERR_MSG(extack, "Invalid mode requested for AH, must be one of TRANSPORT, TUNNEL, BEET"); 757 goto error; 758 } 759 x->data = ahp; 760 761 return 0; 762 763 error: 764 if (ahp) { 765 crypto_free_ahash(ahp->ahash); 766 kfree(ahp); 767 } 768 return -EINVAL; 769 } 770 771 static void ah6_destroy(struct xfrm_state *x) 772 { 773 struct ah_data *ahp = x->data; 774 775 if (!ahp) 776 return; 777 778 crypto_free_ahash(ahp->ahash); 779 kfree(ahp); 780 } 781 782 static int ah6_rcv_cb(struct sk_buff *skb, int err) 783 { 784 return 0; 785 } 786 787 static const struct xfrm_type ah6_type = { 788 .owner = THIS_MODULE, 789 .proto = IPPROTO_AH, 790 .flags = XFRM_TYPE_REPLAY_PROT, 791 .init_state = ah6_init_state, 792 .destructor = ah6_destroy, 793 .input = ah6_input, 794 .output = ah6_output, 795 }; 796 797 static struct xfrm6_protocol ah6_protocol = { 798 .handler = xfrm6_rcv, 799 .input_handler = xfrm_input, 800 .cb_handler = ah6_rcv_cb, 801 .err_handler = ah6_err, 802 .priority = 0, 803 }; 804 805 static int __init ah6_init(void) 806 { 807 if (xfrm_register_type(&ah6_type, AF_INET6) < 0) { 808 pr_info("%s: can't add xfrm type\n", __func__); 809 return -EAGAIN; 810 } 811 812 if (xfrm6_protocol_register(&ah6_protocol, IPPROTO_AH) < 0) { 813 pr_info("%s: can't add protocol\n", __func__); 814 xfrm_unregister_type(&ah6_type, AF_INET6); 815 return -EAGAIN; 816 } 817 818 return 0; 819 } 820 821 static void __exit ah6_fini(void) 822 { 823 if (xfrm6_protocol_deregister(&ah6_protocol, IPPROTO_AH) < 0) 824 pr_info("%s: can't remove protocol\n", __func__); 825 826 xfrm_unregister_type(&ah6_type, AF_INET6); 827 } 828 829 module_init(ah6_init); 830 module_exit(ah6_fini); 831 832 MODULE_DESCRIPTION("IPv6 AH transformation helpers"); 833 MODULE_LICENSE("GPL"); 834 MODULE_ALIAS_XFRM_TYPE(AF_INET6, XFRM_PROTO_AH); 835