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 static void ipv6_rearrange_rthdr(struct ipv6hdr *iph, struct ipv6_rt_hdr *rthdr) 237 { 238 int segments, segments_left; 239 struct in6_addr *addrs; 240 struct in6_addr final_addr; 241 242 segments_left = rthdr->segments_left; 243 if (segments_left == 0) 244 return; 245 rthdr->segments_left = 0; 246 247 /* The value of rthdr->hdrlen has been verified either by the system 248 * call if it is locally generated, or by ipv6_rthdr_rcv() for incoming 249 * packets. So we can assume that it is even and that segments is 250 * greater than or equal to segments_left. 251 * 252 * For the same reason we can assume that this option is of type 0. 253 */ 254 segments = rthdr->hdrlen >> 1; 255 256 addrs = ((struct rt0_hdr *)rthdr)->addr; 257 final_addr = addrs[segments - 1]; 258 259 addrs += segments - segments_left; 260 memmove(addrs + 1, addrs, (segments_left - 1) * sizeof(*addrs)); 261 262 addrs[0] = iph->daddr; 263 iph->daddr = final_addr; 264 } 265 266 static int ipv6_clear_mutable_options(struct ipv6hdr *iph, int len, int dir) 267 { 268 union { 269 struct ipv6hdr *iph; 270 struct ipv6_opt_hdr *opth; 271 struct ipv6_rt_hdr *rth; 272 char *raw; 273 } exthdr = { .iph = iph }; 274 char *end = exthdr.raw + len; 275 int nexthdr = iph->nexthdr; 276 277 exthdr.iph++; 278 279 while (exthdr.raw < end) { 280 switch (nexthdr) { 281 case NEXTHDR_DEST: 282 if (dir == XFRM_POLICY_OUT) 283 ipv6_rearrange_destopt(iph, exthdr.opth); 284 fallthrough; 285 case NEXTHDR_HOP: 286 if (!zero_out_mutable_opts(exthdr.opth)) { 287 net_dbg_ratelimited("overrun %sopts\n", 288 nexthdr == NEXTHDR_HOP ? 289 "hop" : "dest"); 290 return -EINVAL; 291 } 292 break; 293 294 case NEXTHDR_ROUTING: 295 ipv6_rearrange_rthdr(iph, exthdr.rth); 296 break; 297 298 default: 299 return 0; 300 } 301 302 nexthdr = exthdr.opth->nexthdr; 303 exthdr.raw += ipv6_optlen(exthdr.opth); 304 } 305 306 return 0; 307 } 308 309 static void ah6_output_done(void *data, int err) 310 { 311 int extlen; 312 u8 *iph_base; 313 u8 *icv; 314 struct sk_buff *skb = data; 315 struct xfrm_state *x = skb_dst(skb)->xfrm; 316 struct ah_data *ahp = x->data; 317 struct ipv6hdr *top_iph = ipv6_hdr(skb); 318 struct ip_auth_hdr *ah = ip_auth_hdr(skb); 319 struct tmp_ext *iph_ext; 320 321 extlen = skb_network_header_len(skb) - sizeof(struct ipv6hdr); 322 if (extlen) 323 extlen += sizeof(*iph_ext); 324 325 iph_base = AH_SKB_CB(skb)->tmp; 326 iph_ext = ah_tmp_ext(iph_base); 327 icv = ah_tmp_icv(iph_ext, extlen); 328 329 memcpy(ah->auth_data, icv, ahp->icv_trunc_len); 330 memcpy(top_iph, iph_base, IPV6HDR_BASELEN); 331 332 ah6_restore_hdrs(top_iph, iph_ext, extlen); 333 334 kfree(AH_SKB_CB(skb)->tmp); 335 xfrm_output_resume(skb->sk, skb, err); 336 } 337 338 static int ah6_output(struct xfrm_state *x, struct sk_buff *skb) 339 { 340 int err; 341 int nfrags; 342 int extlen; 343 u8 *iph_base; 344 u8 *icv; 345 u8 nexthdr; 346 struct sk_buff *trailer; 347 struct crypto_ahash *ahash; 348 struct ahash_request *req; 349 struct scatterlist *sg; 350 struct ipv6hdr *top_iph; 351 struct ip_auth_hdr *ah; 352 struct ah_data *ahp; 353 struct tmp_ext *iph_ext; 354 int seqhi_len = 0; 355 __be32 *seqhi; 356 int sglists = 0; 357 struct scatterlist *seqhisg; 358 359 ahp = x->data; 360 ahash = ahp->ahash; 361 362 err = skb_cow_data(skb, 0, &trailer); 363 if (err < 0) 364 goto out; 365 nfrags = err; 366 367 skb_push(skb, -skb_network_offset(skb)); 368 extlen = skb_network_header_len(skb) - sizeof(struct ipv6hdr); 369 if (extlen) 370 extlen += sizeof(*iph_ext); 371 372 if (x->props.flags & XFRM_STATE_ESN) { 373 sglists = 1; 374 seqhi_len = sizeof(*seqhi); 375 } 376 err = -ENOMEM; 377 iph_base = ah_alloc_tmp(ahash, nfrags + sglists, IPV6HDR_BASELEN + 378 extlen + seqhi_len); 379 if (!iph_base) 380 goto out; 381 382 iph_ext = ah_tmp_ext(iph_base); 383 seqhi = (__be32 *)((char *)iph_ext + extlen); 384 icv = ah_tmp_icv(seqhi, seqhi_len); 385 req = ah_tmp_req(ahash, icv); 386 sg = ah_req_sg(ahash, req); 387 seqhisg = sg + nfrags; 388 389 ah = ip_auth_hdr(skb); 390 memset(ah->auth_data, 0, ahp->icv_trunc_len); 391 392 top_iph = ipv6_hdr(skb); 393 top_iph->payload_len = htons(skb->len - sizeof(*top_iph)); 394 395 nexthdr = *skb_mac_header(skb); 396 *skb_mac_header(skb) = IPPROTO_AH; 397 398 /* When there are no extension headers, we only need to save the first 399 * 8 bytes of the base IP header. 400 */ 401 memcpy(iph_base, top_iph, IPV6HDR_BASELEN); 402 403 ah6_save_hdrs(iph_ext, top_iph, extlen); 404 if (extlen) { 405 err = ipv6_clear_mutable_options(top_iph, 406 extlen - sizeof(*iph_ext) + 407 sizeof(*top_iph), 408 XFRM_POLICY_OUT); 409 if (err) 410 goto out_free; 411 } 412 413 ah->nexthdr = nexthdr; 414 415 top_iph->priority = 0; 416 top_iph->flow_lbl[0] = 0; 417 top_iph->flow_lbl[1] = 0; 418 top_iph->flow_lbl[2] = 0; 419 top_iph->hop_limit = 0; 420 421 ah->hdrlen = (XFRM_ALIGN8(sizeof(*ah) + ahp->icv_trunc_len) >> 2) - 2; 422 423 ah->reserved = 0; 424 ah->spi = x->id.spi; 425 ah->seq_no = htonl(XFRM_SKB_CB(skb)->seq.output.low); 426 427 sg_init_table(sg, nfrags + sglists); 428 err = skb_to_sgvec_nomark(skb, sg, 0, skb->len); 429 if (unlikely(err < 0)) 430 goto out_free; 431 432 if (x->props.flags & XFRM_STATE_ESN) { 433 /* Attach seqhi sg right after packet payload */ 434 *seqhi = htonl(XFRM_SKB_CB(skb)->seq.output.hi); 435 sg_set_buf(seqhisg, seqhi, seqhi_len); 436 } 437 ahash_request_set_crypt(req, sg, icv, skb->len + seqhi_len); 438 ahash_request_set_callback(req, 0, ah6_output_done, skb); 439 440 AH_SKB_CB(skb)->tmp = iph_base; 441 442 err = crypto_ahash_digest(req); 443 if (err) { 444 if (err == -EINPROGRESS) 445 goto out; 446 447 if (err == -ENOSPC) 448 err = NET_XMIT_DROP; 449 goto out_free; 450 } 451 452 memcpy(ah->auth_data, icv, ahp->icv_trunc_len); 453 memcpy(top_iph, iph_base, IPV6HDR_BASELEN); 454 455 ah6_restore_hdrs(top_iph, iph_ext, extlen); 456 457 out_free: 458 kfree(iph_base); 459 out: 460 return err; 461 } 462 463 static void ah6_input_done(void *data, int err) 464 { 465 u8 *auth_data; 466 u8 *icv; 467 u8 *work_iph; 468 struct sk_buff *skb = data; 469 struct xfrm_state *x = xfrm_input_state(skb); 470 struct ah_data *ahp = x->data; 471 struct ip_auth_hdr *ah = ip_auth_hdr(skb); 472 int hdr_len = skb_network_header_len(skb); 473 int ah_hlen = ipv6_authlen(ah); 474 475 if (err) 476 goto out; 477 478 work_iph = AH_SKB_CB(skb)->tmp; 479 auth_data = ah_tmp_auth(work_iph, hdr_len); 480 icv = ah_tmp_icv(auth_data, ahp->icv_trunc_len); 481 482 err = crypto_memneq(icv, auth_data, ahp->icv_trunc_len) ? -EBADMSG : 0; 483 if (err) 484 goto out; 485 486 err = ah->nexthdr; 487 488 skb->network_header += ah_hlen; 489 memcpy(skb_network_header(skb), work_iph, hdr_len); 490 __skb_pull(skb, ah_hlen + hdr_len); 491 if (x->props.mode == XFRM_MODE_TUNNEL) 492 skb_reset_transport_header(skb); 493 else 494 skb_set_transport_header(skb, -hdr_len); 495 out: 496 kfree(AH_SKB_CB(skb)->tmp); 497 xfrm_input_resume(skb, err); 498 } 499 500 501 502 static int ah6_input(struct xfrm_state *x, struct sk_buff *skb) 503 { 504 /* 505 * Before process AH 506 * [IPv6][Ext1][Ext2][AH][Dest][Payload] 507 * |<-------------->| hdr_len 508 * 509 * To erase AH: 510 * Keeping copy of cleared headers. After AH processing, 511 * Moving the pointer of skb->network_header by using skb_pull as long 512 * as AH header length. Then copy back the copy as long as hdr_len 513 * If destination header following AH exists, copy it into after [Ext2]. 514 * 515 * |<>|[IPv6][Ext1][Ext2][Dest][Payload] 516 * There is offset of AH before IPv6 header after the process. 517 */ 518 519 u8 *auth_data; 520 u8 *icv; 521 u8 *work_iph; 522 struct sk_buff *trailer; 523 struct crypto_ahash *ahash; 524 struct ahash_request *req; 525 struct scatterlist *sg; 526 struct ip_auth_hdr *ah; 527 struct ipv6hdr *ip6h; 528 struct ah_data *ahp; 529 u16 hdr_len; 530 u16 ah_hlen; 531 int nexthdr; 532 int nfrags; 533 int err = -ENOMEM; 534 int seqhi_len = 0; 535 __be32 *seqhi; 536 int sglists = 0; 537 struct scatterlist *seqhisg; 538 539 if (!pskb_may_pull(skb, sizeof(struct ip_auth_hdr))) 540 goto out; 541 542 /* We are going to _remove_ AH header to keep sockets happy, 543 * so... Later this can change. */ 544 if (skb_unclone(skb, GFP_ATOMIC)) 545 goto out; 546 547 skb->ip_summed = CHECKSUM_NONE; 548 549 hdr_len = skb_network_header_len(skb); 550 ah = (struct ip_auth_hdr *)skb->data; 551 ahp = x->data; 552 ahash = ahp->ahash; 553 554 nexthdr = ah->nexthdr; 555 ah_hlen = ipv6_authlen(ah); 556 557 if (ah_hlen != XFRM_ALIGN8(sizeof(*ah) + ahp->icv_full_len) && 558 ah_hlen != XFRM_ALIGN8(sizeof(*ah) + ahp->icv_trunc_len)) 559 goto out; 560 561 if (!pskb_may_pull(skb, ah_hlen)) 562 goto out; 563 564 err = skb_cow_data(skb, 0, &trailer); 565 if (err < 0) 566 goto out; 567 nfrags = err; 568 569 ah = (struct ip_auth_hdr *)skb->data; 570 ip6h = ipv6_hdr(skb); 571 572 skb_push(skb, hdr_len); 573 574 if (x->props.flags & XFRM_STATE_ESN) { 575 sglists = 1; 576 seqhi_len = sizeof(*seqhi); 577 } 578 579 work_iph = ah_alloc_tmp(ahash, nfrags + sglists, hdr_len + 580 ahp->icv_trunc_len + seqhi_len); 581 if (!work_iph) { 582 err = -ENOMEM; 583 goto out; 584 } 585 586 auth_data = ah_tmp_auth((u8 *)work_iph, hdr_len); 587 seqhi = (__be32 *)(auth_data + ahp->icv_trunc_len); 588 icv = ah_tmp_icv(seqhi, seqhi_len); 589 req = ah_tmp_req(ahash, icv); 590 sg = ah_req_sg(ahash, req); 591 seqhisg = sg + nfrags; 592 593 memcpy(work_iph, ip6h, hdr_len); 594 memcpy(auth_data, ah->auth_data, ahp->icv_trunc_len); 595 memset(ah->auth_data, 0, ahp->icv_trunc_len); 596 597 err = ipv6_clear_mutable_options(ip6h, hdr_len, XFRM_POLICY_IN); 598 if (err) 599 goto out_free; 600 601 ip6h->priority = 0; 602 ip6h->flow_lbl[0] = 0; 603 ip6h->flow_lbl[1] = 0; 604 ip6h->flow_lbl[2] = 0; 605 ip6h->hop_limit = 0; 606 607 sg_init_table(sg, nfrags + sglists); 608 err = skb_to_sgvec_nomark(skb, sg, 0, skb->len); 609 if (unlikely(err < 0)) 610 goto out_free; 611 612 if (x->props.flags & XFRM_STATE_ESN) { 613 /* Attach seqhi sg right after packet payload */ 614 *seqhi = XFRM_SKB_CB(skb)->seq.input.hi; 615 sg_set_buf(seqhisg, seqhi, seqhi_len); 616 } 617 618 ahash_request_set_crypt(req, sg, icv, skb->len + seqhi_len); 619 ahash_request_set_callback(req, 0, ah6_input_done, skb); 620 621 AH_SKB_CB(skb)->tmp = work_iph; 622 623 err = crypto_ahash_digest(req); 624 if (err) { 625 if (err == -EINPROGRESS) 626 goto out; 627 628 goto out_free; 629 } 630 631 err = crypto_memneq(icv, auth_data, ahp->icv_trunc_len) ? -EBADMSG : 0; 632 if (err) 633 goto out_free; 634 635 skb->network_header += ah_hlen; 636 memcpy(skb_network_header(skb), work_iph, hdr_len); 637 __skb_pull(skb, ah_hlen + hdr_len); 638 639 if (x->props.mode == XFRM_MODE_TUNNEL) 640 skb_reset_transport_header(skb); 641 else 642 skb_set_transport_header(skb, -hdr_len); 643 644 err = nexthdr; 645 646 out_free: 647 kfree(work_iph); 648 out: 649 return err; 650 } 651 652 static int ah6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, 653 u8 type, u8 code, int offset, __be32 info) 654 { 655 struct net *net = dev_net(skb->dev); 656 struct ipv6hdr *iph = (struct ipv6hdr *)skb->data; 657 struct ip_auth_hdr *ah = (struct ip_auth_hdr *)(skb->data+offset); 658 struct xfrm_state *x; 659 660 if (type != ICMPV6_PKT_TOOBIG && 661 type != NDISC_REDIRECT) 662 return 0; 663 664 x = xfrm_state_lookup(net, skb->mark, (xfrm_address_t *)&iph->daddr, ah->spi, IPPROTO_AH, AF_INET6); 665 if (!x) 666 return 0; 667 668 if (type == NDISC_REDIRECT) 669 ip6_redirect(skb, net, skb->dev->ifindex, 0, 670 sock_net_uid(net, NULL)); 671 else 672 ip6_update_pmtu(skb, net, info, 0, 0, sock_net_uid(net, NULL)); 673 xfrm_state_put(x); 674 675 return 0; 676 } 677 678 static int ah6_init_state(struct xfrm_state *x, struct netlink_ext_ack *extack) 679 { 680 struct ah_data *ahp = NULL; 681 struct xfrm_algo_desc *aalg_desc; 682 struct crypto_ahash *ahash; 683 684 if (!x->aalg) { 685 NL_SET_ERR_MSG(extack, "AH requires a state with an AUTH algorithm"); 686 goto error; 687 } 688 689 if (x->encap) { 690 NL_SET_ERR_MSG(extack, "AH is not compatible with encapsulation"); 691 goto error; 692 } 693 694 ahp = kzalloc(sizeof(*ahp), GFP_KERNEL); 695 if (!ahp) 696 return -ENOMEM; 697 698 ahash = crypto_alloc_ahash(x->aalg->alg_name, 0, 0); 699 if (IS_ERR(ahash)) { 700 NL_SET_ERR_MSG(extack, "Kernel was unable to initialize cryptographic operations"); 701 goto error; 702 } 703 704 ahp->ahash = ahash; 705 if (crypto_ahash_setkey(ahash, x->aalg->alg_key, 706 (x->aalg->alg_key_len + 7) / 8)) { 707 NL_SET_ERR_MSG(extack, "Kernel was unable to initialize cryptographic operations"); 708 goto error; 709 } 710 711 /* 712 * Lookup the algorithm description maintained by xfrm_algo, 713 * verify crypto transform properties, and store information 714 * we need for AH processing. This lookup cannot fail here 715 * after a successful crypto_alloc_hash(). 716 */ 717 aalg_desc = xfrm_aalg_get_byname(x->aalg->alg_name, 0); 718 BUG_ON(!aalg_desc); 719 720 if (aalg_desc->uinfo.auth.icv_fullbits/8 != 721 crypto_ahash_digestsize(ahash)) { 722 NL_SET_ERR_MSG(extack, "Kernel was unable to initialize cryptographic operations"); 723 goto error; 724 } 725 726 ahp->icv_full_len = aalg_desc->uinfo.auth.icv_fullbits/8; 727 ahp->icv_trunc_len = x->aalg->alg_trunc_len/8; 728 729 x->props.header_len = XFRM_ALIGN8(sizeof(struct ip_auth_hdr) + 730 ahp->icv_trunc_len); 731 switch (x->props.mode) { 732 case XFRM_MODE_BEET: 733 case XFRM_MODE_TRANSPORT: 734 break; 735 case XFRM_MODE_TUNNEL: 736 x->props.header_len += sizeof(struct ipv6hdr); 737 break; 738 default: 739 NL_SET_ERR_MSG(extack, "Invalid mode requested for AH, must be one of TRANSPORT, TUNNEL, BEET"); 740 goto error; 741 } 742 x->data = ahp; 743 744 return 0; 745 746 error: 747 if (ahp) { 748 crypto_free_ahash(ahp->ahash); 749 kfree(ahp); 750 } 751 return -EINVAL; 752 } 753 754 static void ah6_destroy(struct xfrm_state *x) 755 { 756 struct ah_data *ahp = x->data; 757 758 if (!ahp) 759 return; 760 761 crypto_free_ahash(ahp->ahash); 762 kfree(ahp); 763 } 764 765 static int ah6_rcv_cb(struct sk_buff *skb, int err) 766 { 767 return 0; 768 } 769 770 static const struct xfrm_type ah6_type = { 771 .owner = THIS_MODULE, 772 .proto = IPPROTO_AH, 773 .flags = XFRM_TYPE_REPLAY_PROT, 774 .init_state = ah6_init_state, 775 .destructor = ah6_destroy, 776 .input = ah6_input, 777 .output = ah6_output, 778 }; 779 780 static struct xfrm6_protocol ah6_protocol = { 781 .handler = xfrm6_rcv, 782 .input_handler = xfrm_input, 783 .cb_handler = ah6_rcv_cb, 784 .err_handler = ah6_err, 785 .priority = 0, 786 }; 787 788 static int __init ah6_init(void) 789 { 790 if (xfrm_register_type(&ah6_type, AF_INET6) < 0) { 791 pr_info("%s: can't add xfrm type\n", __func__); 792 return -EAGAIN; 793 } 794 795 if (xfrm6_protocol_register(&ah6_protocol, IPPROTO_AH) < 0) { 796 pr_info("%s: can't add protocol\n", __func__); 797 xfrm_unregister_type(&ah6_type, AF_INET6); 798 return -EAGAIN; 799 } 800 801 return 0; 802 } 803 804 static void __exit ah6_fini(void) 805 { 806 if (xfrm6_protocol_deregister(&ah6_protocol, IPPROTO_AH) < 0) 807 pr_info("%s: can't remove protocol\n", __func__); 808 809 xfrm_unregister_type(&ah6_type, AF_INET6); 810 } 811 812 module_init(ah6_init); 813 module_exit(ah6_fini); 814 815 MODULE_DESCRIPTION("IPv6 AH transformation helpers"); 816 MODULE_LICENSE("GPL"); 817 MODULE_ALIAS_XFRM_TYPE(AF_INET6, XFRM_PROTO_AH); 818