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>
25 #include <linux/rhashtable.h>
27 #include <linux/netfilter.h>
28 #include <linux/netfilter_ipv6.h>
34 #include <net/protocol.h>
35 #include <net/transp_v6.h>
36 #include <net/rawv6.h>
37 #include <net/ndisc.h>
38 #include <net/ip6_route.h>
39 #include <net/addrconf.h>
42 #include <linux/cryptohash.h>
43 #include <crypto/hash.h>
44 #include <crypto/sha.h>
46 #include <net/genetlink.h>
47 #include <net/seg6_hmac.h>
48 #include <linux/random.h>
50 static DEFINE_PER_CPU(char [SEG6_HMAC_RING_SIZE
], hmac_ring
);
52 static int seg6_hmac_cmpfn(struct rhashtable_compare_arg
*arg
, const void *obj
)
54 const struct seg6_hmac_info
*hinfo
= obj
;
56 return (hinfo
->hmackeyid
!= *(__u32
*)arg
->key
);
59 static inline void seg6_hinfo_release(struct seg6_hmac_info
*hinfo
)
61 kfree_rcu(hinfo
, rcu
);
64 static void seg6_free_hi(void *ptr
, void *arg
)
66 struct seg6_hmac_info
*hinfo
= (struct seg6_hmac_info
*)ptr
;
69 seg6_hinfo_release(hinfo
);
72 static const struct rhashtable_params rht_params
= {
73 .head_offset
= offsetof(struct seg6_hmac_info
, node
),
74 .key_offset
= offsetof(struct seg6_hmac_info
, hmackeyid
),
75 .key_len
= sizeof(u32
),
76 .automatic_shrinking
= true,
77 .obj_cmpfn
= seg6_hmac_cmpfn
,
80 static struct seg6_hmac_algo hmac_algos
[] = {
82 .alg_id
= SEG6_HMAC_ALGO_SHA1
,
86 .alg_id
= SEG6_HMAC_ALGO_SHA256
,
87 .name
= "hmac(sha256)",
91 static struct sr6_tlv_hmac
*seg6_get_tlv_hmac(struct ipv6_sr_hdr
*srh
)
93 struct sr6_tlv_hmac
*tlv
;
95 if (srh
->hdrlen
< (srh
->first_segment
+ 1) * 2 + 5)
98 if (!sr_has_hmac(srh
))
101 tlv
= (struct sr6_tlv_hmac
*)
102 ((char *)srh
+ ((srh
->hdrlen
+ 1) << 3) - 40);
104 if (tlv
->tlvhdr
.type
!= SR6_TLV_HMAC
|| tlv
->tlvhdr
.len
!= 38)
110 static struct seg6_hmac_algo
*__hmac_get_algo(u8 alg_id
)
112 struct seg6_hmac_algo
*algo
;
115 alg_count
= ARRAY_SIZE(hmac_algos
);
116 for (i
= 0; i
< alg_count
; i
++) {
117 algo
= &hmac_algos
[i
];
118 if (algo
->alg_id
== alg_id
)
125 static int __do_hmac(struct seg6_hmac_info
*hinfo
, const char *text
, u8 psize
,
126 u8
*output
, int outlen
)
128 struct seg6_hmac_algo
*algo
;
129 struct crypto_shash
*tfm
;
130 struct shash_desc
*shash
;
133 algo
= __hmac_get_algo(hinfo
->alg_id
);
137 tfm
= *this_cpu_ptr(algo
->tfms
);
139 dgsize
= crypto_shash_digestsize(tfm
);
140 if (dgsize
> outlen
) {
141 pr_debug("sr-ipv6: __do_hmac: digest size too big (%d / %d)\n",
146 ret
= crypto_shash_setkey(tfm
, hinfo
->secret
, hinfo
->slen
);
148 pr_debug("sr-ipv6: crypto_shash_setkey failed: err %d\n", ret
);
152 shash
= *this_cpu_ptr(algo
->shashs
);
155 ret
= crypto_shash_digest(shash
, text
, psize
, output
);
157 pr_debug("sr-ipv6: crypto_shash_digest failed: err %d\n", ret
);
167 int seg6_hmac_compute(struct seg6_hmac_info
*hinfo
, struct ipv6_sr_hdr
*hdr
,
168 struct in6_addr
*saddr
, u8
*output
)
170 __be32 hmackeyid
= cpu_to_be32(hinfo
->hmackeyid
);
171 u8 tmp_out
[SEG6_HMAC_MAX_DIGESTSIZE
];
172 int plen
, i
, dgsize
, wrsize
;
175 /* a 160-byte buffer for digest output allows to store highest known
176 * hash function (RadioGatun) with up to 1216 bits
179 /* saddr(16) + first_seg(1) + flags(1) + keyid(4) + seglist(16n) */
180 plen
= 16 + 1 + 1 + 4 + (hdr
->first_segment
+ 1) * 16;
182 /* this limit allows for 14 segments */
183 if (plen
>= SEG6_HMAC_RING_SIZE
)
186 /* Let's build the HMAC text on the ring buffer. The text is composed
187 * as follows, in order:
189 * 1. Source IPv6 address (128 bits)
190 * 2. first_segment value (8 bits)
192 * 4. HMAC Key ID (32 bits)
193 * 5. All segments in the segments list (n * 128 bits)
197 ring
= this_cpu_ptr(hmac_ring
);
201 memcpy(off
, saddr
, 16);
204 /* first_segment value */
205 *off
++ = hdr
->first_segment
;
211 memcpy(off
, &hmackeyid
, 4);
214 /* all segments in the list */
215 for (i
= 0; i
< hdr
->first_segment
+ 1; i
++) {
216 memcpy(off
, hdr
->segments
+ i
, 16);
220 dgsize
= __do_hmac(hinfo
, ring
, plen
, tmp_out
,
221 SEG6_HMAC_MAX_DIGESTSIZE
);
227 wrsize
= SEG6_HMAC_FIELD_LEN
;
231 memset(output
, 0, SEG6_HMAC_FIELD_LEN
);
232 memcpy(output
, tmp_out
, wrsize
);
236 EXPORT_SYMBOL(seg6_hmac_compute
);
238 /* checks if an incoming SR-enabled packet's HMAC status matches
239 * the incoming policy.
241 * called with rcu_read_lock()
243 bool seg6_hmac_validate_skb(struct sk_buff
*skb
)
245 u8 hmac_output
[SEG6_HMAC_FIELD_LEN
];
246 struct net
*net
= dev_net(skb
->dev
);
247 struct seg6_hmac_info
*hinfo
;
248 struct sr6_tlv_hmac
*tlv
;
249 struct ipv6_sr_hdr
*srh
;
250 struct inet6_dev
*idev
;
252 idev
= __in6_dev_get(skb
->dev
);
254 srh
= (struct ipv6_sr_hdr
*)skb_transport_header(skb
);
256 tlv
= seg6_get_tlv_hmac(srh
);
258 /* mandatory check but no tlv */
259 if (idev
->cnf
.seg6_require_hmac
> 0 && !tlv
)
263 if (idev
->cnf
.seg6_require_hmac
< 0)
266 /* check only if present */
267 if (idev
->cnf
.seg6_require_hmac
== 0 && !tlv
)
270 /* now, seg6_require_hmac >= 0 && tlv */
272 hinfo
= seg6_hmac_info_lookup(net
, be32_to_cpu(tlv
->hmackeyid
));
276 if (seg6_hmac_compute(hinfo
, srh
, &ipv6_hdr(skb
)->saddr
, hmac_output
))
279 if (memcmp(hmac_output
, tlv
->hmac
, SEG6_HMAC_FIELD_LEN
) != 0)
284 EXPORT_SYMBOL(seg6_hmac_validate_skb
);
286 /* called with rcu_read_lock() */
287 struct seg6_hmac_info
*seg6_hmac_info_lookup(struct net
*net
, u32 key
)
289 struct seg6_pernet_data
*sdata
= seg6_pernet(net
);
290 struct seg6_hmac_info
*hinfo
;
292 hinfo
= rhashtable_lookup_fast(&sdata
->hmac_infos
, &key
, rht_params
);
296 EXPORT_SYMBOL(seg6_hmac_info_lookup
);
298 int seg6_hmac_info_add(struct net
*net
, u32 key
, struct seg6_hmac_info
*hinfo
)
300 struct seg6_pernet_data
*sdata
= seg6_pernet(net
);
303 err
= rhashtable_lookup_insert_fast(&sdata
->hmac_infos
, &hinfo
->node
,
308 EXPORT_SYMBOL(seg6_hmac_info_add
);
310 int seg6_hmac_info_del(struct net
*net
, u32 key
)
312 struct seg6_pernet_data
*sdata
= seg6_pernet(net
);
313 struct seg6_hmac_info
*hinfo
;
316 hinfo
= rhashtable_lookup_fast(&sdata
->hmac_infos
, &key
, rht_params
);
320 err
= rhashtable_remove_fast(&sdata
->hmac_infos
, &hinfo
->node
,
325 seg6_hinfo_release(hinfo
);
330 EXPORT_SYMBOL(seg6_hmac_info_del
);
332 int seg6_push_hmac(struct net
*net
, struct in6_addr
*saddr
,
333 struct ipv6_sr_hdr
*srh
)
335 struct seg6_hmac_info
*hinfo
;
336 struct sr6_tlv_hmac
*tlv
;
339 tlv
= seg6_get_tlv_hmac(srh
);
345 hinfo
= seg6_hmac_info_lookup(net
, be32_to_cpu(tlv
->hmackeyid
));
349 memset(tlv
->hmac
, 0, SEG6_HMAC_FIELD_LEN
);
350 err
= seg6_hmac_compute(hinfo
, srh
, saddr
, tlv
->hmac
);
356 EXPORT_SYMBOL(seg6_push_hmac
);
358 static int seg6_hmac_init_algo(void)
360 struct seg6_hmac_algo
*algo
;
361 struct crypto_shash
*tfm
;
362 struct shash_desc
*shash
;
363 int i
, alg_count
, cpu
;
365 alg_count
= ARRAY_SIZE(hmac_algos
);
367 for (i
= 0; i
< alg_count
; i
++) {
368 struct crypto_shash
**p_tfm
;
371 algo
= &hmac_algos
[i
];
372 algo
->tfms
= alloc_percpu(struct crypto_shash
*);
376 for_each_possible_cpu(cpu
) {
377 tfm
= crypto_alloc_shash(algo
->name
, 0, 0);
380 p_tfm
= per_cpu_ptr(algo
->tfms
, cpu
);
384 p_tfm
= raw_cpu_ptr(algo
->tfms
);
387 shsize
= sizeof(*shash
) + crypto_shash_descsize(tfm
);
389 algo
->shashs
= alloc_percpu(struct shash_desc
*);
393 for_each_possible_cpu(cpu
) {
394 shash
= kzalloc_node(shsize
, GFP_KERNEL
,
398 *per_cpu_ptr(algo
->shashs
, cpu
) = shash
;
405 int __init
seg6_hmac_init(void)
407 return seg6_hmac_init_algo();
409 EXPORT_SYMBOL(seg6_hmac_init
);
411 int __net_init
seg6_hmac_net_init(struct net
*net
)
413 struct seg6_pernet_data
*sdata
= seg6_pernet(net
);
415 rhashtable_init(&sdata
->hmac_infos
, &rht_params
);
419 EXPORT_SYMBOL(seg6_hmac_net_init
);
421 void seg6_hmac_exit(void)
423 struct seg6_hmac_algo
*algo
= NULL
;
424 int i
, alg_count
, cpu
;
426 alg_count
= ARRAY_SIZE(hmac_algos
);
427 for (i
= 0; i
< alg_count
; i
++) {
428 algo
= &hmac_algos
[i
];
429 for_each_possible_cpu(cpu
) {
430 struct crypto_shash
*tfm
;
431 struct shash_desc
*shash
;
433 shash
= *per_cpu_ptr(algo
->shashs
, cpu
);
435 tfm
= *per_cpu_ptr(algo
->tfms
, cpu
);
436 crypto_free_shash(tfm
);
438 free_percpu(algo
->tfms
);
439 free_percpu(algo
->shashs
);
442 EXPORT_SYMBOL(seg6_hmac_exit
);
444 void __net_exit
seg6_hmac_net_exit(struct net
*net
)
446 struct seg6_pernet_data
*sdata
= seg6_pernet(net
);
448 rhashtable_free_and_destroy(&sdata
->hmac_infos
, seg6_free_hi
, NULL
);
450 EXPORT_SYMBOL(seg6_hmac_net_exit
);