xref: /linux/drivers/net/netdevsim/psp.c (revision da630d1da2b19442c337bcbe3bb3fa66fda1f5bb)
1 // SPDX-License-Identifier: GPL-2.0
2 
3 #include <linux/ip.h>
4 #include <linux/skbuff.h>
5 #include <net/ip6_checksum.h>
6 #include <net/psp.h>
7 #include <net/sock.h>
8 
9 #include "netdevsim.h"
10 
11 void nsim_psp_handle_ext(struct sk_buff *skb, struct skb_ext *psp_ext)
12 {
13 	if (psp_ext)
14 		__skb_ext_set(skb, SKB_EXT_PSP, psp_ext);
15 }
16 
17 enum skb_drop_reason
18 nsim_do_psp(struct sk_buff *skb, struct netdevsim *ns,
19 	    struct netdevsim *peer_ns, struct skb_ext **psp_ext)
20 {
21 	enum skb_drop_reason rc = 0;
22 	struct psp_dev *peer_psd;
23 	struct psp_assoc *pas;
24 	struct net *net;
25 	int psp_len;
26 
27 	rcu_read_lock();
28 	pas = psp_skb_get_assoc_rcu(skb);
29 	if (!pas) {
30 		rc = SKB_NOT_DROPPED_YET;
31 		goto out_unlock;
32 	}
33 
34 	if (!skb_transport_header_was_set(skb)) {
35 		rc = SKB_DROP_REASON_PSP_OUTPUT;
36 		goto out_unlock;
37 	}
38 
39 	net = sock_net(skb->sk);
40 	if (!psp_dev_encapsulate(net, skb, pas->tx.spi, pas->version, 0)) {
41 		rc = SKB_DROP_REASON_PSP_OUTPUT;
42 		goto out_unlock;
43 	}
44 
45 	psp_len = skb->len - skb_inner_transport_offset(skb);
46 	atomic64_inc(&ns->psp.tx_packets);
47 	atomic64_add(psp_len, &ns->psp.tx_bytes);
48 
49 	/* Now pretend we just received this frame */
50 	peer_psd = rcu_dereference(peer_ns->psp.dev);
51 	if (peer_psd && peer_psd->config.versions & (1 << pas->version)) {
52 		bool strip_icv = false;
53 		u8 generation;
54 
55 		/* We cheat a bit and put the generation in the key.
56 		 * In real life if generation was too old, then decryption would
57 		 * fail. Here, we just make it so a bad key causes a bad
58 		 * generation too, and psp_sk_rx_policy_check() will fail.
59 		 */
60 		generation = pas->tx.key[0];
61 
62 		skb_ext_reset(skb);
63 		skb->mac_len = ETH_HLEN;
64 		if (psp_dev_rcv(skb, peer_psd->id, generation, strip_icv)) {
65 			rc = SKB_DROP_REASON_PSP_OUTPUT;
66 			goto out_unlock;
67 		}
68 
69 		*psp_ext = skb->extensions;
70 		refcount_inc(&(*psp_ext)->refcnt);
71 		skb->decrypted = 1;
72 
73 		atomic64_inc(&peer_ns->psp.rx_packets);
74 		atomic64_add(psp_len, &peer_ns->psp.rx_bytes);
75 	} else {
76 		struct ipv6hdr *ip6h __maybe_unused;
77 		struct iphdr *iph;
78 		struct udphdr *uh;
79 		__wsum csum;
80 		int udplen;
81 
82 		/* Do not decapsulate. Receive the skb with the udp and psp
83 		 * headers still there as if this is a normal udp packet.
84 		 * psp_dev_encapsulate() sets udp checksum to 0, so we need to
85 		 * provide a valid checksum here, so the skb isn't dropped.
86 		 */
87 		uh = udp_hdr(skb);
88 		udplen = udp_get_len(skb, uh, skb_transport_offset(skb));
89 		csum = skb_checksum(skb, skb_transport_offset(skb),
90 				    udplen, 0);
91 
92 		switch (skb->protocol) {
93 		case htons(ETH_P_IP):
94 			iph = ip_hdr(skb);
95 			uh->check = udp_v4_check(udplen, iph->saddr,
96 						 iph->daddr, csum);
97 			break;
98 #if IS_ENABLED(CONFIG_IPV6)
99 		case htons(ETH_P_IPV6):
100 			ip6h = ipv6_hdr(skb);
101 			uh->check = udp_v6_check(udplen, &ip6h->saddr,
102 						 &ip6h->daddr, csum);
103 			break;
104 #endif
105 		}
106 
107 		uh->check	= uh->check ?: CSUM_MANGLED_0;
108 		skb->ip_summed	= CHECKSUM_NONE;
109 	}
110 
111 out_unlock:
112 	rcu_read_unlock();
113 	return rc;
114 }
115 
116 static int
117 nsim_psp_set_config(struct psp_dev *psd, struct psp_dev_config *conf,
118 		    struct netlink_ext_ack *extack)
119 {
120 	return 0;
121 }
122 
123 static int
124 nsim_rx_spi_alloc(struct psp_dev *psd, u32 version,
125 		  struct psp_key_parsed *assoc,
126 		  struct netlink_ext_ack *extack)
127 {
128 	struct netdevsim *ns = psd->drv_priv;
129 	int i;
130 
131 	/* Check if incrementing the spi would change the phase bit */
132 	if ((ns->psp.spi & PSP_SPI_KEY_ID) == PSP_SPI_KEY_ID) {
133 		NL_SET_ERR_MSG(extack, "SPI space exhausted");
134 		return -ENOSPC;
135 	}
136 
137 	assoc->spi = cpu_to_be32(++ns->psp.spi);
138 	assoc->key[0] = psd->generation;
139 	for (i = 1; i < PSP_MAX_KEY; i++)
140 		assoc->key[i] = ns->psp.spi + i;
141 
142 	return 0;
143 }
144 
145 static int nsim_key_rotate(struct psp_dev *psd, struct netlink_ext_ack *extack)
146 {
147 	struct netdevsim *ns = psd->drv_priv;
148 
149 	/* Flip key phase and reset SPI to 0 within that space
150 	 * (will be pre-incremented, as 0 is an invalid SPI).
151 	 */
152 	if (ns->psp.spi & PSP_SPI_KEY_PHASE)
153 		ns->psp.spi = 0;
154 	else
155 		ns->psp.spi = PSP_SPI_KEY_PHASE;
156 
157 	return 0;
158 }
159 
160 static void nsim_get_stats(struct psp_dev *psd, struct psp_dev_stats *stats)
161 {
162 	struct netdevsim *ns = psd->drv_priv;
163 
164 	/* WARNING: do *not* blindly zero stats in real drivers!
165 	 * All required stats must be reported by the device!
166 	 */
167 	memset(stats, 0, sizeof(struct psp_dev_stats));
168 
169 	stats->rx_bytes = atomic64_read(&ns->psp.rx_bytes);
170 	stats->rx_packets = atomic64_read(&ns->psp.rx_packets);
171 	stats->tx_bytes = atomic64_read(&ns->psp.tx_bytes);
172 	stats->tx_packets = atomic64_read(&ns->psp.tx_packets);
173 }
174 
175 static struct psp_dev_ops nsim_psp_ops = {
176 	.set_config	= nsim_psp_set_config,
177 	.rx_spi_alloc	= nsim_rx_spi_alloc,
178 	.key_rotate	= nsim_key_rotate,
179 	.get_stats	= nsim_get_stats,
180 };
181 
182 static struct psp_dev_caps nsim_psp_caps = {
183 	.versions = 1 << PSP_VERSION_HDR0_AES_GCM_128 |
184 		    1 << PSP_VERSION_HDR0_AES_GMAC_128 |
185 		    1 << PSP_VERSION_HDR0_AES_GCM_256 |
186 		    1 << PSP_VERSION_HDR0_AES_GMAC_256,
187 };
188 
189 static void __nsim_psp_uninit(struct netdevsim *ns, bool teardown)
190 {
191 	struct psp_dev *psd;
192 
193 	psd = rcu_dereference_protected(ns->psp.dev,
194 					teardown ||
195 					lockdep_is_held(&ns->psp.rereg_lock));
196 	if (psd) {
197 		rcu_assign_pointer(ns->psp.dev, NULL);
198 		synchronize_rcu();
199 		psp_dev_unregister(psd);
200 	}
201 }
202 
203 void nsim_psp_uninit(struct netdevsim *ns)
204 {
205 	debugfs_remove(ns->psp.rereg);
206 	mutex_destroy(&ns->psp.rereg_lock);
207 	__nsim_psp_uninit(ns, true);
208 }
209 
210 static ssize_t
211 nsim_psp_rereg_write(struct file *file, const char __user *data, size_t count,
212 		     loff_t *ppos)
213 {
214 	struct netdevsim *ns = file->private_data;
215 	struct psp_dev *psd;
216 	ssize_t ret;
217 
218 	mutex_lock(&ns->psp.rereg_lock);
219 	__nsim_psp_uninit(ns, false);
220 
221 	psd = psp_dev_create(ns->netdev, &nsim_psp_ops, &nsim_psp_caps, ns);
222 	if (IS_ERR(psd)) {
223 		ret = PTR_ERR(psd);
224 		goto out;
225 	}
226 
227 	rcu_assign_pointer(ns->psp.dev, psd);
228 	ret = count;
229 out:
230 	mutex_unlock(&ns->psp.rereg_lock);
231 	return ret;
232 }
233 
234 static const struct file_operations nsim_psp_rereg_fops = {
235 	.open = simple_open,
236 	.write = nsim_psp_rereg_write,
237 	.llseek = generic_file_llseek,
238 	.owner = THIS_MODULE,
239 };
240 
241 int nsim_psp_init(struct netdevsim *ns)
242 {
243 	struct dentry *ddir = ns->nsim_dev_port->ddir;
244 	struct psp_dev *psd;
245 
246 	psd = psp_dev_create(ns->netdev, &nsim_psp_ops, &nsim_psp_caps, ns);
247 	if (IS_ERR(psd))
248 		return PTR_ERR(psd);
249 
250 	rcu_assign_pointer(ns->psp.dev, psd);
251 
252 	mutex_init(&ns->psp.rereg_lock);
253 	ns->psp.rereg = debugfs_create_file("psp_rereg", 0200, ddir, ns,
254 					    &nsim_psp_rereg_fops);
255 	return 0;
256 }
257