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/types.h>
16 #include <linux/socket.h>
17 #include <linux/sockios.h>
18 #include <linux/net.h>
19 #include <linux/netdevice.h>
20 #include <linux/in6.h>
21 #include <linux/icmpv6.h>
22 #include <linux/mroute6.h>
23 #include <linux/slab.h>
25 #include <linux/netfilter.h>
26 #include <linux/netfilter_ipv6.h>
32 #include <net/protocol.h>
33 #include <net/transp_v6.h>
34 #include <net/rawv6.h>
35 #include <net/ndisc.h>
36 #include <net/ip6_route.h>
37 #include <net/addrconf.h>
40 #include <linux/cryptohash.h>
41 #include <crypto/hash.h>
42 #include <crypto/sha.h>
44 #include <net/genetlink.h>
45 #include <net/seg6_hmac.h>
46 #include <linux/random.h>
48 static DEFINE_PER_CPU(char [SEG6_HMAC_RING_SIZE
], hmac_ring
);
50 static int seg6_hmac_cmpfn(struct rhashtable_compare_arg
*arg
, const void *obj
)
52 const struct seg6_hmac_info
*hinfo
= obj
;
54 return (hinfo
->hmackeyid
!= *(__u32
*)arg
->key
);
57 static inline void seg6_hinfo_release(struct seg6_hmac_info
*hinfo
)
59 kfree_rcu(hinfo
, rcu
);
62 static void seg6_free_hi(void *ptr
, void *arg
)
64 struct seg6_hmac_info
*hinfo
= (struct seg6_hmac_info
*)ptr
;
67 seg6_hinfo_release(hinfo
);
70 static const struct rhashtable_params rht_params
= {
71 .head_offset
= offsetof(struct seg6_hmac_info
, node
),
72 .key_offset
= offsetof(struct seg6_hmac_info
, hmackeyid
),
73 .key_len
= sizeof(u32
),
74 .automatic_shrinking
= true,
75 .obj_cmpfn
= seg6_hmac_cmpfn
,
78 static struct seg6_hmac_algo hmac_algos
[] = {
80 .alg_id
= SEG6_HMAC_ALGO_SHA1
,
84 .alg_id
= SEG6_HMAC_ALGO_SHA256
,
85 .name
= "hmac(sha256)",
89 static struct sr6_tlv_hmac
*seg6_get_tlv_hmac(struct ipv6_sr_hdr
*srh
)
91 struct sr6_tlv_hmac
*tlv
;
93 if (srh
->hdrlen
< (srh
->first_segment
+ 1) * 2 + 5)
96 if (!sr_has_hmac(srh
))
99 tlv
= (struct sr6_tlv_hmac
*)
100 ((char *)srh
+ ((srh
->hdrlen
+ 1) << 3) - 40);
102 if (tlv
->tlvhdr
.type
!= SR6_TLV_HMAC
|| tlv
->tlvhdr
.len
!= 38)
108 static struct seg6_hmac_algo
*__hmac_get_algo(u8 alg_id
)
110 struct seg6_hmac_algo
*algo
;
113 alg_count
= sizeof(hmac_algos
) / sizeof(struct seg6_hmac_algo
);
114 for (i
= 0; i
< alg_count
; i
++) {
115 algo
= &hmac_algos
[i
];
116 if (algo
->alg_id
== alg_id
)
123 static int __do_hmac(struct seg6_hmac_info
*hinfo
, const char *text
, u8 psize
,
124 u8
*output
, int outlen
)
126 struct seg6_hmac_algo
*algo
;
127 struct crypto_shash
*tfm
;
128 struct shash_desc
*shash
;
131 algo
= __hmac_get_algo(hinfo
->alg_id
);
135 tfm
= *this_cpu_ptr(algo
->tfms
);
137 dgsize
= crypto_shash_digestsize(tfm
);
138 if (dgsize
> outlen
) {
139 pr_debug("sr-ipv6: __do_hmac: digest size too big (%d / %d)\n",
144 ret
= crypto_shash_setkey(tfm
, hinfo
->secret
, hinfo
->slen
);
146 pr_debug("sr-ipv6: crypto_shash_setkey failed: err %d\n", ret
);
150 shash
= *this_cpu_ptr(algo
->shashs
);
153 ret
= crypto_shash_digest(shash
, text
, psize
, output
);
155 pr_debug("sr-ipv6: crypto_shash_digest failed: err %d\n", ret
);
165 int seg6_hmac_compute(struct seg6_hmac_info
*hinfo
, struct ipv6_sr_hdr
*hdr
,
166 struct in6_addr
*saddr
, u8
*output
)
168 __be32 hmackeyid
= cpu_to_be32(hinfo
->hmackeyid
);
169 u8 tmp_out
[SEG6_HMAC_MAX_DIGESTSIZE
];
170 int plen
, i
, dgsize
, wrsize
;
173 /* a 160-byte buffer for digest output allows to store highest known
174 * hash function (RadioGatun) with up to 1216 bits
177 /* saddr(16) + first_seg(1) + flags(1) + keyid(4) + seglist(16n) */
178 plen
= 16 + 1 + 1 + 4 + (hdr
->first_segment
+ 1) * 16;
180 /* this limit allows for 14 segments */
181 if (plen
>= SEG6_HMAC_RING_SIZE
)
184 /* Let's build the HMAC text on the ring buffer. The text is composed
185 * as follows, in order:
187 * 1. Source IPv6 address (128 bits)
188 * 2. first_segment value (8 bits)
190 * 4. HMAC Key ID (32 bits)
191 * 5. All segments in the segments list (n * 128 bits)
195 ring
= this_cpu_ptr(hmac_ring
);
199 memcpy(off
, saddr
, 16);
202 /* first_segment value */
203 *off
++ = hdr
->first_segment
;
209 memcpy(off
, &hmackeyid
, 4);
212 /* all segments in the list */
213 for (i
= 0; i
< hdr
->first_segment
+ 1; i
++) {
214 memcpy(off
, hdr
->segments
+ i
, 16);
218 dgsize
= __do_hmac(hinfo
, ring
, plen
, tmp_out
,
219 SEG6_HMAC_MAX_DIGESTSIZE
);
225 wrsize
= SEG6_HMAC_FIELD_LEN
;
229 memset(output
, 0, SEG6_HMAC_FIELD_LEN
);
230 memcpy(output
, tmp_out
, wrsize
);
234 EXPORT_SYMBOL(seg6_hmac_compute
);
236 /* checks if an incoming SR-enabled packet's HMAC status matches
237 * the incoming policy.
239 * called with rcu_read_lock()
241 bool seg6_hmac_validate_skb(struct sk_buff
*skb
)
243 u8 hmac_output
[SEG6_HMAC_FIELD_LEN
];
244 struct net
*net
= dev_net(skb
->dev
);
245 struct seg6_hmac_info
*hinfo
;
246 struct sr6_tlv_hmac
*tlv
;
247 struct ipv6_sr_hdr
*srh
;
248 struct inet6_dev
*idev
;
250 idev
= __in6_dev_get(skb
->dev
);
252 srh
= (struct ipv6_sr_hdr
*)skb_transport_header(skb
);
254 tlv
= seg6_get_tlv_hmac(srh
);
256 /* mandatory check but no tlv */
257 if (idev
->cnf
.seg6_require_hmac
> 0 && !tlv
)
261 if (idev
->cnf
.seg6_require_hmac
< 0)
264 /* check only if present */
265 if (idev
->cnf
.seg6_require_hmac
== 0 && !tlv
)
268 /* now, seg6_require_hmac >= 0 && tlv */
270 hinfo
= seg6_hmac_info_lookup(net
, be32_to_cpu(tlv
->hmackeyid
));
274 if (seg6_hmac_compute(hinfo
, srh
, &ipv6_hdr(skb
)->saddr
, hmac_output
))
277 if (memcmp(hmac_output
, tlv
->hmac
, SEG6_HMAC_FIELD_LEN
) != 0)
282 EXPORT_SYMBOL(seg6_hmac_validate_skb
);
284 /* called with rcu_read_lock() */
285 struct seg6_hmac_info
*seg6_hmac_info_lookup(struct net
*net
, u32 key
)
287 struct seg6_pernet_data
*sdata
= seg6_pernet(net
);
288 struct seg6_hmac_info
*hinfo
;
290 hinfo
= rhashtable_lookup_fast(&sdata
->hmac_infos
, &key
, rht_params
);
294 EXPORT_SYMBOL(seg6_hmac_info_lookup
);
296 int seg6_hmac_info_add(struct net
*net
, u32 key
, struct seg6_hmac_info
*hinfo
)
298 struct seg6_pernet_data
*sdata
= seg6_pernet(net
);
301 err
= rhashtable_lookup_insert_fast(&sdata
->hmac_infos
, &hinfo
->node
,
306 EXPORT_SYMBOL(seg6_hmac_info_add
);
308 int seg6_hmac_info_del(struct net
*net
, u32 key
)
310 struct seg6_pernet_data
*sdata
= seg6_pernet(net
);
311 struct seg6_hmac_info
*hinfo
;
314 hinfo
= rhashtable_lookup_fast(&sdata
->hmac_infos
, &key
, rht_params
);
318 err
= rhashtable_remove_fast(&sdata
->hmac_infos
, &hinfo
->node
,
323 seg6_hinfo_release(hinfo
);
328 EXPORT_SYMBOL(seg6_hmac_info_del
);
330 int seg6_push_hmac(struct net
*net
, struct in6_addr
*saddr
,
331 struct ipv6_sr_hdr
*srh
)
333 struct seg6_hmac_info
*hinfo
;
334 struct sr6_tlv_hmac
*tlv
;
337 tlv
= seg6_get_tlv_hmac(srh
);
343 hinfo
= seg6_hmac_info_lookup(net
, be32_to_cpu(tlv
->hmackeyid
));
347 memset(tlv
->hmac
, 0, SEG6_HMAC_FIELD_LEN
);
348 err
= seg6_hmac_compute(hinfo
, srh
, saddr
, tlv
->hmac
);
354 EXPORT_SYMBOL(seg6_push_hmac
);
356 static int seg6_hmac_init_algo(void)
358 struct seg6_hmac_algo
*algo
;
359 struct crypto_shash
*tfm
;
360 struct shash_desc
*shash
;
361 int i
, alg_count
, cpu
;
363 alg_count
= sizeof(hmac_algos
) / sizeof(struct seg6_hmac_algo
);
365 for (i
= 0; i
< alg_count
; i
++) {
366 struct crypto_shash
**p_tfm
;
369 algo
= &hmac_algos
[i
];
370 algo
->tfms
= alloc_percpu(struct crypto_shash
*);
374 for_each_possible_cpu(cpu
) {
375 tfm
= crypto_alloc_shash(algo
->name
, 0, GFP_KERNEL
);
378 p_tfm
= per_cpu_ptr(algo
->tfms
, cpu
);
382 p_tfm
= raw_cpu_ptr(algo
->tfms
);
385 shsize
= sizeof(*shash
) + crypto_shash_descsize(tfm
);
387 algo
->shashs
= alloc_percpu(struct shash_desc
*);
391 for_each_possible_cpu(cpu
) {
392 shash
= kzalloc_node(shsize
, GFP_KERNEL
,
396 *per_cpu_ptr(algo
->shashs
, cpu
) = shash
;
403 int __init
seg6_hmac_init(void)
405 return seg6_hmac_init_algo();
407 EXPORT_SYMBOL(seg6_hmac_init
);
409 int __net_init
seg6_hmac_net_init(struct net
*net
)
411 struct seg6_pernet_data
*sdata
= seg6_pernet(net
);
413 rhashtable_init(&sdata
->hmac_infos
, &rht_params
);
417 EXPORT_SYMBOL(seg6_hmac_net_init
);
419 void seg6_hmac_exit(void)
421 struct seg6_hmac_algo
*algo
= NULL
;
422 int i
, alg_count
, cpu
;
424 alg_count
= sizeof(hmac_algos
) / sizeof(struct seg6_hmac_algo
);
425 for (i
= 0; i
< alg_count
; i
++) {
426 algo
= &hmac_algos
[i
];
427 for_each_possible_cpu(cpu
) {
428 struct crypto_shash
*tfm
;
429 struct shash_desc
*shash
;
431 shash
= *per_cpu_ptr(algo
->shashs
, cpu
);
433 tfm
= *per_cpu_ptr(algo
->tfms
, cpu
);
434 crypto_free_shash(tfm
);
436 free_percpu(algo
->tfms
);
437 free_percpu(algo
->shashs
);
440 EXPORT_SYMBOL(seg6_hmac_exit
);
442 void __net_exit
seg6_hmac_net_exit(struct net
*net
)
444 struct seg6_pernet_data
*sdata
= seg6_pernet(net
);
446 rhashtable_free_and_destroy(&sdata
->hmac_infos
, seg6_free_hi
, NULL
);
448 EXPORT_SYMBOL(seg6_hmac_net_exit
);