1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * SR-IPv6 implementation -- HMAC functions
6 * David Lebrun <david.lebrun@uclouvain.be>
9 #include <linux/errno.h>
10 #include <linux/kernel.h>
11 #include <linux/types.h>
12 #include <linux/socket.h>
13 #include <linux/sockios.h>
14 #include <linux/net.h>
15 #include <linux/netdevice.h>
16 #include <linux/in6.h>
17 #include <linux/icmpv6.h>
18 #include <linux/mroute6.h>
19 #include <linux/slab.h>
20 #include <linux/rhashtable.h>
22 #include <linux/netfilter.h>
23 #include <linux/netfilter_ipv6.h>
29 #include <net/protocol.h>
30 #include <net/transp_v6.h>
31 #include <net/rawv6.h>
32 #include <net/ndisc.h>
33 #include <net/ip6_route.h>
34 #include <net/addrconf.h>
37 #include <crypto/hash.h>
38 #include <crypto/sha.h>
40 #include <net/genetlink.h>
41 #include <net/seg6_hmac.h>
42 #include <linux/random.h>
44 static DEFINE_PER_CPU(char [SEG6_HMAC_RING_SIZE
], hmac_ring
);
46 static int seg6_hmac_cmpfn(struct rhashtable_compare_arg
*arg
, const void *obj
)
48 const struct seg6_hmac_info
*hinfo
= obj
;
50 return (hinfo
->hmackeyid
!= *(__u32
*)arg
->key
);
53 static inline void seg6_hinfo_release(struct seg6_hmac_info
*hinfo
)
55 kfree_rcu(hinfo
, rcu
);
58 static void seg6_free_hi(void *ptr
, void *arg
)
60 struct seg6_hmac_info
*hinfo
= (struct seg6_hmac_info
*)ptr
;
63 seg6_hinfo_release(hinfo
);
66 static const struct rhashtable_params rht_params
= {
67 .head_offset
= offsetof(struct seg6_hmac_info
, node
),
68 .key_offset
= offsetof(struct seg6_hmac_info
, hmackeyid
),
69 .key_len
= sizeof(u32
),
70 .automatic_shrinking
= true,
71 .obj_cmpfn
= seg6_hmac_cmpfn
,
74 static struct seg6_hmac_algo hmac_algos
[] = {
76 .alg_id
= SEG6_HMAC_ALGO_SHA1
,
80 .alg_id
= SEG6_HMAC_ALGO_SHA256
,
81 .name
= "hmac(sha256)",
85 static struct sr6_tlv_hmac
*seg6_get_tlv_hmac(struct ipv6_sr_hdr
*srh
)
87 struct sr6_tlv_hmac
*tlv
;
89 if (srh
->hdrlen
< (srh
->first_segment
+ 1) * 2 + 5)
92 if (!sr_has_hmac(srh
))
95 tlv
= (struct sr6_tlv_hmac
*)
96 ((char *)srh
+ ((srh
->hdrlen
+ 1) << 3) - 40);
98 if (tlv
->tlvhdr
.type
!= SR6_TLV_HMAC
|| tlv
->tlvhdr
.len
!= 38)
104 static struct seg6_hmac_algo
*__hmac_get_algo(u8 alg_id
)
106 struct seg6_hmac_algo
*algo
;
109 alg_count
= ARRAY_SIZE(hmac_algos
);
110 for (i
= 0; i
< alg_count
; i
++) {
111 algo
= &hmac_algos
[i
];
112 if (algo
->alg_id
== alg_id
)
119 static int __do_hmac(struct seg6_hmac_info
*hinfo
, const char *text
, u8 psize
,
120 u8
*output
, int outlen
)
122 struct seg6_hmac_algo
*algo
;
123 struct crypto_shash
*tfm
;
124 struct shash_desc
*shash
;
127 algo
= __hmac_get_algo(hinfo
->alg_id
);
131 tfm
= *this_cpu_ptr(algo
->tfms
);
133 dgsize
= crypto_shash_digestsize(tfm
);
134 if (dgsize
> outlen
) {
135 pr_debug("sr-ipv6: __do_hmac: digest size too big (%d / %d)\n",
140 ret
= crypto_shash_setkey(tfm
, hinfo
->secret
, hinfo
->slen
);
142 pr_debug("sr-ipv6: crypto_shash_setkey failed: err %d\n", ret
);
146 shash
= *this_cpu_ptr(algo
->shashs
);
149 ret
= crypto_shash_digest(shash
, text
, psize
, output
);
151 pr_debug("sr-ipv6: crypto_shash_digest failed: err %d\n", ret
);
161 int seg6_hmac_compute(struct seg6_hmac_info
*hinfo
, struct ipv6_sr_hdr
*hdr
,
162 struct in6_addr
*saddr
, u8
*output
)
164 __be32 hmackeyid
= cpu_to_be32(hinfo
->hmackeyid
);
165 u8 tmp_out
[SEG6_HMAC_MAX_DIGESTSIZE
];
166 int plen
, i
, dgsize
, wrsize
;
169 /* a 160-byte buffer for digest output allows to store highest known
170 * hash function (RadioGatun) with up to 1216 bits
173 /* saddr(16) + first_seg(1) + flags(1) + keyid(4) + seglist(16n) */
174 plen
= 16 + 1 + 1 + 4 + (hdr
->first_segment
+ 1) * 16;
176 /* this limit allows for 14 segments */
177 if (plen
>= SEG6_HMAC_RING_SIZE
)
180 /* Let's build the HMAC text on the ring buffer. The text is composed
181 * as follows, in order:
183 * 1. Source IPv6 address (128 bits)
184 * 2. first_segment value (8 bits)
186 * 4. HMAC Key ID (32 bits)
187 * 5. All segments in the segments list (n * 128 bits)
191 ring
= this_cpu_ptr(hmac_ring
);
195 memcpy(off
, saddr
, 16);
198 /* first_segment value */
199 *off
++ = hdr
->first_segment
;
205 memcpy(off
, &hmackeyid
, 4);
208 /* all segments in the list */
209 for (i
= 0; i
< hdr
->first_segment
+ 1; i
++) {
210 memcpy(off
, hdr
->segments
+ i
, 16);
214 dgsize
= __do_hmac(hinfo
, ring
, plen
, tmp_out
,
215 SEG6_HMAC_MAX_DIGESTSIZE
);
221 wrsize
= SEG6_HMAC_FIELD_LEN
;
225 memset(output
, 0, SEG6_HMAC_FIELD_LEN
);
226 memcpy(output
, tmp_out
, wrsize
);
230 EXPORT_SYMBOL(seg6_hmac_compute
);
232 /* checks if an incoming SR-enabled packet's HMAC status matches
233 * the incoming policy.
235 * called with rcu_read_lock()
237 bool seg6_hmac_validate_skb(struct sk_buff
*skb
)
239 u8 hmac_output
[SEG6_HMAC_FIELD_LEN
];
240 struct net
*net
= dev_net(skb
->dev
);
241 struct seg6_hmac_info
*hinfo
;
242 struct sr6_tlv_hmac
*tlv
;
243 struct ipv6_sr_hdr
*srh
;
244 struct inet6_dev
*idev
;
246 idev
= __in6_dev_get(skb
->dev
);
248 srh
= (struct ipv6_sr_hdr
*)skb_transport_header(skb
);
250 tlv
= seg6_get_tlv_hmac(srh
);
252 /* mandatory check but no tlv */
253 if (idev
->cnf
.seg6_require_hmac
> 0 && !tlv
)
257 if (idev
->cnf
.seg6_require_hmac
< 0)
260 /* check only if present */
261 if (idev
->cnf
.seg6_require_hmac
== 0 && !tlv
)
264 /* now, seg6_require_hmac >= 0 && tlv */
266 hinfo
= seg6_hmac_info_lookup(net
, be32_to_cpu(tlv
->hmackeyid
));
270 if (seg6_hmac_compute(hinfo
, srh
, &ipv6_hdr(skb
)->saddr
, hmac_output
))
273 if (memcmp(hmac_output
, tlv
->hmac
, SEG6_HMAC_FIELD_LEN
) != 0)
278 EXPORT_SYMBOL(seg6_hmac_validate_skb
);
280 /* called with rcu_read_lock() */
281 struct seg6_hmac_info
*seg6_hmac_info_lookup(struct net
*net
, u32 key
)
283 struct seg6_pernet_data
*sdata
= seg6_pernet(net
);
284 struct seg6_hmac_info
*hinfo
;
286 hinfo
= rhashtable_lookup_fast(&sdata
->hmac_infos
, &key
, rht_params
);
290 EXPORT_SYMBOL(seg6_hmac_info_lookup
);
292 int seg6_hmac_info_add(struct net
*net
, u32 key
, struct seg6_hmac_info
*hinfo
)
294 struct seg6_pernet_data
*sdata
= seg6_pernet(net
);
297 err
= rhashtable_lookup_insert_fast(&sdata
->hmac_infos
, &hinfo
->node
,
302 EXPORT_SYMBOL(seg6_hmac_info_add
);
304 int seg6_hmac_info_del(struct net
*net
, u32 key
)
306 struct seg6_pernet_data
*sdata
= seg6_pernet(net
);
307 struct seg6_hmac_info
*hinfo
;
310 hinfo
= rhashtable_lookup_fast(&sdata
->hmac_infos
, &key
, rht_params
);
314 err
= rhashtable_remove_fast(&sdata
->hmac_infos
, &hinfo
->node
,
319 seg6_hinfo_release(hinfo
);
324 EXPORT_SYMBOL(seg6_hmac_info_del
);
326 int seg6_push_hmac(struct net
*net
, struct in6_addr
*saddr
,
327 struct ipv6_sr_hdr
*srh
)
329 struct seg6_hmac_info
*hinfo
;
330 struct sr6_tlv_hmac
*tlv
;
333 tlv
= seg6_get_tlv_hmac(srh
);
339 hinfo
= seg6_hmac_info_lookup(net
, be32_to_cpu(tlv
->hmackeyid
));
343 memset(tlv
->hmac
, 0, SEG6_HMAC_FIELD_LEN
);
344 err
= seg6_hmac_compute(hinfo
, srh
, saddr
, tlv
->hmac
);
350 EXPORT_SYMBOL(seg6_push_hmac
);
352 static int seg6_hmac_init_algo(void)
354 struct seg6_hmac_algo
*algo
;
355 struct crypto_shash
*tfm
;
356 struct shash_desc
*shash
;
357 int i
, alg_count
, cpu
;
359 alg_count
= ARRAY_SIZE(hmac_algos
);
361 for (i
= 0; i
< alg_count
; i
++) {
362 struct crypto_shash
**p_tfm
;
365 algo
= &hmac_algos
[i
];
366 algo
->tfms
= alloc_percpu(struct crypto_shash
*);
370 for_each_possible_cpu(cpu
) {
371 tfm
= crypto_alloc_shash(algo
->name
, 0, 0);
374 p_tfm
= per_cpu_ptr(algo
->tfms
, cpu
);
378 p_tfm
= raw_cpu_ptr(algo
->tfms
);
381 shsize
= sizeof(*shash
) + crypto_shash_descsize(tfm
);
383 algo
->shashs
= alloc_percpu(struct shash_desc
*);
387 for_each_possible_cpu(cpu
) {
388 shash
= kzalloc_node(shsize
, GFP_KERNEL
,
392 *per_cpu_ptr(algo
->shashs
, cpu
) = shash
;
399 int __init
seg6_hmac_init(void)
401 return seg6_hmac_init_algo();
403 EXPORT_SYMBOL(seg6_hmac_init
);
405 int __net_init
seg6_hmac_net_init(struct net
*net
)
407 struct seg6_pernet_data
*sdata
= seg6_pernet(net
);
409 rhashtable_init(&sdata
->hmac_infos
, &rht_params
);
413 EXPORT_SYMBOL(seg6_hmac_net_init
);
415 void seg6_hmac_exit(void)
417 struct seg6_hmac_algo
*algo
= NULL
;
418 int i
, alg_count
, cpu
;
420 alg_count
= ARRAY_SIZE(hmac_algos
);
421 for (i
= 0; i
< alg_count
; i
++) {
422 algo
= &hmac_algos
[i
];
423 for_each_possible_cpu(cpu
) {
424 struct crypto_shash
*tfm
;
425 struct shash_desc
*shash
;
427 shash
= *per_cpu_ptr(algo
->shashs
, cpu
);
429 tfm
= *per_cpu_ptr(algo
->tfms
, cpu
);
430 crypto_free_shash(tfm
);
432 free_percpu(algo
->tfms
);
433 free_percpu(algo
->shashs
);
436 EXPORT_SYMBOL(seg6_hmac_exit
);
438 void __net_exit
seg6_hmac_net_exit(struct net
*net
)
440 struct seg6_pernet_data
*sdata
= seg6_pernet(net
);
442 rhashtable_free_and_destroy(&sdata
->hmac_infos
, seg6_free_hi
, NULL
);
444 EXPORT_SYMBOL(seg6_hmac_net_exit
);