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 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 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 * 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 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 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 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 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 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 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 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 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 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 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 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 * 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 * 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 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 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 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 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 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 * 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 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 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 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 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