Skip to content

Commit bf355b8

Browse files
David Lebrundavem330
authored andcommitted
ipv6: sr: add core files for SR HMAC support
This patch adds the necessary functions to compute and check the HMAC signature of an SR-enabled packet. Two HMAC algorithms are supported: hmac(sha1) and hmac(sha256). In order to avoid dynamic memory allocation for each HMAC computation, a per-cpu ring buffer is allocated for this purpose. A new per-interface sysctl called seg6_require_hmac is added, allowing a user-defined policy for processing HMAC-signed SR-enabled packets. A value of -1 means that the HMAC field will always be ignored. A value of 0 means that if an HMAC field is present, its validity will be enforced (the packet is dropped is the signature is incorrect). Finally, a value of 1 means that any SR-enabled packet that does not contain an HMAC signature or whose signature is incorrect will be dropped. Signed-off-by: David Lebrun <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 6c8702c commit bf355b8

File tree

10 files changed

+612
-0
lines changed

10 files changed

+612
-0
lines changed

include/linux/ipv6.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,9 @@ struct ipv6_devconf {
6565
__s32 use_oif_addrs_only;
6666
__s32 keep_addr_on_down;
6767
__s32 seg6_enabled;
68+
#ifdef CONFIG_IPV6_SEG6_HMAC
69+
__s32 seg6_require_hmac;
70+
#endif
6871

6972
struct ctl_table_header *sysctl_header;
7073
};

include/linux/seg6_hmac.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#ifndef _LINUX_SEG6_HMAC_H
2+
#define _LINUX_SEG6_HMAC_H
3+
4+
#include <uapi/linux/seg6_hmac.h>
5+
6+
#endif

include/net/seg6.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include <linux/ipv6.h>
1919
#include <net/lwtunnel.h>
2020
#include <linux/seg6.h>
21+
#include <linux/rhashtable.h>
2122

2223
static inline void update_csum_diff4(struct sk_buff *skb, __be32 from,
2324
__be32 to)
@@ -41,6 +42,9 @@ static inline void update_csum_diff16(struct sk_buff *skb, __be32 *from,
4142
struct seg6_pernet_data {
4243
struct mutex lock;
4344
struct in6_addr __rcu *tun_src;
45+
#ifdef CONFIG_IPV6_SEG6_HMAC
46+
struct rhashtable hmac_infos;
47+
#endif
4448
};
4549

4650
static inline struct seg6_pernet_data *seg6_pernet(struct net *net)

include/net/seg6_hmac.h

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/*
2+
* SR-IPv6 implementation
3+
*
4+
* Author:
5+
* David Lebrun <[email protected]>
6+
*
7+
*
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.
12+
*/
13+
14+
#ifndef _NET_SEG6_HMAC_H
15+
#define _NET_SEG6_HMAC_H
16+
17+
#include <net/flow.h>
18+
#include <net/ip6_fib.h>
19+
#include <net/sock.h>
20+
#include <linux/ip.h>
21+
#include <linux/ipv6.h>
22+
#include <linux/route.h>
23+
#include <net/seg6.h>
24+
#include <linux/seg6_hmac.h>
25+
#include <linux/rhashtable.h>
26+
27+
#define SEG6_HMAC_MAX_DIGESTSIZE 160
28+
#define SEG6_HMAC_RING_SIZE 256
29+
30+
struct seg6_hmac_info {
31+
struct rhash_head node;
32+
struct rcu_head rcu;
33+
34+
u32 hmackeyid;
35+
char secret[SEG6_HMAC_SECRET_LEN];
36+
u8 slen;
37+
u8 alg_id;
38+
};
39+
40+
struct seg6_hmac_algo {
41+
u8 alg_id;
42+
char name[64];
43+
struct crypto_shash * __percpu *tfms;
44+
struct shash_desc * __percpu *shashs;
45+
};
46+
47+
extern int seg6_hmac_compute(struct seg6_hmac_info *hinfo,
48+
struct ipv6_sr_hdr *hdr, struct in6_addr *saddr,
49+
u8 *output);
50+
extern struct seg6_hmac_info *seg6_hmac_info_lookup(struct net *net, u32 key);
51+
extern int seg6_hmac_info_add(struct net *net, u32 key,
52+
struct seg6_hmac_info *hinfo);
53+
extern int seg6_hmac_info_del(struct net *net, u32 key);
54+
extern int seg6_push_hmac(struct net *net, struct in6_addr *saddr,
55+
struct ipv6_sr_hdr *srh);
56+
extern bool seg6_hmac_validate_skb(struct sk_buff *skb);
57+
extern int seg6_hmac_init(void);
58+
extern void seg6_hmac_exit(void);
59+
extern int seg6_hmac_net_init(struct net *net);
60+
extern void seg6_hmac_net_exit(struct net *net);
61+
62+
#endif

include/uapi/linux/ipv6.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,7 @@ enum {
180180
DEVCONF_KEEP_ADDR_ON_DOWN,
181181
DEVCONF_RTR_SOLICIT_MAX_INTERVAL,
182182
DEVCONF_SEG6_ENABLED,
183+
DEVCONF_SEG6_REQUIRE_HMAC,
183184
DEVCONF_MAX
184185
};
185186

include/uapi/linux/seg6_hmac.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#ifndef _UAPI_LINUX_SEG6_HMAC_H
2+
#define _UAPI_LINUX_SEG6_HMAC_H
3+
4+
#include <linux/seg6.h>
5+
6+
#define SEG6_HMAC_SECRET_LEN 64
7+
#define SEG6_HMAC_FIELD_LEN 32
8+
9+
struct sr6_tlv_hmac {
10+
struct sr6_tlv tlvhdr;
11+
__u16 reserved;
12+
__be32 hmackeyid;
13+
__u8 hmac[SEG6_HMAC_FIELD_LEN];
14+
};
15+
16+
enum {
17+
SEG6_HMAC_ALGO_SHA1 = 1,
18+
SEG6_HMAC_ALGO_SHA256 = 2,
19+
};
20+
21+
#endif

net/ipv6/Kconfig

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,4 +301,16 @@ config IPV6_SEG6_INLINE
301301

302302
If unsure, say N.
303303

304+
config IPV6_SEG6_HMAC
305+
bool "IPv6: Segment Routing HMAC support"
306+
depends on IPV6
307+
select CRYPTO_HMAC
308+
select CRYPTO_SHA1
309+
select CRYPTO_SHA256
310+
---help---
311+
Support for HMAC signature generation and verification
312+
of SR-enabled packets.
313+
314+
If unsure, say N.
315+
304316
endif # IPV6

net/ipv6/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ obj-$(CONFIG_IPV6_SIT) += sit.o
4444
obj-$(CONFIG_IPV6_TUNNEL) += ip6_tunnel.o
4545
obj-$(CONFIG_IPV6_GRE) += ip6_gre.o
4646
obj-$(CONFIG_IPV6_FOU) += fou6.o
47+
obj-$(CONFIG_IPV6_SEG6_HMAC) += seg6_hmac.o
4748

4849
obj-y += addrconf_core.o exthdrs_core.o ip6_checksum.o ip6_icmp.o
4950
obj-$(CONFIG_INET) += output_core.o protocol.o $(ipv6-offload)

net/ipv6/addrconf.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,9 @@ static struct ipv6_devconf ipv6_devconf __read_mostly = {
239239
.ignore_routes_with_linkdown = 0,
240240
.keep_addr_on_down = 0,
241241
.seg6_enabled = 0,
242+
#ifdef CONFIG_IPV6_SEG6_HMAC
243+
.seg6_require_hmac = 0,
244+
#endif
242245
};
243246

244247
static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = {
@@ -286,6 +289,9 @@ static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = {
286289
.ignore_routes_with_linkdown = 0,
287290
.keep_addr_on_down = 0,
288291
.seg6_enabled = 0,
292+
#ifdef CONFIG_IPV6_SEG6_HMAC
293+
.seg6_require_hmac = 0,
294+
#endif
289295
};
290296

291297
/* Check if a valid qdisc is available */
@@ -4947,6 +4953,9 @@ static inline void ipv6_store_devconf(struct ipv6_devconf *cnf,
49474953
array[DEVCONF_DROP_UNSOLICITED_NA] = cnf->drop_unsolicited_na;
49484954
array[DEVCONF_KEEP_ADDR_ON_DOWN] = cnf->keep_addr_on_down;
49494955
array[DEVCONF_SEG6_ENABLED] = cnf->seg6_enabled;
4956+
#ifdef CONFIG_IPV6_SEG6_HMAC
4957+
array[DEVCONF_SEG6_REQUIRE_HMAC] = cnf->seg6_require_hmac;
4958+
#endif
49504959
}
49514960

49524961
static inline size_t inet6_ifla6_size(void)
@@ -6045,6 +6054,15 @@ static const struct ctl_table addrconf_sysctl[] = {
60456054
.mode = 0644,
60466055
.proc_handler = proc_dointvec,
60476056
},
6057+
#ifdef CONFIG_IPV6_SEG6_HMAC
6058+
{
6059+
.procname = "seg6_require_hmac",
6060+
.data = &ipv6_devconf.seg6_require_hmac,
6061+
.maxlen = sizeof(int),
6062+
.mode = 0644,
6063+
.proc_handler = proc_dointvec,
6064+
},
6065+
#endif
60486066
{
60496067
/* sentinel */
60506068
}

0 commit comments

Comments
 (0)