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