xref: /dpdk/lib/security/rte_security.c (revision af0785a2447b307965377b62f46a5f39457a85a3)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright 2017 NXP.
3  * Copyright(c) 2017 Intel Corporation.
4  * Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved
5  */
6 
7 #include <ctype.h>
8 #include <stdlib.h>
9 
10 #include <rte_cryptodev.h>
11 #include <dev_driver.h>
12 #include <rte_telemetry.h>
13 #include "rte_security.h"
14 #include "rte_security_driver.h"
15 
16 /* Macro to check for invalid pointers */
17 #define RTE_PTR_OR_ERR_RET(ptr, retval) do {	\
18 	if ((ptr) == NULL)			\
19 		return retval;			\
20 } while (0)
21 
22 /* Macro to check for invalid pointers chains */
23 #define RTE_PTR_CHAIN3_OR_ERR_RET(p1, p2, p3, retval, last_retval) do {	\
24 	RTE_PTR_OR_ERR_RET(p1, retval);					\
25 	RTE_PTR_OR_ERR_RET(p1->p2, retval);				\
26 	RTE_PTR_OR_ERR_RET(p1->p2->p3, last_retval);			\
27 } while (0)
28 
29 #define RTE_SECURITY_DYNFIELD_NAME "rte_security_dynfield_metadata"
30 int rte_security_dynfield_offset = -1;
31 
32 int
33 rte_security_dynfield_register(void)
34 {
35 	static const struct rte_mbuf_dynfield dynfield_desc = {
36 		.name = RTE_SECURITY_DYNFIELD_NAME,
37 		.size = sizeof(rte_security_dynfield_t),
38 		.align = __alignof__(rte_security_dynfield_t),
39 	};
40 	rte_security_dynfield_offset =
41 		rte_mbuf_dynfield_register(&dynfield_desc);
42 	return rte_security_dynfield_offset;
43 }
44 
45 void *
46 rte_security_session_create(struct rte_security_ctx *instance,
47 			    struct rte_security_session_conf *conf,
48 			    struct rte_mempool *mp)
49 {
50 	struct rte_security_session *sess = NULL;
51 	uint32_t sess_priv_size;
52 
53 	RTE_PTR_CHAIN3_OR_ERR_RET(instance, ops, session_create, NULL, NULL);
54 	RTE_PTR_OR_ERR_RET(conf, NULL);
55 	RTE_PTR_OR_ERR_RET(mp, NULL);
56 
57 	sess_priv_size = instance->ops->session_get_size(instance->device);
58 	if (mp->elt_size < (sizeof(struct rte_security_session) + sess_priv_size))
59 		return NULL;
60 
61 	if (rte_mempool_get(mp, (void **)&sess))
62 		return NULL;
63 
64 	/* Clear session priv data */
65 	memset(sess->driver_priv_data, 0, sess_priv_size);
66 
67 	sess->driver_priv_data_iova = rte_mempool_virt2iova(sess) +
68 			offsetof(struct rte_security_session, driver_priv_data);
69 	if (instance->ops->session_create(instance->device, conf, sess)) {
70 		rte_mempool_put(mp, (void *)sess);
71 		return NULL;
72 	}
73 	instance->sess_cnt++;
74 
75 	return (void *)sess;
76 }
77 
78 int
79 rte_security_session_update(struct rte_security_ctx *instance,
80 			    void *sess,
81 			    struct rte_security_session_conf *conf)
82 {
83 	RTE_PTR_CHAIN3_OR_ERR_RET(instance, ops, session_update, -EINVAL,
84 			-ENOTSUP);
85 	RTE_PTR_OR_ERR_RET(sess, -EINVAL);
86 	RTE_PTR_OR_ERR_RET(conf, -EINVAL);
87 
88 	return instance->ops->session_update(instance->device, sess, conf);
89 }
90 
91 unsigned int
92 rte_security_session_get_size(struct rte_security_ctx *instance)
93 {
94 	RTE_PTR_CHAIN3_OR_ERR_RET(instance, ops, session_get_size, 0, 0);
95 
96 	return (sizeof(struct rte_security_session) +
97 			instance->ops->session_get_size(instance->device));
98 }
99 
100 int
101 rte_security_session_stats_get(struct rte_security_ctx *instance,
102 			       void *sess,
103 			       struct rte_security_stats *stats)
104 {
105 	RTE_PTR_CHAIN3_OR_ERR_RET(instance, ops, session_stats_get, -EINVAL,
106 			-ENOTSUP);
107 	/* Parameter sess can be NULL in case of getting global statistics. */
108 	RTE_PTR_OR_ERR_RET(stats, -EINVAL);
109 
110 	return instance->ops->session_stats_get(instance->device, sess, stats);
111 }
112 
113 int
114 rte_security_session_destroy(struct rte_security_ctx *instance, void *sess)
115 {
116 	int ret;
117 
118 	RTE_PTR_CHAIN3_OR_ERR_RET(instance, ops, session_destroy, -EINVAL,
119 			-ENOTSUP);
120 	RTE_PTR_OR_ERR_RET(sess, -EINVAL);
121 
122 	ret = instance->ops->session_destroy(instance->device, sess);
123 	if (ret != 0)
124 		return ret;
125 
126 	rte_mempool_put(rte_mempool_from_obj(sess), (void *)sess);
127 
128 	if (instance->sess_cnt)
129 		instance->sess_cnt--;
130 
131 	return 0;
132 }
133 
134 int
135 rte_security_macsec_sc_create(struct rte_security_ctx *instance,
136 			      struct rte_security_macsec_sc *conf)
137 {
138 	int sc_id;
139 
140 	RTE_PTR_CHAIN3_OR_ERR_RET(instance, ops, macsec_sc_create, -EINVAL, -ENOTSUP);
141 	RTE_PTR_OR_ERR_RET(conf, -EINVAL);
142 
143 	sc_id = instance->ops->macsec_sc_create(instance->device, conf);
144 	if (sc_id >= 0)
145 		instance->macsec_sc_cnt++;
146 
147 	return sc_id;
148 }
149 
150 int
151 rte_security_macsec_sa_create(struct rte_security_ctx *instance,
152 			      struct rte_security_macsec_sa *conf)
153 {
154 	int sa_id;
155 
156 	RTE_PTR_CHAIN3_OR_ERR_RET(instance, ops, macsec_sa_create, -EINVAL, -ENOTSUP);
157 	RTE_PTR_OR_ERR_RET(conf, -EINVAL);
158 
159 	sa_id = instance->ops->macsec_sa_create(instance->device, conf);
160 	if (sa_id >= 0)
161 		instance->macsec_sa_cnt++;
162 
163 	return sa_id;
164 }
165 
166 int
167 rte_security_macsec_sc_destroy(struct rte_security_ctx *instance, uint16_t sc_id)
168 {
169 	int ret;
170 
171 	RTE_PTR_CHAIN3_OR_ERR_RET(instance, ops, macsec_sc_destroy, -EINVAL, -ENOTSUP);
172 
173 	ret = instance->ops->macsec_sc_destroy(instance->device, sc_id);
174 	if (ret != 0)
175 		return ret;
176 
177 	if (instance->macsec_sc_cnt)
178 		instance->macsec_sc_cnt--;
179 
180 	return 0;
181 }
182 
183 int
184 rte_security_macsec_sa_destroy(struct rte_security_ctx *instance, uint16_t sa_id)
185 {
186 	int ret;
187 
188 	RTE_PTR_CHAIN3_OR_ERR_RET(instance, ops, macsec_sa_destroy, -EINVAL, -ENOTSUP);
189 
190 	ret = instance->ops->macsec_sa_destroy(instance->device, sa_id);
191 	if (ret != 0)
192 		return ret;
193 
194 	if (instance->macsec_sa_cnt)
195 		instance->macsec_sa_cnt--;
196 
197 	return 0;
198 }
199 
200 int
201 rte_security_macsec_sc_stats_get(struct rte_security_ctx *instance, uint16_t sc_id,
202 				 struct rte_security_macsec_sc_stats *stats)
203 {
204 	RTE_PTR_CHAIN3_OR_ERR_RET(instance, ops, macsec_sc_stats_get, -EINVAL, -ENOTSUP);
205 	RTE_PTR_OR_ERR_RET(stats, -EINVAL);
206 
207 	return instance->ops->macsec_sc_stats_get(instance->device, sc_id, stats);
208 }
209 
210 int
211 rte_security_macsec_sa_stats_get(struct rte_security_ctx *instance, uint16_t sa_id,
212 				 struct rte_security_macsec_sa_stats *stats)
213 {
214 	RTE_PTR_CHAIN3_OR_ERR_RET(instance, ops, macsec_sa_stats_get, -EINVAL, -ENOTSUP);
215 	RTE_PTR_OR_ERR_RET(stats, -EINVAL);
216 
217 	return instance->ops->macsec_sa_stats_get(instance->device, sa_id, stats);
218 }
219 
220 int
221 __rte_security_set_pkt_metadata(struct rte_security_ctx *instance,
222 				void *sess,
223 				struct rte_mbuf *m, void *params)
224 {
225 #ifdef RTE_DEBUG
226 	RTE_PTR_OR_ERR_RET(sess, -EINVAL);
227 	RTE_PTR_OR_ERR_RET(instance, -EINVAL);
228 	RTE_PTR_OR_ERR_RET(instance->ops, -EINVAL);
229 #endif
230 	if (*instance->ops->set_pkt_metadata == NULL)
231 		return -ENOTSUP;
232 	return instance->ops->set_pkt_metadata(instance->device,
233 					       sess, m, params);
234 }
235 
236 const struct rte_security_capability *
237 rte_security_capabilities_get(struct rte_security_ctx *instance)
238 {
239 	RTE_PTR_CHAIN3_OR_ERR_RET(instance, ops, capabilities_get, NULL, NULL);
240 
241 	return instance->ops->capabilities_get(instance->device);
242 }
243 
244 const struct rte_security_capability *
245 rte_security_capability_get(struct rte_security_ctx *instance,
246 			    struct rte_security_capability_idx *idx)
247 {
248 	const struct rte_security_capability *capabilities;
249 	const struct rte_security_capability *capability;
250 	uint16_t i = 0;
251 
252 	RTE_PTR_CHAIN3_OR_ERR_RET(instance, ops, capabilities_get, NULL, NULL);
253 	RTE_PTR_OR_ERR_RET(idx, NULL);
254 
255 	capabilities = instance->ops->capabilities_get(instance->device);
256 
257 	if (capabilities == NULL)
258 		return NULL;
259 
260 	while ((capability = &capabilities[i++])->action
261 			!= RTE_SECURITY_ACTION_TYPE_NONE) {
262 		if (capability->action == idx->action &&
263 				capability->protocol == idx->protocol) {
264 			if (idx->protocol == RTE_SECURITY_PROTOCOL_IPSEC) {
265 				if (capability->ipsec.proto ==
266 						idx->ipsec.proto &&
267 					capability->ipsec.mode ==
268 							idx->ipsec.mode &&
269 					capability->ipsec.direction ==
270 							idx->ipsec.direction)
271 					return capability;
272 			} else if (idx->protocol == RTE_SECURITY_PROTOCOL_PDCP) {
273 				if (capability->pdcp.domain ==
274 							idx->pdcp.domain)
275 					return capability;
276 			} else if (idx->protocol ==
277 						RTE_SECURITY_PROTOCOL_DOCSIS) {
278 				if (capability->docsis.direction ==
279 							idx->docsis.direction)
280 					return capability;
281 			}
282 		}
283 	}
284 
285 	return NULL;
286 }
287 
288 static int
289 security_handle_cryptodev_list(const char *cmd __rte_unused,
290 			       const char *params __rte_unused,
291 			       struct rte_tel_data *d)
292 {
293 	int dev_id;
294 
295 	if (rte_cryptodev_count() < 1)
296 		return -1;
297 
298 	rte_tel_data_start_array(d, RTE_TEL_INT_VAL);
299 	for (dev_id = 0; dev_id < RTE_CRYPTO_MAX_DEVS; dev_id++)
300 		if (rte_cryptodev_is_valid_dev(dev_id) &&
301 		    rte_cryptodev_get_sec_ctx(dev_id))
302 			rte_tel_data_add_array_int(d, dev_id);
303 
304 	return 0;
305 }
306 
307 #define CRYPTO_CAPS_SZ                                             \
308 	(RTE_ALIGN_CEIL(sizeof(struct rte_cryptodev_capabilities), \
309 			sizeof(uint64_t)) /	sizeof(uint64_t))
310 
311 static int
312 crypto_caps_array(struct rte_tel_data *d,
313 		  const struct rte_cryptodev_capabilities *capabilities)
314 {
315 	const struct rte_cryptodev_capabilities *dev_caps;
316 	uint64_t caps_val[CRYPTO_CAPS_SZ];
317 	unsigned int i = 0, j;
318 
319 	rte_tel_data_start_array(d, RTE_TEL_UINT_VAL);
320 
321 	while ((dev_caps = &capabilities[i++])->op !=
322 	   RTE_CRYPTO_OP_TYPE_UNDEFINED) {
323 		memset(&caps_val, 0, CRYPTO_CAPS_SZ * sizeof(caps_val[0]));
324 		rte_memcpy(caps_val, dev_caps, sizeof(capabilities[0]));
325 		for (j = 0; j < CRYPTO_CAPS_SZ; j++)
326 			rte_tel_data_add_array_uint(d, caps_val[j]);
327 	}
328 
329 	return (i - 1);
330 }
331 
332 #define SEC_CAPS_SZ						\
333 	(RTE_ALIGN_CEIL(sizeof(struct rte_security_capability), \
334 			sizeof(uint64_t)) /	sizeof(uint64_t))
335 
336 static int
337 sec_caps_array(struct rte_tel_data *d,
338 	       const struct rte_security_capability *capabilities)
339 {
340 	const struct rte_security_capability *dev_caps;
341 	uint64_t caps_val[SEC_CAPS_SZ];
342 	unsigned int i = 0, j;
343 
344 	rte_tel_data_start_array(d, RTE_TEL_UINT_VAL);
345 
346 	while ((dev_caps = &capabilities[i++])->action !=
347 	   RTE_SECURITY_ACTION_TYPE_NONE) {
348 		memset(&caps_val, 0, SEC_CAPS_SZ * sizeof(caps_val[0]));
349 		rte_memcpy(caps_val, dev_caps, sizeof(capabilities[0]));
350 		for (j = 0; j < SEC_CAPS_SZ; j++)
351 			rte_tel_data_add_array_uint(d, caps_val[j]);
352 	}
353 
354 	return i - 1;
355 }
356 
357 static const struct rte_security_capability *
358 security_capability_by_index(const struct rte_security_capability *capabilities,
359 			     int index)
360 {
361 	const struct rte_security_capability *dev_caps = NULL;
362 	int i = 0;
363 
364 	while ((dev_caps = &capabilities[i])->action !=
365 	   RTE_SECURITY_ACTION_TYPE_NONE) {
366 		if (i == index)
367 			return dev_caps;
368 
369 		++i;
370 	}
371 
372 	return NULL;
373 }
374 
375 static int
376 security_capabilities_from_dev_id(int dev_id, const void **caps)
377 {
378 	const struct rte_security_capability *capabilities;
379 	struct rte_security_ctx *sec_ctx;
380 
381 	if (rte_cryptodev_is_valid_dev(dev_id) == 0)
382 		return -EINVAL;
383 
384 	sec_ctx = (struct rte_security_ctx *)rte_cryptodev_get_sec_ctx(dev_id);
385 	RTE_PTR_OR_ERR_RET(sec_ctx, -EINVAL);
386 
387 	capabilities = rte_security_capabilities_get(sec_ctx);
388 	RTE_PTR_OR_ERR_RET(capabilities, -EINVAL);
389 
390 	*caps = capabilities;
391 	return 0;
392 }
393 
394 static int
395 security_handle_cryptodev_sec_caps(const char *cmd __rte_unused, const char *params,
396 				   struct rte_tel_data *d)
397 {
398 	const struct rte_security_capability *capabilities;
399 	struct rte_tel_data *sec_caps;
400 	char *end_param;
401 	int sec_caps_n;
402 	int dev_id;
403 	int rc;
404 
405 	if (!params || strlen(params) == 0 || !isdigit(*params))
406 		return -EINVAL;
407 
408 	dev_id = strtoul(params, &end_param, 0);
409 	if (*end_param != '\0')
410 		CDEV_LOG_ERR("Extra parameters passed to command, ignoring");
411 
412 	rc = security_capabilities_from_dev_id(dev_id, (void *)&capabilities);
413 	if (rc < 0)
414 		return rc;
415 
416 	sec_caps = rte_tel_data_alloc();
417 	RTE_PTR_OR_ERR_RET(sec_caps, -ENOMEM);
418 
419 	rte_tel_data_start_dict(d);
420 	sec_caps_n = sec_caps_array(sec_caps, capabilities);
421 	rte_tel_data_add_dict_container(d, "sec_caps", sec_caps, 0);
422 	rte_tel_data_add_dict_int(d, "sec_caps_n", sec_caps_n);
423 
424 	return 0;
425 }
426 
427 static int
428 security_handle_cryptodev_crypto_caps(const char *cmd __rte_unused, const char *params,
429 				      struct rte_tel_data *d)
430 {
431 	const struct rte_security_capability *capabilities;
432 	struct rte_tel_data *crypto_caps;
433 	const char *capa_param;
434 	int dev_id, capa_id;
435 	int crypto_caps_n;
436 	char *end_param;
437 	int rc;
438 
439 	if (!params || strlen(params) == 0 || !isdigit(*params))
440 		return -EINVAL;
441 
442 	dev_id = strtoul(params, &end_param, 0);
443 	capa_param = strtok(end_param, ",");
444 	if (!capa_param || strlen(capa_param) == 0 || !isdigit(*capa_param))
445 		return -EINVAL;
446 
447 	capa_id = strtoul(capa_param, &end_param, 0);
448 	if (*end_param != '\0')
449 		CDEV_LOG_ERR("Extra parameters passed to command, ignoring");
450 
451 	rc = security_capabilities_from_dev_id(dev_id, (void *)&capabilities);
452 	if (rc < 0)
453 		return rc;
454 
455 	capabilities = security_capability_by_index(capabilities, capa_id);
456 	RTE_PTR_OR_ERR_RET(capabilities, -EINVAL);
457 
458 	crypto_caps = rte_tel_data_alloc();
459 	RTE_PTR_OR_ERR_RET(crypto_caps, -ENOMEM);
460 
461 	rte_tel_data_start_dict(d);
462 	crypto_caps_n = crypto_caps_array(crypto_caps, capabilities->crypto_capabilities);
463 
464 	rte_tel_data_add_dict_container(d, "crypto_caps", crypto_caps, 0);
465 	rte_tel_data_add_dict_int(d, "crypto_caps_n", crypto_caps_n);
466 
467 	return 0;
468 }
469 
470 RTE_INIT(security_init_telemetry)
471 {
472 	rte_telemetry_register_cmd("/security/cryptodev/list",
473 		security_handle_cryptodev_list,
474 		"Returns list of available crypto devices by IDs. No parameters.");
475 
476 	rte_telemetry_register_cmd("/security/cryptodev/sec_caps",
477 		security_handle_cryptodev_sec_caps,
478 		"Returns security capabilities for a cryptodev. Parameters: int dev_id");
479 
480 	rte_telemetry_register_cmd("/security/cryptodev/crypto_caps",
481 		security_handle_cryptodev_crypto_caps,
482 		"Returns crypto capabilities for a security capability. Parameters: int dev_id, sec_cap_id");
483 }
484