xref: /dpdk/lib/security/rte_security.c (revision a8ca598cd8e696b4135f04cdd86a93b12fd5642a)
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 			       enum rte_security_macsec_direction dir)
169 {
170 	int ret;
171 
172 	RTE_PTR_CHAIN3_OR_ERR_RET(instance, ops, macsec_sc_destroy, -EINVAL, -ENOTSUP);
173 
174 	ret = instance->ops->macsec_sc_destroy(instance->device, sc_id, dir);
175 	if (ret != 0)
176 		return ret;
177 
178 	if (instance->macsec_sc_cnt)
179 		instance->macsec_sc_cnt--;
180 
181 	return 0;
182 }
183 
184 int
185 rte_security_macsec_sa_destroy(struct rte_security_ctx *instance, uint16_t sa_id,
186 			       enum rte_security_macsec_direction dir)
187 {
188 	int ret;
189 
190 	RTE_PTR_CHAIN3_OR_ERR_RET(instance, ops, macsec_sa_destroy, -EINVAL, -ENOTSUP);
191 
192 	ret = instance->ops->macsec_sa_destroy(instance->device, sa_id, dir);
193 	if (ret != 0)
194 		return ret;
195 
196 	if (instance->macsec_sa_cnt)
197 		instance->macsec_sa_cnt--;
198 
199 	return 0;
200 }
201 
202 int
203 rte_security_macsec_sc_stats_get(struct rte_security_ctx *instance, uint16_t sc_id,
204 				 enum rte_security_macsec_direction dir,
205 				 struct rte_security_macsec_sc_stats *stats)
206 {
207 	RTE_PTR_CHAIN3_OR_ERR_RET(instance, ops, macsec_sc_stats_get, -EINVAL, -ENOTSUP);
208 	RTE_PTR_OR_ERR_RET(stats, -EINVAL);
209 
210 	return instance->ops->macsec_sc_stats_get(instance->device, sc_id, dir, stats);
211 }
212 
213 int
214 rte_security_macsec_sa_stats_get(struct rte_security_ctx *instance, uint16_t sa_id,
215 				 enum rte_security_macsec_direction dir,
216 				 struct rte_security_macsec_sa_stats *stats)
217 {
218 	RTE_PTR_CHAIN3_OR_ERR_RET(instance, ops, macsec_sa_stats_get, -EINVAL, -ENOTSUP);
219 	RTE_PTR_OR_ERR_RET(stats, -EINVAL);
220 
221 	return instance->ops->macsec_sa_stats_get(instance->device, sa_id, dir, stats);
222 }
223 
224 int
225 __rte_security_set_pkt_metadata(struct rte_security_ctx *instance,
226 				void *sess,
227 				struct rte_mbuf *m, void *params)
228 {
229 #ifdef RTE_DEBUG
230 	RTE_PTR_OR_ERR_RET(sess, -EINVAL);
231 	RTE_PTR_OR_ERR_RET(instance, -EINVAL);
232 	RTE_PTR_OR_ERR_RET(instance->ops, -EINVAL);
233 #endif
234 	if (*instance->ops->set_pkt_metadata == NULL)
235 		return -ENOTSUP;
236 	return instance->ops->set_pkt_metadata(instance->device,
237 					       sess, m, params);
238 }
239 
240 const struct rte_security_capability *
241 rte_security_capabilities_get(struct rte_security_ctx *instance)
242 {
243 	RTE_PTR_CHAIN3_OR_ERR_RET(instance, ops, capabilities_get, NULL, NULL);
244 
245 	return instance->ops->capabilities_get(instance->device);
246 }
247 
248 const struct rte_security_capability *
249 rte_security_capability_get(struct rte_security_ctx *instance,
250 			    struct rte_security_capability_idx *idx)
251 {
252 	const struct rte_security_capability *capabilities;
253 	const struct rte_security_capability *capability;
254 	uint16_t i = 0;
255 
256 	RTE_PTR_CHAIN3_OR_ERR_RET(instance, ops, capabilities_get, NULL, NULL);
257 	RTE_PTR_OR_ERR_RET(idx, NULL);
258 
259 	capabilities = instance->ops->capabilities_get(instance->device);
260 
261 	if (capabilities == NULL)
262 		return NULL;
263 
264 	while ((capability = &capabilities[i++])->action
265 			!= RTE_SECURITY_ACTION_TYPE_NONE) {
266 		if (capability->action == idx->action &&
267 				capability->protocol == idx->protocol) {
268 			if (idx->protocol == RTE_SECURITY_PROTOCOL_IPSEC) {
269 				if (capability->ipsec.proto ==
270 						idx->ipsec.proto &&
271 					capability->ipsec.mode ==
272 							idx->ipsec.mode &&
273 					capability->ipsec.direction ==
274 							idx->ipsec.direction)
275 					return capability;
276 			} else if (idx->protocol == RTE_SECURITY_PROTOCOL_PDCP) {
277 				if (capability->pdcp.domain ==
278 							idx->pdcp.domain)
279 					return capability;
280 			} else if (idx->protocol ==
281 						RTE_SECURITY_PROTOCOL_DOCSIS) {
282 				if (capability->docsis.direction ==
283 							idx->docsis.direction)
284 					return capability;
285 			}
286 		}
287 	}
288 
289 	return NULL;
290 }
291 
292 static int
293 security_handle_cryptodev_list(const char *cmd __rte_unused,
294 			       const char *params __rte_unused,
295 			       struct rte_tel_data *d)
296 {
297 	int dev_id;
298 
299 	if (rte_cryptodev_count() < 1)
300 		return -1;
301 
302 	rte_tel_data_start_array(d, RTE_TEL_INT_VAL);
303 	for (dev_id = 0; dev_id < RTE_CRYPTO_MAX_DEVS; dev_id++)
304 		if (rte_cryptodev_is_valid_dev(dev_id) &&
305 		    rte_cryptodev_get_sec_ctx(dev_id))
306 			rte_tel_data_add_array_int(d, dev_id);
307 
308 	return 0;
309 }
310 
311 #define CRYPTO_CAPS_SZ                                             \
312 	(RTE_ALIGN_CEIL(sizeof(struct rte_cryptodev_capabilities), \
313 			sizeof(uint64_t)) /	sizeof(uint64_t))
314 
315 static int
316 crypto_caps_array(struct rte_tel_data *d,
317 		  const struct rte_cryptodev_capabilities *capabilities)
318 {
319 	const struct rte_cryptodev_capabilities *dev_caps;
320 	uint64_t caps_val[CRYPTO_CAPS_SZ];
321 	unsigned int i = 0, j;
322 
323 	rte_tel_data_start_array(d, RTE_TEL_UINT_VAL);
324 
325 	while ((dev_caps = &capabilities[i++])->op !=
326 	   RTE_CRYPTO_OP_TYPE_UNDEFINED) {
327 		memset(&caps_val, 0, CRYPTO_CAPS_SZ * sizeof(caps_val[0]));
328 		rte_memcpy(caps_val, dev_caps, sizeof(capabilities[0]));
329 		for (j = 0; j < CRYPTO_CAPS_SZ; j++)
330 			rte_tel_data_add_array_uint(d, caps_val[j]);
331 	}
332 
333 	return (i - 1);
334 }
335 
336 #define SEC_CAPS_SZ						\
337 	(RTE_ALIGN_CEIL(sizeof(struct rte_security_capability), \
338 			sizeof(uint64_t)) /	sizeof(uint64_t))
339 
340 static int
341 sec_caps_array(struct rte_tel_data *d,
342 	       const struct rte_security_capability *capabilities)
343 {
344 	const struct rte_security_capability *dev_caps;
345 	uint64_t caps_val[SEC_CAPS_SZ];
346 	unsigned int i = 0, j;
347 
348 	rte_tel_data_start_array(d, RTE_TEL_UINT_VAL);
349 
350 	while ((dev_caps = &capabilities[i++])->action !=
351 	   RTE_SECURITY_ACTION_TYPE_NONE) {
352 		memset(&caps_val, 0, SEC_CAPS_SZ * sizeof(caps_val[0]));
353 		rte_memcpy(caps_val, dev_caps, sizeof(capabilities[0]));
354 		for (j = 0; j < SEC_CAPS_SZ; j++)
355 			rte_tel_data_add_array_uint(d, caps_val[j]);
356 	}
357 
358 	return i - 1;
359 }
360 
361 static const struct rte_security_capability *
362 security_capability_by_index(const struct rte_security_capability *capabilities,
363 			     int index)
364 {
365 	const struct rte_security_capability *dev_caps = NULL;
366 	int i = 0;
367 
368 	while ((dev_caps = &capabilities[i])->action !=
369 	   RTE_SECURITY_ACTION_TYPE_NONE) {
370 		if (i == index)
371 			return dev_caps;
372 
373 		++i;
374 	}
375 
376 	return NULL;
377 }
378 
379 static int
380 security_capabilities_from_dev_id(int dev_id, const void **caps)
381 {
382 	const struct rte_security_capability *capabilities;
383 	struct rte_security_ctx *sec_ctx;
384 
385 	if (rte_cryptodev_is_valid_dev(dev_id) == 0)
386 		return -EINVAL;
387 
388 	sec_ctx = (struct rte_security_ctx *)rte_cryptodev_get_sec_ctx(dev_id);
389 	RTE_PTR_OR_ERR_RET(sec_ctx, -EINVAL);
390 
391 	capabilities = rte_security_capabilities_get(sec_ctx);
392 	RTE_PTR_OR_ERR_RET(capabilities, -EINVAL);
393 
394 	*caps = capabilities;
395 	return 0;
396 }
397 
398 static int
399 security_handle_cryptodev_sec_caps(const char *cmd __rte_unused, const char *params,
400 				   struct rte_tel_data *d)
401 {
402 	const struct rte_security_capability *capabilities;
403 	struct rte_tel_data *sec_caps;
404 	char *end_param;
405 	int sec_caps_n;
406 	int dev_id;
407 	int rc;
408 
409 	if (!params || strlen(params) == 0 || !isdigit(*params))
410 		return -EINVAL;
411 
412 	dev_id = strtoul(params, &end_param, 0);
413 	if (*end_param != '\0')
414 		CDEV_LOG_ERR("Extra parameters passed to command, ignoring");
415 
416 	rc = security_capabilities_from_dev_id(dev_id, (void *)&capabilities);
417 	if (rc < 0)
418 		return rc;
419 
420 	sec_caps = rte_tel_data_alloc();
421 	RTE_PTR_OR_ERR_RET(sec_caps, -ENOMEM);
422 
423 	rte_tel_data_start_dict(d);
424 	sec_caps_n = sec_caps_array(sec_caps, capabilities);
425 	rte_tel_data_add_dict_container(d, "sec_caps", sec_caps, 0);
426 	rte_tel_data_add_dict_int(d, "sec_caps_n", sec_caps_n);
427 
428 	return 0;
429 }
430 
431 static int
432 security_handle_cryptodev_crypto_caps(const char *cmd __rte_unused, const char *params,
433 				      struct rte_tel_data *d)
434 {
435 	const struct rte_security_capability *capabilities;
436 	struct rte_tel_data *crypto_caps;
437 	const char *capa_param;
438 	int dev_id, capa_id;
439 	int crypto_caps_n;
440 	char *end_param;
441 	int rc;
442 
443 	if (!params || strlen(params) == 0 || !isdigit(*params))
444 		return -EINVAL;
445 
446 	dev_id = strtoul(params, &end_param, 0);
447 	capa_param = strtok(end_param, ",");
448 	if (!capa_param || strlen(capa_param) == 0 || !isdigit(*capa_param))
449 		return -EINVAL;
450 
451 	capa_id = strtoul(capa_param, &end_param, 0);
452 	if (*end_param != '\0')
453 		CDEV_LOG_ERR("Extra parameters passed to command, ignoring");
454 
455 	rc = security_capabilities_from_dev_id(dev_id, (void *)&capabilities);
456 	if (rc < 0)
457 		return rc;
458 
459 	capabilities = security_capability_by_index(capabilities, capa_id);
460 	RTE_PTR_OR_ERR_RET(capabilities, -EINVAL);
461 
462 	crypto_caps = rte_tel_data_alloc();
463 	RTE_PTR_OR_ERR_RET(crypto_caps, -ENOMEM);
464 
465 	rte_tel_data_start_dict(d);
466 	crypto_caps_n = crypto_caps_array(crypto_caps, capabilities->crypto_capabilities);
467 
468 	rte_tel_data_add_dict_container(d, "crypto_caps", crypto_caps, 0);
469 	rte_tel_data_add_dict_int(d, "crypto_caps_n", crypto_caps_n);
470 
471 	return 0;
472 }
473 
474 RTE_INIT(security_init_telemetry)
475 {
476 	rte_telemetry_register_cmd("/security/cryptodev/list",
477 		security_handle_cryptodev_list,
478 		"Returns list of available crypto devices by IDs. No parameters.");
479 
480 	rte_telemetry_register_cmd("/security/cryptodev/sec_caps",
481 		security_handle_cryptodev_sec_caps,
482 		"Returns security capabilities for a cryptodev. Parameters: int dev_id");
483 
484 	rte_telemetry_register_cmd("/security/cryptodev/crypto_caps",
485 		security_handle_cryptodev_crypto_caps,
486 		"Returns crypto capabilities for a security capability. Parameters: int dev_id, sec_cap_id");
487 }
488