2 * SR-IPv6 implementation -- HMAC functions
5 * David Lebrun <david.lebrun@uclouvain.be>
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version
11 * 2 of the License, or (at your option) any later version.
14 #include <linux/errno.h>
15 #include <linux/kernel.h>
16 #include <linux/types.h>
17 #include <linux/socket.h>
18 #include <linux/sockios.h>
19 #include <linux/net.h>
20 #include <linux/netdevice.h>
21 #include <linux/in6.h>
22 #include <linux/icmpv6.h>
23 #include <linux/mroute6.h>
24 #include <linux/slab.h>
26 #include <linux/netfilter.h>
27 #include <linux/netfilter_ipv6.h>
33 #include <net/protocol.h>
34 #include <net/transp_v6.h>
35 #include <net/rawv6.h>
36 #include <net/ndisc.h>
37 #include <net/ip6_route.h>
38 #include <net/addrconf.h>
41 #include <linux/cryptohash.h>
42 #include <crypto/hash.h>
43 #include <crypto/sha.h>
45 #include <net/genetlink.h>
46 #include <net/seg6_hmac.h>
47 #include <linux/random.h>
49 static DEFINE_PER_CPU(char [SEG6_HMAC_RING_SIZE
], hmac_ring
);
51 static int seg6_hmac_cmpfn(struct rhashtable_compare_arg
*arg
, const void *obj
)
53 const struct seg6_hmac_info
*hinfo
= obj
;
55 return (hinfo
->hmackeyid
!= *(__u32
*)arg
->key
);
58 static inline void seg6_hinfo_release(struct seg6_hmac_info
*hinfo
)
60 kfree_rcu(hinfo
, rcu
);
63 static void seg6_free_hi(void *ptr
, void *arg
)
65 struct seg6_hmac_info
*hinfo
= (struct seg6_hmac_info
*)ptr
;
68 seg6_hinfo_release(hinfo
);
71 static const struct rhashtable_params rht_params
= {
72 .head_offset
= offsetof(struct seg6_hmac_info
, node
),
73 .key_offset
= offsetof(struct seg6_hmac_info
, hmackeyid
),
74 .key_len
= sizeof(u32
),
75 .automatic_shrinking
= true,
76 .obj_cmpfn
= seg6_hmac_cmpfn
,
79 static struct seg6_hmac_algo hmac_algos
[] = {
81 .alg_id
= SEG6_HMAC_ALGO_SHA1
,
85 .alg_id
= SEG6_HMAC_ALGO_SHA256
,
86 .name
= "hmac(sha256)",
90 static struct sr6_tlv_hmac
*seg6_get_tlv_hmac(struct ipv6_sr_hdr
*srh
)
92 struct sr6_tlv_hmac
*tlv
;
94 if (srh
->hdrlen
< (srh
->first_segment
+ 1) * 2 + 5)
97 if (!sr_has_hmac(srh
))
100 tlv
= (struct sr6_tlv_hmac
*)
101 ((char *)srh
+ ((srh
->hdrlen
+ 1) << 3) - 40);
103 if (tlv
->tlvhdr
.type
!= SR6_TLV_HMAC
|| tlv
->tlvhdr
.len
!= 38)
109 static struct seg6_hmac_algo
*__hmac_get_algo(u8 alg_id
)
111 struct seg6_hmac_algo
*algo
;
114 alg_count
= ARRAY_SIZE(hmac_algos
);
115 for (i
= 0; i
< alg_count
; i
++) {
116 algo
= &hmac_algos
[i
];
117 if (algo
->alg_id
== alg_id
)
124 static int __do_hmac(struct seg6_hmac_info
*hinfo
, const char *text
, u8 psize
,
125 u8
*output
, int outlen
)
127 struct seg6_hmac_algo
*algo
;
128 struct crypto_shash
*tfm
;
129 struct shash_desc
*shash
;
132 algo
= __hmac_get_algo(hinfo
->alg_id
);
136 tfm
= *this_cpu_ptr(algo
->tfms
);
138 dgsize
= crypto_shash_digestsize(tfm
);
139 if (dgsize
> outlen
) {
140 pr_debug("sr-ipv6: __do_hmac: digest size too big (%d / %d)\n",
145 ret
= crypto_shash_setkey(tfm
, hinfo
->secret
, hinfo
->slen
);
147 pr_debug("sr-ipv6: crypto_shash_setkey failed: err %d\n", ret
);
151 shash
= *this_cpu_ptr(algo
->shashs
);
154 ret
= crypto_shash_digest(shash
, text
, psize
, output
);
156 pr_debug("sr-ipv6: crypto_shash_digest failed: err %d\n", ret
);
166 int seg6_hmac_compute(struct seg6_hmac_info
*hinfo
, struct ipv6_sr_hdr
*hdr
,
167 struct in6_addr
*saddr
, u8
*output
)
169 __be32 hmackeyid
= cpu_to_be32(hinfo
->hmackeyid
);
170 u8 tmp_out
[SEG6_HMAC_MAX_DIGESTSIZE
];
171 int plen
, i
, dgsize
, wrsize
;
174 /* a 160-byte buffer for digest output allows to store highest known
175 * hash function (RadioGatun) with up to 1216 bits
178 /* saddr(16) + first_seg(1) + flags(1) + keyid(4) + seglist(16n) */
179 plen
= 16 + 1 + 1 + 4 + (hdr
->first_segment
+ 1) * 16;
181 /* this limit allows for 14 segments */
182 if (plen
>= SEG6_HMAC_RING_SIZE
)
185 /* Let's build the HMAC text on the ring buffer. The text is composed
186 * as follows, in order:
188 * 1. Source IPv6 address (128 bits)
189 * 2. first_segment value (8 bits)
191 * 4. HMAC Key ID (32 bits)
192 * 5. All segments in the segments list (n * 128 bits)
196 ring
= this_cpu_ptr(hmac_ring
);
200 memcpy(off
, saddr
, 16);
203 /* first_segment value */
204 *off
++ = hdr
->first_segment
;
210 memcpy(off
, &hmackeyid
, 4);
213 /* all segments in the list */
214 for (i
= 0; i
< hdr
->first_segment
+ 1; i
++) {
215 memcpy(off
, hdr
->segments
+ i
, 16);
219 dgsize
= __do_hmac(hinfo
, ring
, plen
, tmp_out
,
220 SEG6_HMAC_MAX_DIGESTSIZE
);
226 wrsize
= SEG6_HMAC_FIELD_LEN
;
230 memset(output
, 0, SEG6_HMAC_FIELD_LEN
);
231 memcpy(output
, tmp_out
, wrsize
);
235 EXPORT_SYMBOL(seg6_hmac_compute
);
237 /* checks if an incoming SR-enabled packet's HMAC status matches
238 * the incoming policy.
240 * called with rcu_read_lock()
242 bool seg6_hmac_validate_skb(struct sk_buff
*skb
)
244 u8 hmac_output
[SEG6_HMAC_FIELD_LEN
];
245 struct net
*net
= dev_net(skb
->dev
);
246 struct seg6_hmac_info
*hinfo
;
247 struct sr6_tlv_hmac
*tlv
;
248 struct ipv6_sr_hdr
*srh
;
249 struct inet6_dev
*idev
;
251 idev
= __in6_dev_get(skb
->dev
);
253 srh
= (struct ipv6_sr_hdr
*)skb_transport_header(skb
);
255 tlv
= seg6_get_tlv_hmac(srh
);
257 /* mandatory check but no tlv */
258 if (idev
->cnf
.seg6_require_hmac
> 0 && !tlv
)
262 if (idev
->cnf
.seg6_require_hmac
< 0)
265 /* check only if present */
266 if (idev
->cnf
.seg6_require_hmac
== 0 && !tlv
)
269 /* now, seg6_require_hmac >= 0 && tlv */
271 hinfo
= seg6_hmac_info_lookup(net
, be32_to_cpu(tlv
->hmackeyid
));
275 if (seg6_hmac_compute(hinfo
, srh
, &ipv6_hdr(skb
)->saddr
, hmac_output
))
278 if (memcmp(hmac_output
, tlv
->hmac
, SEG6_HMAC_FIELD_LEN
) != 0)
283 EXPORT_SYMBOL(seg6_hmac_validate_skb
);
285 /* called with rcu_read_lock() */
286 struct seg6_hmac_info
*seg6_hmac_info_lookup(struct net
*net
, u32 key
)
288 struct seg6_pernet_data
*sdata
= seg6_pernet(net
);
289 struct seg6_hmac_info
*hinfo
;
291 hinfo
= rhashtable_lookup_fast(&sdata
->hmac_infos
, &key
, rht_params
);
295 EXPORT_SYMBOL(seg6_hmac_info_lookup
);
297 int seg6_hmac_info_add(struct net
*net
, u32 key
, struct seg6_hmac_info
*hinfo
)
299 struct seg6_pernet_data
*sdata
= seg6_pernet(net
);
302 err
= rhashtable_lookup_insert_fast(&sdata
->hmac_infos
, &hinfo
->node
,
307 EXPORT_SYMBOL(seg6_hmac_info_add
);
309 int seg6_hmac_info_del(struct net
*net
, u32 key
)
311 struct seg6_pernet_data
*sdata
= seg6_pernet(net
);
312 struct seg6_hmac_info
*hinfo
;
315 hinfo
= rhashtable_lookup_fast(&sdata
->hmac_infos
, &key
, rht_params
);
319 err
= rhashtable_remove_fast(&sdata
->hmac_infos
, &hinfo
->node
,
324 seg6_hinfo_release(hinfo
);
329 EXPORT_SYMBOL(seg6_hmac_info_del
);
331 int seg6_push_hmac(struct net
*net
, struct in6_addr
*saddr
,
332 struct ipv6_sr_hdr
*srh
)
334 struct seg6_hmac_info
*hinfo
;
335 struct sr6_tlv_hmac
*tlv
;
338 tlv
= seg6_get_tlv_hmac(srh
);
344 hinfo
= seg6_hmac_info_lookup(net
, be32_to_cpu(tlv
->hmackeyid
));
348 memset(tlv
->hmac
, 0, SEG6_HMAC_FIELD_LEN
);
349 err
= seg6_hmac_compute(hinfo
, srh
, saddr
, tlv
->hmac
);
355 EXPORT_SYMBOL(seg6_push_hmac
);
357 static int seg6_hmac_init_algo(void)
359 struct seg6_hmac_algo
*algo
;
360 struct crypto_shash
*tfm
;
361 struct shash_desc
*shash
;
362 int i
, alg_count
, cpu
;
364 alg_count
= ARRAY_SIZE(hmac_algos
);
366 for (i
= 0; i
< alg_count
; i
++) {
367 struct crypto_shash
**p_tfm
;
370 algo
= &hmac_algos
[i
];
371 algo
->tfms
= alloc_percpu(struct crypto_shash
*);
375 for_each_possible_cpu(cpu
) {
376 tfm
= crypto_alloc_shash(algo
->name
, 0, GFP_KERNEL
);
379 p_tfm
= per_cpu_ptr(algo
->tfms
, cpu
);
383 p_tfm
= raw_cpu_ptr(algo
->tfms
);
386 shsize
= sizeof(*shash
) + crypto_shash_descsize(tfm
);
388 algo
->shashs
= alloc_percpu(struct shash_desc
*);
392 for_each_possible_cpu(cpu
) {
393 shash
= kzalloc_node(shsize
, GFP_KERNEL
,
397 *per_cpu_ptr(algo
->shashs
, cpu
) = shash
;
404 int __init
seg6_hmac_init(void)
406 return seg6_hmac_init_algo();
408 EXPORT_SYMBOL(seg6_hmac_init
);
410 int __net_init
seg6_hmac_net_init(struct net
*net
)
412 struct seg6_pernet_data
*sdata
= seg6_pernet(net
);
414 rhashtable_init(&sdata
->hmac_infos
, &rht_params
);
418 EXPORT_SYMBOL(seg6_hmac_net_init
);
420 void seg6_hmac_exit(void)
422 struct seg6_hmac_algo
*algo
= NULL
;
423 int i
, alg_count
, cpu
;
425 alg_count
= ARRAY_SIZE(hmac_algos
);
426 for (i
= 0; i
< alg_count
; i
++) {
427 algo
= &hmac_algos
[i
];
428 for_each_possible_cpu(cpu
) {
429 struct crypto_shash
*tfm
;
430 struct shash_desc
*shash
;
432 shash
= *per_cpu_ptr(algo
->shashs
, cpu
);
434 tfm
= *per_cpu_ptr(algo
->tfms
, cpu
);
435 crypto_free_shash(tfm
);
437 free_percpu(algo
->tfms
);
438 free_percpu(algo
->shashs
);
441 EXPORT_SYMBOL(seg6_hmac_exit
);
443 void __net_exit
seg6_hmac_net_exit(struct net
*net
)
445 struct seg6_pernet_data
*sdata
= seg6_pernet(net
);
447 rhashtable_free_and_destroy(&sdata
->hmac_infos
, seg6_free_hi
, NULL
);
449 EXPORT_SYMBOL(seg6_hmac_net_exit
);