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