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