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