1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright (c) 2022-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 3 */ 4 5 #include <rdma/rdma_cma.h> 6 #include <infiniband/verbs.h> 7 #include <infiniband/mlx5dv.h> 8 9 #include "spdk/stdinc.h" 10 #include "spdk/queue.h" 11 #include "spdk/log.h" 12 #include "spdk/likely.h" 13 #include "spdk/util.h" 14 #include "spdk_internal/mlx5.h" 15 #include "spdk_internal/rdma_utils.h" 16 #include "mlx5_ifc.h" 17 #include "mlx5_priv.h" 18 19 /* Plaintext key sizes */ 20 /* 64b keytag */ 21 #define SPDK_MLX5_AES_XTS_KEYTAG_SIZE 8 22 /* key1_128b + key2_128b */ 23 #define SPDK_MLX5_AES_XTS_128_DEK_BYTES 32 24 /* key1_256b + key2_256b */ 25 #define SPDK_MLX5_AES_XTS_256_DEK_BYTES 64 26 /* key1_128b + key2_128b + 64b_keytag */ 27 #define SPDK_MLX5_AES_XTS_128_DEK_BYTES_WITH_KEYTAG (SPDK_MLX5_AES_XTS_128_DEK_BYTES + SPDK_MLX5_AES_XTS_KEYTAG_SIZE) 28 /* key1_256b + key2_256b + 64b_keytag */ 29 #define SPDK_MLX5_AES_XTS_256_DEK_BYTES_WITH_KEYTAG (SPDK_MLX5_AES_XTS_256_DEK_BYTES + SPDK_MLX5_AES_XTS_KEYTAG_SIZE) 30 31 struct mlx5_crypto_dek_init_attr { 32 char *dek; 33 uint64_t opaque; 34 uint32_t key_size_bytes; 35 uint8_t key_size; /* driver representation of \b key_size_bytes */ 36 uint8_t keytag; 37 }; 38 39 struct mlx5_crypto_dek_query_attr { 40 /* state either MLX5_ENCRYPTION_KEY_OBJ_STATE_READY or MLX5_ENCRYPTION_KEY_OBJ_STATE_ERROR */ 41 uint8_t state; 42 uint64_t opaque; 43 }; 44 45 struct spdk_mlx5_crypto_dek_legacy { 46 struct mlx5dv_dek *dek_obj; 47 struct ibv_pd *pd; 48 struct ibv_context *context; 49 }; 50 51 struct mlx5_crypto_dek { 52 struct mlx5dv_devx_obj *devx_obj; 53 struct ibv_pd *pd; 54 struct ibv_context *context; 55 /* Cached dek_obj_id */ 56 uint32_t dek_obj_id; 57 enum spdk_mlx5_crypto_key_tweak_mode tweak_mode; 58 }; 59 60 struct spdk_mlx5_crypto_keytag { 61 struct mlx5_crypto_dek *deks; 62 struct spdk_mlx5_crypto_dek_legacy *deks_legacy; 63 uint32_t deks_num; 64 bool has_keytag; 65 char keytag[8]; 66 }; 67 68 static char **g_allowed_devices; 69 static size_t g_allowed_devices_count; 70 71 static void 72 mlx5_crypto_devs_free(void) 73 { 74 size_t i; 75 76 if (!g_allowed_devices) { 77 return; 78 } 79 80 for (i = 0; i < g_allowed_devices_count; i++) { 81 free(g_allowed_devices[i]); 82 } 83 free(g_allowed_devices); 84 g_allowed_devices = NULL; 85 g_allowed_devices_count = 0; 86 } 87 88 static bool 89 mlx5_crypto_dev_allowed(const char *dev) 90 { 91 size_t i; 92 93 if (!g_allowed_devices || !g_allowed_devices_count) { 94 return true; 95 } 96 97 for (i = 0; i < g_allowed_devices_count; i++) { 98 if (strcmp(g_allowed_devices[i], dev) == 0) { 99 return true; 100 } 101 } 102 103 return false; 104 } 105 106 int 107 spdk_mlx5_crypto_devs_allow(const char *const dev_names[], size_t devs_count) 108 { 109 size_t i; 110 111 mlx5_crypto_devs_free(); 112 113 if (!dev_names || !devs_count) { 114 return 0; 115 } 116 117 g_allowed_devices = calloc(devs_count, sizeof(char *)); 118 if (!g_allowed_devices) { 119 return -ENOMEM; 120 } 121 for (i = 0; i < devs_count; i++) { 122 g_allowed_devices[i] = strndup(dev_names[i], SPDK_MLX5_DEV_MAX_NAME_LEN); 123 if (!g_allowed_devices[i]) { 124 mlx5_crypto_devs_free(); 125 return -ENOMEM; 126 } 127 g_allowed_devices_count++; 128 } 129 130 return 0; 131 } 132 133 struct ibv_context ** 134 spdk_mlx5_crypto_devs_get(int *dev_num) 135 { 136 struct ibv_context **rdma_devs, **rdma_devs_out = NULL, *dev; 137 struct ibv_device_attr dev_attr; 138 struct ibv_port_attr port_attr; 139 struct spdk_mlx5_device_caps dev_caps; 140 uint8_t in[DEVX_ST_SZ_BYTES(query_nic_vport_context_in)]; 141 uint8_t out[DEVX_ST_SZ_BYTES(query_nic_vport_context_out)]; 142 uint8_t devx_v; 143 int num_rdma_devs = 0, i, rc; 144 int num_crypto_devs = 0; 145 146 /* query all devices, save mlx5 with crypto support */ 147 rdma_devs = rdma_get_devices(&num_rdma_devs); 148 if (!rdma_devs || !num_rdma_devs) { 149 *dev_num = 0; 150 return NULL; 151 } 152 153 rdma_devs_out = calloc(num_rdma_devs + 1, sizeof(*rdma_devs_out)); 154 if (!rdma_devs_out) { 155 SPDK_ERRLOG("Memory allocation failed\n"); 156 return NULL; 157 } 158 159 for (i = 0; i < num_rdma_devs; i++) { 160 dev = rdma_devs[i]; 161 rc = ibv_query_device(dev, &dev_attr); 162 if (rc) { 163 SPDK_ERRLOG("Failed to query dev %s, skipping\n", dev->device->name); 164 continue; 165 } 166 if (dev_attr.vendor_id != SPDK_MLX5_VENDOR_ID_MELLANOX) { 167 SPDK_DEBUGLOG(mlx5, "dev %s is not Mellanox device, skipping\n", dev->device->name); 168 continue; 169 } 170 171 if (!mlx5_crypto_dev_allowed(dev->device->name)) { 172 continue; 173 } 174 175 rc = ibv_query_port(dev, 1, &port_attr); 176 if (rc) { 177 SPDK_ERRLOG("Failed to query port attributes for device %s, rc %d\n", dev->device->name, rc); 178 continue; 179 } 180 181 if (port_attr.link_layer == IBV_LINK_LAYER_ETHERNET) { 182 /* Port may be ethernet but roce is still disabled */ 183 memset(in, 0, sizeof(in)); 184 memset(out, 0, sizeof(out)); 185 DEVX_SET(query_nic_vport_context_in, in, opcode, MLX5_CMD_OP_QUERY_NIC_VPORT_CONTEXT); 186 rc = mlx5dv_devx_general_cmd(dev, in, sizeof(in), out, sizeof(out)); 187 if (rc) { 188 SPDK_ERRLOG("Failed to get VPORT context for device %s. Assuming ROCE is disabled\n", 189 dev->device->name); 190 continue; 191 } 192 193 devx_v = DEVX_GET(query_nic_vport_context_out, out, nic_vport_context.roce_en); 194 if (!devx_v) { 195 SPDK_ERRLOG("Device %s, RoCE disabled\n", dev->device->name); 196 continue; 197 } 198 } 199 200 memset(&dev_caps, 0, sizeof(dev_caps)); 201 rc = spdk_mlx5_device_query_caps(dev, &dev_caps); 202 if (rc) { 203 SPDK_ERRLOG("Failed to query mlx5 dev %s, skipping\n", dev->device->name); 204 continue; 205 } 206 if (!dev_caps.crypto_supported) { 207 SPDK_WARNLOG("dev %s crypto engine doesn't support crypto\n", dev->device->name); 208 continue; 209 } 210 if (!(dev_caps.crypto.single_block_le_tweak || dev_caps.crypto.multi_block_le_tweak || 211 dev_caps.crypto.multi_block_be_tweak)) { 212 SPDK_WARNLOG("dev %s crypto engine doesn't support AES_XTS\n", dev->device->name); 213 continue; 214 } 215 if (dev_caps.crypto.wrapped_import_method_aes_xts) { 216 SPDK_WARNLOG("dev %s uses wrapped import method which is not supported by mlx5 lib\n", 217 dev->device->name); 218 continue; 219 } 220 221 rdma_devs_out[num_crypto_devs++] = dev; 222 } 223 224 if (!num_crypto_devs) { 225 SPDK_DEBUGLOG(mlx5, "Found no mlx5 crypto devices\n"); 226 goto err_out; 227 } 228 229 rdma_free_devices(rdma_devs); 230 *dev_num = num_crypto_devs; 231 232 return rdma_devs_out; 233 234 err_out: 235 free(rdma_devs_out); 236 rdma_free_devices(rdma_devs); 237 *dev_num = 0; 238 return NULL; 239 } 240 241 void 242 spdk_mlx5_crypto_devs_release(struct ibv_context **rdma_devs) 243 { 244 if (rdma_devs) { 245 free(rdma_devs); 246 } 247 } 248 249 int 250 spdk_mlx5_device_query_caps(struct ibv_context *context, struct spdk_mlx5_device_caps *caps) 251 { 252 uint16_t opmod = MLX5_SET_HCA_CAP_OP_MOD_GENERAL_DEVICE | 253 HCA_CAP_OPMOD_GET_CUR; 254 uint32_t out[DEVX_ST_SZ_DW(query_hca_cap_out)] = {}; 255 uint32_t in[DEVX_ST_SZ_DW(query_hca_cap_in)] = {}; 256 int rc; 257 258 DEVX_SET(query_hca_cap_in, in, opcode, MLX5_CMD_OP_QUERY_HCA_CAP); 259 DEVX_SET(query_hca_cap_in, in, op_mod, opmod); 260 261 rc = mlx5dv_devx_general_cmd(context, in, sizeof(in), out, sizeof(out)); 262 if (rc) { 263 return rc; 264 } 265 266 caps->crypto_supported = DEVX_GET(query_hca_cap_out, out, capability.cmd_hca_cap.crypto); 267 if (!caps->crypto_supported) { 268 return 0; 269 } 270 271 caps->crypto.single_block_le_tweak = DEVX_GET(query_hca_cap_out, 272 out, capability.cmd_hca_cap.aes_xts_single_block_le_tweak); 273 caps->crypto.multi_block_be_tweak = DEVX_GET(query_hca_cap_out, out, 274 capability.cmd_hca_cap.aes_xts_multi_block_be_tweak); 275 caps->crypto.multi_block_le_tweak = DEVX_GET(query_hca_cap_out, out, 276 capability.cmd_hca_cap.aes_xts_multi_block_le_tweak); 277 278 opmod = MLX5_SET_HCA_CAP_OP_MOD_CRYPTO | HCA_CAP_OPMOD_GET_CUR; 279 memset(&out, 0, sizeof(out)); 280 memset(&in, 0, sizeof(in)); 281 282 DEVX_SET(query_hca_cap_in, in, opcode, MLX5_CMD_OP_QUERY_HCA_CAP); 283 DEVX_SET(query_hca_cap_in, in, op_mod, opmod); 284 285 rc = mlx5dv_devx_general_cmd(context, in, sizeof(in), out, sizeof(out)); 286 if (rc) { 287 return rc; 288 } 289 290 caps->crypto.wrapped_crypto_operational = DEVX_GET(query_hca_cap_out, out, 291 capability.crypto_caps.wrapped_crypto_operational); 292 caps->crypto.wrapped_crypto_going_to_commissioning = DEVX_GET(query_hca_cap_out, out, 293 capability.crypto_caps .wrapped_crypto_going_to_commissioning); 294 caps->crypto.wrapped_import_method_aes_xts = (DEVX_GET(query_hca_cap_out, out, 295 capability.crypto_caps.wrapped_import_method) & 296 MLX5_CRYPTO_CAPS_WRAPPED_IMPORT_METHOD_AES) != 0; 297 298 return 0; 299 } 300 301 static void 302 mlx5_crypto_dek_deinit(struct mlx5_crypto_dek *dek) 303 { 304 int rc; 305 306 rc = mlx5dv_devx_obj_destroy(dek->devx_obj); 307 if (rc) { 308 SPDK_ERRLOG("Failed to destroy crypto obj:%p, rc %d\n", dek->devx_obj, rc); 309 } 310 } 311 312 void 313 spdk_mlx5_crypto_keytag_destroy(struct spdk_mlx5_crypto_keytag *keytag) 314 { 315 struct mlx5_crypto_dek *dek; 316 uint32_t i; 317 318 if (!keytag) { 319 return; 320 } 321 322 for (i = 0; i < keytag->deks_num; i++) { 323 dek = &keytag->deks[i]; 324 if (dek->devx_obj) { 325 mlx5_crypto_dek_deinit(dek); 326 } 327 if (dek->pd) { 328 spdk_rdma_utils_put_pd(dek->pd); 329 } 330 331 if (keytag->deks_legacy[i].dek_obj) { 332 mlx5dv_dek_destroy(keytag->deks_legacy[i].dek_obj); 333 } 334 335 } 336 spdk_memset_s(keytag->keytag, sizeof(keytag->keytag), 0, sizeof(keytag->keytag)); 337 free(keytag->deks_legacy); 338 free(keytag->deks); 339 free(keytag); 340 } 341 342 static int 343 mlx5_crypto_dek_init(struct ibv_pd *pd, struct mlx5_crypto_dek_init_attr *attr, 344 struct mlx5_crypto_dek *dek) 345 { 346 uint32_t in[DEVX_ST_SZ_DW(create_encryption_key_obj_in)] = {}; 347 uint32_t out[DEVX_ST_SZ_DW(general_obj_out_cmd_hdr)] = {}; 348 uint8_t *dek_in; 349 uint32_t pdn; 350 int rc; 351 352 rc = mlx5_get_pd_id(pd, &pdn); 353 if (rc) { 354 return rc; 355 } 356 357 dek_in = DEVX_ADDR_OF(create_encryption_key_obj_in, in, hdr); 358 DEVX_SET(general_obj_in_cmd_hdr, dek_in, opcode, MLX5_CMD_OP_CREATE_GENERAL_OBJECT); 359 DEVX_SET(general_obj_in_cmd_hdr, dek_in, obj_type, MLX5_OBJ_TYPE_DEK); 360 dek_in = DEVX_ADDR_OF(create_encryption_key_obj_in, in, key_obj); 361 DEVX_SET(encryption_key_obj, dek_in, key_size, attr->key_size); 362 DEVX_SET(encryption_key_obj, dek_in, has_keytag, attr->keytag); 363 DEVX_SET(encryption_key_obj, dek_in, key_purpose, MLX5_ENCRYPTION_KEY_OBJ_KEY_PURPOSE_AES_XTS); 364 DEVX_SET(encryption_key_obj, dek_in, pd, pdn); 365 memcpy(DEVX_ADDR_OF(encryption_key_obj, dek_in, opaque), &attr->opaque, sizeof(attr->opaque)); 366 memcpy(DEVX_ADDR_OF(encryption_key_obj, dek_in, key), attr->dek, attr->key_size_bytes); 367 368 dek->devx_obj = mlx5dv_devx_obj_create(pd->context, in, sizeof(in), out, sizeof(out)); 369 spdk_memset_s(DEVX_ADDR_OF(encryption_key_obj, dek_in, key), attr->key_size_bytes, 0, 370 attr->key_size_bytes); 371 if (!dek->devx_obj) { 372 return -errno; 373 } 374 dek->dek_obj_id = DEVX_GET(general_obj_out_cmd_hdr, out, obj_id); 375 376 return 0; 377 } 378 379 static int 380 mlx5_crypto_dek_query(struct mlx5_crypto_dek *dek, struct mlx5_crypto_dek_query_attr *attr) 381 { 382 uint32_t out[DEVX_ST_SZ_DW(query_encryption_key_obj_out)] = {}; 383 uint32_t in[DEVX_ST_SZ_DW(general_obj_in_cmd_hdr)] = {}; 384 uint8_t *dek_out; 385 int rc; 386 387 assert(attr); 388 DEVX_SET(general_obj_in_cmd_hdr, in, opcode, MLX5_CMD_OP_QUERY_GENERAL_OBJECT); 389 DEVX_SET(general_obj_in_cmd_hdr, in, obj_type, MLX5_OBJ_TYPE_DEK); 390 DEVX_SET(general_obj_in_cmd_hdr, in, obj_id, dek->dek_obj_id); 391 392 rc = mlx5dv_devx_obj_query(dek->devx_obj, in, sizeof(in), out, sizeof(out)); 393 if (rc) { 394 return rc; 395 } 396 397 dek_out = DEVX_ADDR_OF(query_encryption_key_obj_out, out, obj); 398 attr->state = DEVX_GET(encryption_key_obj, dek_out, state); 399 memcpy(&attr->opaque, DEVX_ADDR_OF(encryption_key_obj, dek_out, opaque), sizeof(attr->opaque)); 400 401 return 0; 402 } 403 404 static int 405 mlx5_crypto_dek_create_legacy(struct spdk_mlx5_crypto_dek_legacy *dek, 406 struct mlx5dv_dek_init_attr *init_attr_legacy) 407 { 408 struct mlx5dv_dek_attr query_attr_legacy; 409 int rc; 410 411 init_attr_legacy->pd = dek->pd; 412 413 dek->dek_obj = mlx5dv_dek_create(dek->context, init_attr_legacy); 414 if (!dek->dek_obj) { 415 SPDK_ERRLOG("mlx5dv_dek_create failed on dev %s, errno %d\n", dek->context->device->name, errno); 416 return -EINVAL; 417 } 418 419 rc = mlx5dv_dek_query(dek->dek_obj, &query_attr_legacy); 420 if (rc) { 421 SPDK_ERRLOG("Failed to query DEK on dev %s, rc %d\n", dek->context->device->name, rc); 422 return rc; 423 } 424 if (query_attr_legacy.state != MLX5DV_DEK_STATE_READY) { 425 SPDK_ERRLOG("DEK on dev %s state %d\n", dek->context->device->name, query_attr_legacy.state); 426 return -EINVAL; 427 } 428 429 return 0; 430 } 431 432 int 433 spdk_mlx5_crypto_keytag_create(struct spdk_mlx5_crypto_dek_create_attr *attr, 434 struct spdk_mlx5_crypto_keytag **out) 435 { 436 struct mlx5_crypto_dek *dek; 437 struct spdk_mlx5_crypto_keytag *keytag; 438 struct ibv_context **devs; 439 struct ibv_pd *pd; 440 struct mlx5_crypto_dek_init_attr dek_attr = {}; 441 struct mlx5_crypto_dek_query_attr query_attr; 442 struct mlx5dv_dek_init_attr init_attr_legacy = {}; 443 struct spdk_mlx5_crypto_dek_legacy *dek_legacy; 444 struct spdk_mlx5_device_caps dev_caps; 445 int num_devs = 0, i, rc; 446 447 dek_attr.dek = attr->dek; 448 dek_attr.key_size_bytes = attr->dek_len; 449 dek_attr.opaque = 0; 450 switch (dek_attr.key_size_bytes) { 451 case SPDK_MLX5_AES_XTS_128_DEK_BYTES_WITH_KEYTAG: 452 init_attr_legacy.key_size = MLX5DV_CRYPTO_KEY_SIZE_128; 453 init_attr_legacy.has_keytag = true; 454 dek_attr.key_size = MLX5_ENCRYPTION_KEY_OBJ_KEY_SIZE_SIZE_128; 455 dek_attr.keytag = 1; 456 SPDK_DEBUGLOG(mlx5, "128b AES_XTS with keytag\n"); 457 break; 458 case SPDK_MLX5_AES_XTS_256_DEK_BYTES_WITH_KEYTAG: 459 init_attr_legacy.key_size = MLX5DV_CRYPTO_KEY_SIZE_256; 460 init_attr_legacy.has_keytag = true; 461 dek_attr.key_size = MLX5_ENCRYPTION_KEY_OBJ_KEY_SIZE_SIZE_256; 462 dek_attr.keytag = 1; 463 SPDK_DEBUGLOG(mlx5, "256b AES_XTS with keytag\n"); 464 break; 465 case SPDK_MLX5_AES_XTS_128_DEK_BYTES: 466 init_attr_legacy.key_size = MLX5DV_CRYPTO_KEY_SIZE_128; 467 init_attr_legacy.has_keytag = false; 468 dek_attr.key_size = MLX5_ENCRYPTION_KEY_OBJ_KEY_SIZE_SIZE_128; 469 dek_attr.keytag = 0; 470 SPDK_DEBUGLOG(mlx5, "128b AES_XTS\n"); 471 break; 472 case SPDK_MLX5_AES_XTS_256_DEK_BYTES: 473 init_attr_legacy.key_size = MLX5DV_CRYPTO_KEY_SIZE_256; 474 init_attr_legacy.has_keytag = false; 475 dek_attr.key_size = MLX5_ENCRYPTION_KEY_OBJ_KEY_SIZE_SIZE_256; 476 dek_attr.keytag = 0; 477 SPDK_DEBUGLOG(mlx5, "256b AES_XTS\n"); 478 break; 479 default: 480 SPDK_ERRLOG("Invalid key length %zu. The following keys are supported:\n" 481 "128b key + key2, %u bytes;\n" 482 "256b key + key2, %u bytes\n" 483 "128b key + key2 + keytag, %u bytes\n" 484 "256b lye + key2 + keytag, %u bytes\n", 485 attr->dek_len, SPDK_MLX5_AES_XTS_128_DEK_BYTES, SPDK_MLX5_AES_XTS_256_DEK_BYTES, 486 SPDK_MLX5_AES_XTS_128_DEK_BYTES_WITH_KEYTAG, SPDK_MLX5_AES_XTS_256_DEK_BYTES_WITH_KEYTAG); 487 return -EINVAL; 488 } 489 490 devs = spdk_mlx5_crypto_devs_get(&num_devs); 491 if (!devs || !num_devs) { 492 SPDK_DEBUGLOG(mlx5, "No crypto devices found\n"); 493 return -ENOTSUP; 494 } 495 496 keytag = calloc(1, sizeof(*keytag)); 497 if (!keytag) { 498 SPDK_ERRLOG("Memory allocation failed\n"); 499 spdk_mlx5_crypto_devs_release(devs); 500 return -ENOMEM; 501 } 502 keytag->deks = calloc(num_devs, sizeof(struct mlx5_crypto_dek)); 503 if (!keytag->deks) { 504 SPDK_ERRLOG("Memory allocation failed\n"); 505 spdk_mlx5_crypto_devs_release(devs); 506 free(keytag); 507 return -ENOMEM; 508 } 509 510 /* Legacy part, to be removed soon */ 511 memcpy(init_attr_legacy.key, attr->dek, attr->dek_len); 512 keytag->deks_legacy = calloc(num_devs, sizeof(struct spdk_mlx5_crypto_dek_legacy)); 513 if (!keytag->deks_legacy) { 514 SPDK_ERRLOG("Memory allocation failed\n"); 515 spdk_mlx5_crypto_devs_release(devs); 516 free(keytag->deks); 517 free(keytag); 518 return -ENOMEM; 519 } 520 init_attr_legacy.key_purpose = MLX5DV_CRYPTO_KEY_PURPOSE_AES_XTS; 521 init_attr_legacy.comp_mask = MLX5DV_DEK_INIT_ATTR_CRYPTO_LOGIN; 522 init_attr_legacy.crypto_login = NULL; 523 524 for (i = 0; i < num_devs; i++) { 525 keytag->deks_num++; 526 dek = &keytag->deks[i]; 527 pd = spdk_rdma_utils_get_pd(devs[i]); 528 if (!pd) { 529 SPDK_ERRLOG("Failed to get PD on device %s\n", devs[i]->device->name); 530 rc = -EINVAL; 531 goto err_out; 532 } 533 534 memset(&dev_caps, 0, sizeof(dev_caps)); 535 rc = spdk_mlx5_device_query_caps(devs[i], &dev_caps); 536 if (rc) { 537 SPDK_ERRLOG("Failed to get device %s crypto caps\n", devs[i]->device->name); 538 goto err_out; 539 } 540 rc = mlx5_crypto_dek_init(pd, &dek_attr, dek); 541 if (rc) { 542 SPDK_ERRLOG("Failed to create DEK on dev %s, rc %d\n", pd->context->device->name, rc); 543 goto err_out; 544 } 545 memset(&query_attr, 0, sizeof(query_attr)); 546 rc = mlx5_crypto_dek_query(dek, &query_attr); 547 if (rc) { 548 SPDK_ERRLOG("Failed to query DEK on dev %s, rc %d\n", pd->context->device->name, rc); 549 goto err_out; 550 } 551 if (query_attr.opaque != 0 || query_attr.state != MLX5_ENCRYPTION_KEY_OBJ_STATE_READY) { 552 SPDK_ERRLOG("DEK on dev %s in bad state %d, oapque %"PRIu64"\n", pd->context->device->name, 553 query_attr.state, query_attr.opaque); 554 rc = -EINVAL; 555 goto err_out; 556 } 557 558 dek->pd = pd; 559 dek->context = devs[i]; 560 dek->tweak_mode = dev_caps.crypto.multi_block_be_tweak ? 561 SPDK_MLX5_CRYPTO_KEY_TWEAK_MODE_SIMPLE_LBA_BE : SPDK_MLX5_CRYPTO_KEY_TWEAK_MODE_SIMPLE_LBA_LE; 562 563 /* Legacy part, to be removed soon */ 564 dek_legacy = &keytag->deks_legacy[i]; 565 dek_legacy->pd = pd; 566 dek_legacy->context = devs[i]; 567 rc = mlx5_crypto_dek_create_legacy(dek_legacy, &init_attr_legacy); 568 if (rc) { 569 SPDK_ERRLOG("Failed to create legacy DEK on dev %s, rc %d\n", pd->context->device->name, rc); 570 goto err_out; 571 } 572 } 573 574 spdk_memset_s(init_attr_legacy.key, sizeof(init_attr_legacy.key), 0, sizeof(init_attr_legacy.key)); 575 576 if (dek_attr.keytag) { 577 /* Save keytag, it will be used to configure crypto MKEY */ 578 keytag->has_keytag = true; 579 memcpy(keytag->keytag, attr->dek + attr->dek_len - SPDK_MLX5_AES_XTS_KEYTAG_SIZE, 580 SPDK_MLX5_AES_XTS_KEYTAG_SIZE); 581 } 582 583 spdk_mlx5_crypto_devs_release(devs); 584 *out = keytag; 585 586 return 0; 587 588 err_out: 589 spdk_mlx5_crypto_keytag_destroy(keytag); 590 spdk_mlx5_crypto_devs_release(devs); 591 592 return rc; 593 } 594 595 static inline struct mlx5_crypto_dek * 596 mlx5_crypto_get_dek_by_pd(struct spdk_mlx5_crypto_keytag *keytag, struct ibv_pd *pd) 597 { 598 struct mlx5_crypto_dek *dek; 599 uint32_t i; 600 601 for (i = 0; i < keytag->deks_num; i++) { 602 dek = &keytag->deks[i]; 603 if (dek->pd == pd) { 604 return dek; 605 } 606 } 607 608 return NULL; 609 } 610 611 int 612 spdk_mlx5_crypto_get_dek_data(struct spdk_mlx5_crypto_keytag *keytag, struct ibv_pd *pd, 613 struct spdk_mlx5_crypto_dek_data *data) 614 { 615 struct mlx5_crypto_dek *dek; 616 617 dek = mlx5_crypto_get_dek_by_pd(keytag, pd); 618 if (spdk_unlikely(!dek)) { 619 SPDK_ERRLOG("No DEK for pd %p (dev %s)\n", pd, pd->context->device->name); 620 return -EINVAL; 621 } 622 data->dek_obj_id = dek->dek_obj_id; 623 data->tweak_mode = dek->tweak_mode; 624 625 return 0; 626 } 627 628 SPDK_LOG_REGISTER_COMPONENT(mlx5) 629