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 <rte_cryptodev.h> 8 #include <rte_dev.h> 9 #include <rte_telemetry.h> 10 #include "rte_security.h" 11 #include "rte_security_driver.h" 12 13 /* Macro to check for invalid pointers */ 14 #define RTE_PTR_OR_ERR_RET(ptr, retval) do { \ 15 if ((ptr) == NULL) \ 16 return retval; \ 17 } while (0) 18 19 /* Macro to check for invalid pointers chains */ 20 #define RTE_PTR_CHAIN3_OR_ERR_RET(p1, p2, p3, retval, last_retval) do { \ 21 RTE_PTR_OR_ERR_RET(p1, retval); \ 22 RTE_PTR_OR_ERR_RET(p1->p2, retval); \ 23 RTE_PTR_OR_ERR_RET(p1->p2->p3, last_retval); \ 24 } while (0) 25 26 #define RTE_SECURITY_DYNFIELD_NAME "rte_security_dynfield_metadata" 27 int rte_security_dynfield_offset = -1; 28 29 int 30 rte_security_dynfield_register(void) 31 { 32 static const struct rte_mbuf_dynfield dynfield_desc = { 33 .name = RTE_SECURITY_DYNFIELD_NAME, 34 .size = sizeof(rte_security_dynfield_t), 35 .align = __alignof__(rte_security_dynfield_t), 36 }; 37 rte_security_dynfield_offset = 38 rte_mbuf_dynfield_register(&dynfield_desc); 39 return rte_security_dynfield_offset; 40 } 41 42 struct rte_security_session * 43 rte_security_session_create(struct rte_security_ctx *instance, 44 struct rte_security_session_conf *conf, 45 struct rte_mempool *mp, 46 struct rte_mempool *priv_mp) 47 { 48 struct rte_security_session *sess = NULL; 49 50 RTE_PTR_CHAIN3_OR_ERR_RET(instance, ops, session_create, NULL, NULL); 51 RTE_PTR_OR_ERR_RET(conf, NULL); 52 RTE_PTR_OR_ERR_RET(mp, NULL); 53 RTE_PTR_OR_ERR_RET(priv_mp, NULL); 54 55 if (rte_mempool_get(mp, (void **)&sess)) 56 return NULL; 57 58 if (instance->ops->session_create(instance->device, conf, 59 sess, priv_mp)) { 60 rte_mempool_put(mp, (void *)sess); 61 return NULL; 62 } 63 instance->sess_cnt++; 64 65 return sess; 66 } 67 68 int 69 rte_security_session_update(struct rte_security_ctx *instance, 70 struct rte_security_session *sess, 71 struct rte_security_session_conf *conf) 72 { 73 RTE_PTR_CHAIN3_OR_ERR_RET(instance, ops, session_update, -EINVAL, 74 -ENOTSUP); 75 RTE_PTR_OR_ERR_RET(sess, -EINVAL); 76 RTE_PTR_OR_ERR_RET(conf, -EINVAL); 77 78 return instance->ops->session_update(instance->device, sess, conf); 79 } 80 81 unsigned int 82 rte_security_session_get_size(struct rte_security_ctx *instance) 83 { 84 RTE_PTR_CHAIN3_OR_ERR_RET(instance, ops, session_get_size, 0, 0); 85 86 return instance->ops->session_get_size(instance->device); 87 } 88 89 int 90 rte_security_session_stats_get(struct rte_security_ctx *instance, 91 struct rte_security_session *sess, 92 struct rte_security_stats *stats) 93 { 94 RTE_PTR_CHAIN3_OR_ERR_RET(instance, ops, session_stats_get, -EINVAL, 95 -ENOTSUP); 96 /* Parameter sess can be NULL in case of getting global statistics. */ 97 RTE_PTR_OR_ERR_RET(stats, -EINVAL); 98 99 return instance->ops->session_stats_get(instance->device, sess, stats); 100 } 101 102 int 103 rte_security_session_destroy(struct rte_security_ctx *instance, 104 struct rte_security_session *sess) 105 { 106 int ret; 107 108 RTE_PTR_CHAIN3_OR_ERR_RET(instance, ops, session_destroy, -EINVAL, 109 -ENOTSUP); 110 RTE_PTR_OR_ERR_RET(sess, -EINVAL); 111 112 ret = instance->ops->session_destroy(instance->device, sess); 113 if (ret != 0) 114 return ret; 115 116 rte_mempool_put(rte_mempool_from_obj(sess), (void *)sess); 117 118 if (instance->sess_cnt) 119 instance->sess_cnt--; 120 121 return 0; 122 } 123 124 int 125 __rte_security_set_pkt_metadata(struct rte_security_ctx *instance, 126 struct rte_security_session *sess, 127 struct rte_mbuf *m, void *params) 128 { 129 #ifdef RTE_DEBUG 130 RTE_PTR_OR_ERR_RET(sess, -EINVAL); 131 RTE_PTR_OR_ERR_RET(instance, -EINVAL); 132 RTE_PTR_OR_ERR_RET(instance->ops, -EINVAL); 133 #endif 134 RTE_FUNC_PTR_OR_ERR_RET(*instance->ops->set_pkt_metadata, -ENOTSUP); 135 return instance->ops->set_pkt_metadata(instance->device, 136 sess, m, params); 137 } 138 139 void * 140 __rte_security_get_userdata(struct rte_security_ctx *instance, uint64_t md) 141 { 142 void *userdata = NULL; 143 144 #ifdef RTE_DEBUG 145 RTE_PTR_OR_ERR_RET(instance, NULL); 146 RTE_PTR_OR_ERR_RET(instance->ops, NULL); 147 #endif 148 RTE_FUNC_PTR_OR_ERR_RET(*instance->ops->get_userdata, NULL); 149 if (instance->ops->get_userdata(instance->device, md, &userdata)) 150 return NULL; 151 152 return userdata; 153 } 154 155 const struct rte_security_capability * 156 rte_security_capabilities_get(struct rte_security_ctx *instance) 157 { 158 RTE_PTR_CHAIN3_OR_ERR_RET(instance, ops, capabilities_get, NULL, NULL); 159 160 return instance->ops->capabilities_get(instance->device); 161 } 162 163 const struct rte_security_capability * 164 rte_security_capability_get(struct rte_security_ctx *instance, 165 struct rte_security_capability_idx *idx) 166 { 167 const struct rte_security_capability *capabilities; 168 const struct rte_security_capability *capability; 169 uint16_t i = 0; 170 171 RTE_PTR_CHAIN3_OR_ERR_RET(instance, ops, capabilities_get, NULL, NULL); 172 RTE_PTR_OR_ERR_RET(idx, NULL); 173 174 capabilities = instance->ops->capabilities_get(instance->device); 175 176 if (capabilities == NULL) 177 return NULL; 178 179 while ((capability = &capabilities[i++])->action 180 != RTE_SECURITY_ACTION_TYPE_NONE) { 181 if (capability->action == idx->action && 182 capability->protocol == idx->protocol) { 183 if (idx->protocol == RTE_SECURITY_PROTOCOL_IPSEC) { 184 if (capability->ipsec.proto == 185 idx->ipsec.proto && 186 capability->ipsec.mode == 187 idx->ipsec.mode && 188 capability->ipsec.direction == 189 idx->ipsec.direction) 190 return capability; 191 } else if (idx->protocol == RTE_SECURITY_PROTOCOL_PDCP) { 192 if (capability->pdcp.domain == 193 idx->pdcp.domain) 194 return capability; 195 } else if (idx->protocol == 196 RTE_SECURITY_PROTOCOL_DOCSIS) { 197 if (capability->docsis.direction == 198 idx->docsis.direction) 199 return capability; 200 } 201 } 202 } 203 204 return NULL; 205 } 206 207 static int 208 security_handle_cryptodev_list(const char *cmd __rte_unused, 209 const char *params __rte_unused, 210 struct rte_tel_data *d) 211 { 212 int dev_id; 213 214 if (rte_cryptodev_count() < 1) 215 return -1; 216 217 rte_tel_data_start_array(d, RTE_TEL_INT_VAL); 218 for (dev_id = 0; dev_id < RTE_CRYPTO_MAX_DEVS; dev_id++) 219 if (rte_cryptodev_is_valid_dev(dev_id) && 220 rte_cryptodev_get_sec_ctx(dev_id)) 221 rte_tel_data_add_array_int(d, dev_id); 222 223 return 0; 224 } 225 226 #define CRYPTO_CAPS_SZ \ 227 (RTE_ALIGN_CEIL(sizeof(struct rte_cryptodev_capabilities), \ 228 sizeof(uint64_t)) / sizeof(uint64_t)) 229 230 static int 231 crypto_caps_array(struct rte_tel_data *d, 232 const struct rte_cryptodev_capabilities *capabilities) 233 { 234 const struct rte_cryptodev_capabilities *dev_caps; 235 uint64_t caps_val[CRYPTO_CAPS_SZ]; 236 unsigned int i = 0, j; 237 238 rte_tel_data_start_array(d, RTE_TEL_U64_VAL); 239 240 while ((dev_caps = &capabilities[i++])->op != 241 RTE_CRYPTO_OP_TYPE_UNDEFINED) { 242 memset(&caps_val, 0, CRYPTO_CAPS_SZ * sizeof(caps_val[0])); 243 rte_memcpy(caps_val, dev_caps, sizeof(capabilities[0])); 244 for (j = 0; j < CRYPTO_CAPS_SZ; j++) 245 rte_tel_data_add_array_u64(d, caps_val[j]); 246 } 247 248 return (i - 1); 249 } 250 251 #define SEC_CAPS_SZ \ 252 (RTE_ALIGN_CEIL(sizeof(struct rte_security_capability), \ 253 sizeof(uint64_t)) / sizeof(uint64_t)) 254 255 static int 256 sec_caps_array(struct rte_tel_data *d, 257 const struct rte_security_capability *capabilities) 258 { 259 const struct rte_security_capability *dev_caps; 260 uint64_t caps_val[SEC_CAPS_SZ]; 261 unsigned int i = 0, j; 262 263 rte_tel_data_start_array(d, RTE_TEL_U64_VAL); 264 265 while ((dev_caps = &capabilities[i++])->action != 266 RTE_SECURITY_ACTION_TYPE_NONE) { 267 memset(&caps_val, 0, SEC_CAPS_SZ * sizeof(caps_val[0])); 268 rte_memcpy(caps_val, dev_caps, sizeof(capabilities[0])); 269 for (j = 0; j < SEC_CAPS_SZ; j++) 270 rte_tel_data_add_array_u64(d, caps_val[j]); 271 } 272 273 return i - 1; 274 } 275 276 static const struct rte_security_capability * 277 security_capability_by_index(const struct rte_security_capability *capabilities, 278 int index) 279 { 280 const struct rte_security_capability *dev_caps = NULL; 281 int i = 0; 282 283 while ((dev_caps = &capabilities[i])->action != 284 RTE_SECURITY_ACTION_TYPE_NONE) { 285 if (i == index) 286 return dev_caps; 287 288 ++i; 289 } 290 291 return NULL; 292 } 293 294 static int 295 security_capabilities_from_dev_id(int dev_id, const void **caps) 296 { 297 const struct rte_security_capability *capabilities; 298 struct rte_security_ctx *sec_ctx; 299 300 if (rte_cryptodev_is_valid_dev(dev_id) == 0) 301 return -EINVAL; 302 303 sec_ctx = (struct rte_security_ctx *)rte_cryptodev_get_sec_ctx(dev_id); 304 RTE_PTR_OR_ERR_RET(sec_ctx, -EINVAL); 305 306 capabilities = rte_security_capabilities_get(sec_ctx); 307 RTE_PTR_OR_ERR_RET(capabilities, -EINVAL); 308 309 *caps = capabilities; 310 return 0; 311 } 312 313 static int 314 security_handle_cryptodev_sec_caps(const char *cmd __rte_unused, const char *params, 315 struct rte_tel_data *d) 316 { 317 const struct rte_security_capability *capabilities; 318 struct rte_tel_data *sec_caps; 319 char *end_param; 320 int sec_caps_n; 321 int dev_id; 322 int rc; 323 324 if (!params || strlen(params) == 0 || !isdigit(*params)) 325 return -EINVAL; 326 327 dev_id = strtoul(params, &end_param, 0); 328 if (*end_param != '\0') 329 CDEV_LOG_ERR("Extra parameters passed to command, ignoring"); 330 331 rc = security_capabilities_from_dev_id(dev_id, (void *)&capabilities); 332 if (rc < 0) 333 return rc; 334 335 sec_caps = rte_tel_data_alloc(); 336 RTE_PTR_OR_ERR_RET(sec_caps, -ENOMEM); 337 338 rte_tel_data_start_dict(d); 339 sec_caps_n = sec_caps_array(sec_caps, capabilities); 340 rte_tel_data_add_dict_container(d, "sec_caps", sec_caps, 0); 341 rte_tel_data_add_dict_int(d, "sec_caps_n", sec_caps_n); 342 343 return 0; 344 } 345 346 static int 347 security_handle_cryptodev_crypto_caps(const char *cmd __rte_unused, const char *params, 348 struct rte_tel_data *d) 349 { 350 const struct rte_security_capability *capabilities; 351 struct rte_tel_data *crypto_caps; 352 const char *capa_param; 353 int dev_id, capa_id; 354 int crypto_caps_n; 355 char *end_param; 356 int rc; 357 358 if (!params || strlen(params) == 0 || !isdigit(*params)) 359 return -EINVAL; 360 361 dev_id = strtoul(params, &end_param, 0); 362 capa_param = strtok(end_param, ","); 363 if (!capa_param || strlen(capa_param) == 0 || !isdigit(*capa_param)) 364 return -EINVAL; 365 366 capa_id = strtoul(capa_param, &end_param, 0); 367 if (*end_param != '\0') 368 CDEV_LOG_ERR("Extra parameters passed to command, ignoring"); 369 370 rc = security_capabilities_from_dev_id(dev_id, (void *)&capabilities); 371 if (rc < 0) 372 return rc; 373 374 capabilities = security_capability_by_index(capabilities, capa_id); 375 RTE_PTR_OR_ERR_RET(capabilities, -EINVAL); 376 377 crypto_caps = rte_tel_data_alloc(); 378 RTE_PTR_OR_ERR_RET(crypto_caps, -ENOMEM); 379 380 rte_tel_data_start_dict(d); 381 crypto_caps_n = crypto_caps_array(crypto_caps, capabilities->crypto_capabilities); 382 383 rte_tel_data_add_dict_container(d, "crypto_caps", crypto_caps, 0); 384 rte_tel_data_add_dict_int(d, "crypto_caps_n", crypto_caps_n); 385 386 return 0; 387 } 388 389 RTE_INIT(security_init_telemetry) 390 { 391 rte_telemetry_register_cmd("/security/cryptodev/list", 392 security_handle_cryptodev_list, 393 "Returns list of available crypto devices by IDs. No parameters."); 394 395 rte_telemetry_register_cmd("/security/cryptodev/sec_caps", 396 security_handle_cryptodev_sec_caps, 397 "Returns security capabilities for a cryptodev. Parameters: int dev_id"); 398 399 rte_telemetry_register_cmd("/security/cryptodev/crypto_caps", 400 security_handle_cryptodev_crypto_caps, 401 "Returns crypto capabilities for a security capability. Parameters: int dev_id, sec_cap_id"); 402 } 403