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