Bug Summary

File:.build-ci/../libnvme/src/nvme/crypto.c
Warning:line 1160, column 11
Potential leak of memory pointed to by 'identity'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -O3 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name crypto.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/__w/nvme-cli/nvme-cli/.build-ci -fcoverage-compilation-dir=/__w/nvme-cli/nvme-cli/.build-ci -resource-dir /usr/bin/../lib/clang/22 -include /__w/nvme-cli/nvme-cli/.build-ci/nvme-config.h -I libnvme/src/libnvme3.so.1.0.0.p -I libnvme/src -I ../libnvme/src -I ccan -I ../ccan -I . -I .. -D _FILE_OFFSET_BITS=64 -D _GNU_SOURCE -U NDEBUG -internal-isystem /usr/bin/../lib/clang/22/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/16/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -std=gnu11 -ferror-limit 19 -fvisibility=hidden -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fcolor-diagnostics -vectorize-loops -vectorize-slp -analyzer-opt-analyze-headers -analyzer-output=html -faddrsig -fdwarf2-cfi-asm -o /__w/nvme-cli/nvme-cli/.build-ci/scan-results/2026-09-23-073103-589-1 -x c ../libnvme/src/nvme/crypto.c
1// SPDX-License-Identifier: LGPL-2.1-or-later
2/*
3 * This file is part of libnvme.
4 * Copyright (c) 2020 Western Digital Corporation or its affiliates.
5 *
6 * Authors: Keith Busch <keith.busch@wdc.com>
7 * Chaitanya Kulkarni <chaitanya.kulkarni@wdc.com>
8 */
9
10#include <arpa/inet.h>
11#include <errno(*__errno_location ()).h>
12#include <fcntl.h>
13#include <stdio.h>
14#include <stdlib.h>
15#include <string.h>
16#include <unistd.h>
17
18#if NVME_HAVE_SYS_RANDOM1
19#include <sys/random.h>
20#endif
21#include <sys/param.h>
22#include <sys/stat.h>
23
24#ifdef CONFIG_OPENSSL
25#include <openssl/evp.h>
26#include <openssl/hmac.h>
27#include <openssl/kdf.h>
28#include <openssl/core_names.h>
29#include <openssl/params.h>
30#endif
31
32#ifdef CONFIG_KEYUTILS
33#include <keyutils.h>
34
35#define NVME_TLS_DEFAULT_KEYRING".nvme" ".nvme"
36#endif
37
38#include <ccan/endian/endian.h>
39
40#include <shared/base64-util.h>
41#include <shared/crc32-util.h>
42#include <shared/hex-util.h>
43#include <shared/compiler-attributes-util.h>
44
45#include <libnvme.h>
46
47#include "cleanup.h"
48#include "cleanup-linux.h"
49#include "private.h"
50
51
52#ifndef CONFIG_OPENSSL
53static unsigned char default_hmac(size_t key_len)
54{
55 return LIBNVMF_HMAC_ALG_NONE;
56}
57
58__shr_public__attribute__((visibility("default"))) int libnvmf_gen_kxchap_key(struct libnvme_global_ctx *ctx,
59 char *hostnqn, enum libnvmf_hmac_alg hmac,
60 unsigned int key_len, unsigned char *secret,
61 unsigned char *key)
62{
63 if (hmac != LIBNVMF_HMAC_ALG_NONE) {
64 libnvme_msg(ctx, LIBNVME_LOG_ERR, "HMAC transformation not supported; "__libnvme_msg(ctx, LIBNVME_LOG_ERR, ((void*)0), "HMAC transformation not supported; "
"recompile with OpenSSL support.\n")
65 "recompile with OpenSSL support.\n")__libnvme_msg(ctx, LIBNVME_LOG_ERR, ((void*)0), "HMAC transformation not supported; "
"recompile with OpenSSL support.\n")
;
66 return -EINVAL22;
67 }
68
69 memcpy(key, secret, key_len);
70 return 0;
71}
72
73__shr_public__attribute__((visibility("default"))) int libnvmf_create_raw_secret(struct libnvme_global_ctx *ctx,
74 const char *secret, size_t key_len, unsigned char **raw_secret)
75{
76 libnvme_msg(ctx, LIBNVME_LOG_ERR, "NVMe TLS is not supported; "__libnvme_msg(ctx, LIBNVME_LOG_ERR, ((void*)0), "NVMe TLS is not supported; "
"recompile with OpenSSL support.\n")
77 "recompile with OpenSSL support.\n")__libnvme_msg(ctx, LIBNVME_LOG_ERR, ((void*)0), "NVMe TLS is not supported; "
"recompile with OpenSSL support.\n")
;
78 return -ENOTSUP95;
79}
80
81static int derive_retained_key(struct libnvme_global_ctx *ctx,
82 int hmac, const char *hostnqn, unsigned char *generated,
83 unsigned char *retained, size_t key_len)
84{
85 libnvme_msg(ctx, LIBNVME_LOG_ERR, "NVMe TLS is not supported; "__libnvme_msg(ctx, LIBNVME_LOG_ERR, ((void*)0), "NVMe TLS is not supported; "
"recompile with OpenSSL support.\n")
86 "recompile with OpenSSL support.\n")__libnvme_msg(ctx, LIBNVME_LOG_ERR, ((void*)0), "NVMe TLS is not supported; "
"recompile with OpenSSL support.\n")
;
87 return -ENOTSUP95;
88}
89
90static int derive_retained_key_compat(struct libnvme_global_ctx *ctx,
91 int hmac, const char *hostnqn, unsigned char *generated,
92 unsigned char *retained, size_t key_len)
93{
94 libnvme_msg(ctx, LIBNVME_LOG_ERR, "NVMe TLS is not supported; "__libnvme_msg(ctx, LIBNVME_LOG_ERR, ((void*)0), "NVMe TLS is not supported; "
"recompile with OpenSSL support.\n")
95 "recompile with OpenSSL support.\n")__libnvme_msg(ctx, LIBNVME_LOG_ERR, ((void*)0), "NVMe TLS is not supported; "
"recompile with OpenSSL support.\n")
;
96 return -ENOTSUP95;
97}
98
99static int derive_psk_digest(struct libnvme_global_ctx *ctx,
100 const char *hostnqn, const char *subsysnqn,
101 int version, int cipher,
102 unsigned char *retained, size_t key_len,
103 char *digest, size_t digest_len)
104{
105 libnvme_msg(ctx, LIBNVME_LOG_ERR, "TLS PSK identity version 1 is not "__libnvme_msg(ctx, LIBNVME_LOG_ERR, ((void*)0), "TLS PSK identity version 1 is not "
"supported; recompile with OpenSSL support.\n")
106 "supported; recompile with OpenSSL support.\n")__libnvme_msg(ctx, LIBNVME_LOG_ERR, ((void*)0), "TLS PSK identity version 1 is not "
"supported; recompile with OpenSSL support.\n")
;
107 return -ENOTSUP95;
108}
109
110static int derive_tls_key(struct libnvme_global_ctx *ctx,
111 int version, unsigned char cipher, const char *context,
112 unsigned char *retained, unsigned char *psk, size_t key_len)
113{
114 libnvme_msg(ctx, LIBNVME_LOG_ERR, "NVMe TLS is not supported; "__libnvme_msg(ctx, LIBNVME_LOG_ERR, ((void*)0), "NVMe TLS is not supported; "
"recompile with OpenSSL support.\n")
115 "recompile with OpenSSL support.\n")__libnvme_msg(ctx, LIBNVME_LOG_ERR, ((void*)0), "NVMe TLS is not supported; "
"recompile with OpenSSL support.\n")
;
116 return -ENOTSUP95;
117}
118
119static int derive_tls_key_compat(struct libnvme_global_ctx *ctx,
120 int version, unsigned char cipher, const char *context,
121 unsigned char *retained, unsigned char *psk, size_t key_len)
122{
123 libnvme_msg(ctx, LIBNVME_LOG_ERR, "NVMe TLS is not supported; "__libnvme_msg(ctx, LIBNVME_LOG_ERR, ((void*)0), "NVMe TLS is not supported; "
"recompile with OpenSSL support.\n")
124 "recompile with OpenSSL support.\n")__libnvme_msg(ctx, LIBNVME_LOG_ERR, ((void*)0), "NVMe TLS is not supported; "
"recompile with OpenSSL support.\n")
;
125 return -ENOTSUP95;
126}
127#else /* CONFIG_OPENSSL */
128static unsigned char default_hmac(size_t key_len)
129{
130 unsigned char hmac = LIBNVMF_HMAC_ALG_NONE;
131
132 switch (key_len) {
133 case 32:
134 hmac = LIBNVMF_HMAC_ALG_SHA2_256;
135 break;
136 case 48:
137 hmac = LIBNVMF_HMAC_ALG_SHA2_384;
138 break;
139 case 64:
140 hmac = LIBNVMF_HMAC_ALG_SHA2_512;
141 break;
142 default:
143 break;
144 }
145 return hmac;
146}
147
148static const EVP_MD *select_hmac(int hmac, size_t *hmac_len)
149{
150 const EVP_MD *md = NULL((void*)0);
151
152 switch (hmac) {
153 case LIBNVMF_HMAC_ALG_SHA2_256:
154 md = EVP_sha256();
155 *hmac_len = 32;
156 break;
157 case LIBNVMF_HMAC_ALG_SHA2_384:
158 md = EVP_sha384();
159 *hmac_len = 48;
160 break;
161 default:
162 *hmac_len = 0;
163 break;
164 }
165 return md;
166}
167
168static DEFINE_CLEANUP_FUNC(void cleanup_evp_pkey_ctx(EVP_PKEY_CTX * *__p) { if (*__p) EVP_PKEY_CTX_free
(*__p); }
169 cleanup_evp_pkey_ctx, EVP_PKEY_CTX *, EVP_PKEY_CTX_free)void cleanup_evp_pkey_ctx(EVP_PKEY_CTX * *__p) { if (*__p) EVP_PKEY_CTX_free
(*__p); }
170#define __cleanup_evp_pkey_ctx__attribute__((cleanup(cleanup_evp_pkey_ctx))) __cleanup(cleanup_evp_pkey_ctx)__attribute__((cleanup(cleanup_evp_pkey_ctx)))
171
172/* NVMe is using the TLS 1.3 HkdfLabel structure */
173#define HKDF_INFO_MAX_LEN514 514
174#define HKDF_INFO_LABEL_MAX256 256
175#define HKDF_INFO_CONTEXT_MAX256 256
176
177/*
178 * derive_retained_key()
179 *
180 * Derive a retained PSK according to the NVMe TCP Transport
181 * Specification 1.3, section 3.6.1.3:
182 *
183 * The retained PSK is derived from the configured PSK. The configured PSK
184 * shall be destroyed as soon as the retained PSK is generated and stored.
185 * Each NVMe/TCP entity shall support:
186 * 1) transforming the configured PSK into a retained PSK before it is stored
187 * by the NVMe/TCP entity for repeated use with another NVMe/TCP entity; and
188 * 2) using the configured PSK as a retained PSK.
189 *
190 * The method to derive a retained PSK from a configured PSK shall be using
191 * the HKDF-Extract and HKDF-Expand-Label operations (refer to RFC 5869 and
192 * RFC 8446):
193 * 1. PRK = HKDF-Extract(0, Configured PSK); and
194 * 2. Retained PSK = HKDF-Expand-Label(PRK, “HostNQN”, NQNh,
195 * Length(Configured PSK)),
196 * where NQNh is the NQN of the host.
197 *
198 * 'hmac' indicates the hash function to be used to transform the configured
199 * PSK in a retained PSK, encoded as follows:
200 *
201 * - 0 indicates no transform (i.e., the configured PSK is used as a
202 * retained PSK)
203 * - 1 indicates SHA-256
204 * - 2 indicates SHA-384
205 */
206static int derive_retained_key(struct libnvme_global_ctx *ctx,
207 int hmac, const char *hostnqn,
208 unsigned char *configured, unsigned char *retained,
209 size_t key_len)
210{
211 __cleanup_evp_pkey_ctx__attribute__((cleanup(cleanup_evp_pkey_ctx))) EVP_PKEY_CTX *ectx = NULL((void*)0);
212 __cleanup_free__attribute__((cleanup(shr_freep))) uint8_t *hkdf_info = NULL((void*)0);
213 char *hkdf_label;
214 const EVP_MD *md;
215 size_t hmac_len;
216 char *pos;
217 int ret;
218
219 /* +1 byte so that the snprintf terminating null can not overflow */
220 hkdf_info = malloc(HKDF_INFO_MAX_LEN514 + 1);
221 if (!hkdf_info)
222 return -ENOMEM12;
223
224 if (hmac == LIBNVMF_HMAC_ALG_NONE) {
225 memcpy(retained, configured, key_len);
226 return key_len;
227 }
228
229 md = select_hmac(hmac, &hmac_len);
230 if (!md || !hmac_len)
231 return -EINVAL22;
232
233 ectx = EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF1036, NULL((void*)0));
234 if (!ectx)
235 return -ENOMEM12;
236
237 if (EVP_PKEY_derive_init(ectx) <= 0)
238 return -ENOMEM12;
239
240 if (EVP_PKEY_CTX_set_hkdf_md(ectx, md) <= 0)
241 return -ENOKEY126;
242
243 if (EVP_PKEY_CTX_set1_hkdf_key(ectx, configured, key_len) <= 0)
244 return -ENOKEY126;
245
246 if (key_len > USHRT_MAX(32767 * 2 + 1))
247 return -EINVAL22;
248
249 pos = (char *)hkdf_info;
250 *(uint16_t *)pos = htons(key_len & 0xFFFF)__bswap_16 (key_len & 0xFFFF);
251 pos += sizeof(uint16_t);
252
253 hkdf_label = "tls13 HostNQN";
254 ret = snprintf(pos, HKDF_INFO_LABEL_MAX256 + 1, "%c%s",
255 (int)strlen(hkdf_label), hkdf_label);
256 if (ret <= 0 || ret > HKDF_INFO_LABEL_MAX256)
257 return -ENOKEY126;
258 pos += ret;
259
260 ret = snprintf(pos, HKDF_INFO_CONTEXT_MAX256 + 1, "%c%s",
261 (int)strlen(hostnqn), hostnqn);
262 if (ret <= 0 || ret > HKDF_INFO_CONTEXT_MAX256)
263 return -ENOKEY126;
264 pos += ret;
265
266 if (EVP_PKEY_CTX_add1_hkdf_info(ectx, hkdf_info,
267 (pos - (char *)hkdf_info)) <= 0)
268 return -ENOKEY126;
269
270 if (EVP_PKEY_derive(ectx, retained, &key_len) <= 0)
271 return -ENOKEY126;
272
273 return key_len;
274}
275
276static int derive_retained_key_compat(struct libnvme_global_ctx *ctx,
277 int hmac, const char *hostnqn, unsigned char *configured,
278 unsigned char *retained, size_t key_len)
279{
280 __cleanup_evp_pkey_ctx__attribute__((cleanup(cleanup_evp_pkey_ctx))) EVP_PKEY_CTX *ectx = NULL((void*)0);
281 __cleanup_free__attribute__((cleanup(shr_freep))) uint8_t *hkdf_info = NULL((void*)0);
282 const EVP_MD *md;
283 size_t hmac_len;
284 char *pos;
285 int ret;
286
287 if (hmac == LIBNVMF_HMAC_ALG_NONE) {
288 memcpy(retained, configured, key_len);
289 return key_len;
290 }
291
292 md = select_hmac(hmac, &hmac_len);
293 if (!md || !hmac_len)
294 return -EINVAL22;
295
296 ectx = EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF1036, NULL((void*)0));
297 if (!ectx)
298 return -ENOMEM12;
299
300 if (EVP_PKEY_derive_init(ectx) <= 0)
301 return -ENOMEM12;
302
303 if (EVP_PKEY_CTX_set_hkdf_md(ectx, md) <= 0)
304 return -ENOKEY126;
305
306 if (EVP_PKEY_CTX_set1_hkdf_key(ectx, configured, key_len) <= 0)
307 return -ENOKEY126;
308
309 /* +1 byte so that the snprintf terminating null can not overflow */
310 hkdf_info = malloc(HKDF_INFO_MAX_LEN514 + 1);
311 if (!hkdf_info)
312 return -ENOMEM12;
313
314 pos = (char *)hkdf_info;
315 *(uint16_t *)pos = cpu_to_le16(key_len);
316 pos += sizeof(uint16_t);
317
318 ret = snprintf(pos, HKDF_INFO_LABEL_MAX256 + 1,
319 "tls13 HostNQN%s", hostnqn);
320 if (ret <= 0 || ret > HKDF_INFO_LABEL_MAX256)
321 return -ENOKEY126;
322 pos += ret;
323
324 if (EVP_PKEY_CTX_add1_hkdf_info(ectx, hkdf_info,
325 (pos - (char *)hkdf_info)) <= 0)
326 return -ENOKEY126;
327
328 if (EVP_PKEY_derive(ectx, retained, &key_len) <= 0)
329 return -ENOKEY126;
330
331 return key_len;
332}
333
334/*
335 * derive_tls_key()
336 *
337 * Derive a TLS PSK from a retained PSK.
338 *
339 * The TLS PSK shall be derived as follows from an input PSK (i.e., either
340 * a retained PSK or a generated PSK) and a PSK identity using the HKDF-Extract
341 * and HKDF-Expand-Label operations (refer to RFC 5869 and RFC 8446) where the
342 * hash function is the one specified by the hash specifier of the PSK identity:
343 * 1. PRK = HKDF-Extract(0, Input PSK); and
344 * 2. TLS PSK = HKDF-Expand-Label(PRK, “nvme-tls-psk”, PskIdentity, L),
345 * where PskIdentity is the PSK identity and L is the output size in bytes of
346 * the hash function (i.e., 32 for SHA-256 and 48 for SHA-384).
347 *
348 * Note that this is _not_ the hash value as specified by the configured PSK,
349 * but rather the hash function of the cipher suite associated with the
350 * PSK:
351 * - 1 indicates SHA-256 (for the TLS_AES_128_GCM_SHA256 cipher suite)
352 * - 2 indicates SHA-384 (for the TLS_AES_256_GCM_SHA384 cipher suite)
353 *
354 * and the value '0' is invalid here.
355 */
356
357static int derive_tls_key(struct libnvme_global_ctx *ctx,
358 int version, unsigned char cipher, const char *context,
359 unsigned char *retained, unsigned char *psk, size_t key_len)
360{
361 __cleanup_evp_pkey_ctx__attribute__((cleanup(cleanup_evp_pkey_ctx))) EVP_PKEY_CTX *ectx = NULL((void*)0);
362 __cleanup_free__attribute__((cleanup(shr_freep))) uint8_t *hkdf_info = NULL((void*)0);
363 char *hkdf_label;
364 const EVP_MD *md;
365 size_t hmac_len;
366 char *pos;
367 int ret;
368
369 /* +1 byte so that the snprintf terminating null can not overflow */
370 hkdf_info = malloc(HKDF_INFO_MAX_LEN514 + 1);
371 if (!hkdf_info)
372 return -ENOMEM12;
373
374 md = select_hmac(cipher, &hmac_len);
375 if (!md || !hmac_len)
376 return -EINVAL22;
377
378 ectx = EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF1036, NULL((void*)0));
379 if (!ectx)
380 return -ENOMEM12;
381
382 if (EVP_PKEY_derive_init(ectx) <= 0)
383 return -ENOMEM12;
384
385 if (EVP_PKEY_CTX_set_hkdf_md(ectx, md) <= 0)
386 return -ENOKEY126;
387
388 if (EVP_PKEY_CTX_set1_hkdf_key(ectx, retained, key_len) <= 0)
389 return -ENOKEY126;
390
391 if (key_len > USHRT_MAX(32767 * 2 + 1))
392 return -EINVAL22;
393
394 pos = (char *)hkdf_info;
395 *(uint16_t *)pos = htons(key_len & 0xFFFF)__bswap_16 (key_len & 0xFFFF);
396 pos += sizeof(uint16_t);
397
398 hkdf_label = "tls13 nvme-tls-psk";
399 ret = snprintf(pos, HKDF_INFO_LABEL_MAX256 + 1, "%c%s",
400 (int)strlen(hkdf_label), hkdf_label);
401 if (ret <= 0 || ret > HKDF_INFO_LABEL_MAX256)
402 return -ENOKEY126;
403 pos += ret;
404
405 switch (version) {
406 case 0:
407 ret = snprintf(pos, HKDF_INFO_CONTEXT_MAX256 + 1, "%c%s",
408 (int)strlen(context), context);
409 if (ret <= 0 || ret > HKDF_INFO_CONTEXT_MAX256)
410 return -ENOKEY126;
411 pos += ret;
412 break;
413 case 1:
414 ret = snprintf(pos, HKDF_INFO_CONTEXT_MAX256 + 1, "%c%02d %s",
415 (int)strlen(context) + 3, cipher, context);
416 if (ret <= 0 || ret > HKDF_INFO_CONTEXT_MAX256)
417 return -ENOKEY126;
418 pos += ret;
419 break;
420 default:
421 return -ENOKEY126;
422 }
423
424 if (EVP_PKEY_CTX_add1_hkdf_info(ectx, hkdf_info,
425 (pos - (char *)hkdf_info)) <= 0)
426 return -ENOKEY126;
427
428 if (EVP_PKEY_derive(ectx, psk, &key_len) <= 0)
429 return -ENOKEY126;
430
431 return key_len;
432}
433
434static int derive_tls_key_compat(struct libnvme_global_ctx *ctx,
435 int version, unsigned char cipher, const char *context,
436 unsigned char *retained, unsigned char *psk, size_t key_len)
437{
438 __cleanup_evp_pkey_ctx__attribute__((cleanup(cleanup_evp_pkey_ctx))) EVP_PKEY_CTX *ectx = NULL((void*)0);
439 __cleanup_free__attribute__((cleanup(shr_freep))) uint8_t *hkdf_info = NULL((void*)0);
440 const EVP_MD *md;
441 size_t hmac_len;
442 char *pos;
443 int ret;
444
445 md = select_hmac(cipher, &hmac_len);
446 if (!md || !hmac_len)
447 return -EINVAL22;
448
449 ectx = EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF1036, NULL((void*)0));
450 if (!ectx)
451 return -ENOMEM12;
452
453 if (EVP_PKEY_derive_init(ectx) <= 0)
454 return -ENOMEM12;
455
456 if (EVP_PKEY_CTX_set_hkdf_md(ectx, md) <= 0)
457 return -ENOKEY126;
458
459 if (EVP_PKEY_CTX_set1_hkdf_key(ectx, retained, key_len) <= 0)
460 return -ENOKEY126;
461
462 /* +1 byte so that the snprintf terminating null can not overflow */
463 hkdf_info = malloc(HKDF_INFO_MAX_LEN514 + 1);
464 if (!hkdf_info)
465 return -ENOMEM12;
466
467 pos = (char *)hkdf_info;
468 *(uint16_t *)pos = cpu_to_le16(key_len);
469 pos += sizeof(uint16_t);
470
471 ret = snprintf(pos, HKDF_INFO_LABEL_MAX256 + 1, "tls13 nvme-tls-psk");
472 if (ret <= 0 || ret > HKDF_INFO_LABEL_MAX256)
473 return -ENOKEY126;
474 pos += ret;
475
476 switch (version) {
477 case 0:
478 ret = snprintf(pos, HKDF_INFO_CONTEXT_MAX256 + 1, "%s", context);
479 if (ret <= 0 || ret > HKDF_INFO_CONTEXT_MAX256)
480 return -ENOKEY126;
481 pos += ret;
482 break;
483 case 1:
484 ret = snprintf(pos, HKDF_INFO_CONTEXT_MAX256 + 1, "%02d %s",
485 cipher, context);
486 if (ret <= 0 || ret > HKDF_INFO_CONTEXT_MAX256)
487 return -ENOKEY126;
488 pos += ret;
489 break;
490 default:
491 return -ENOKEY126;
492 }
493
494 if (EVP_PKEY_CTX_add1_hkdf_info(ectx, hkdf_info,
495 (pos - (char *)hkdf_info)) <= 0)
496 return -ENOKEY126;
497
498 if (EVP_PKEY_derive(ectx, psk, &key_len) <= 0)
499 return -ENOKEY126;
500
501 return key_len;
502}
503
504static DEFINE_CLEANUP_FUNC(void cleanup_ossl_lib_ctx(OSSL_LIB_CTX * *__p) { if (*__p) OSSL_LIB_CTX_free
(*__p); }
505 cleanup_ossl_lib_ctx, OSSL_LIB_CTX *, OSSL_LIB_CTX_free)void cleanup_ossl_lib_ctx(OSSL_LIB_CTX * *__p) { if (*__p) OSSL_LIB_CTX_free
(*__p); }
506#define __cleanup_ossl_lib_ctx__attribute__((cleanup(cleanup_ossl_lib_ctx))) __cleanup(cleanup_ossl_lib_ctx)__attribute__((cleanup(cleanup_ossl_lib_ctx)))
507static DEFINE_CLEANUP_FUNC(cleanup_evp_mac_ctx, EVP_MAC_CTX *, EVP_MAC_CTX_free)void cleanup_evp_mac_ctx(EVP_MAC_CTX * *__p) { if (*__p) EVP_MAC_CTX_free
(*__p); }
508#define __cleanup_evp_mac_ctx__attribute__((cleanup(cleanup_evp_mac_ctx))) __cleanup(cleanup_evp_mac_ctx)__attribute__((cleanup(cleanup_evp_mac_ctx)))
509static DEFINE_CLEANUP_FUNC(cleanup_evp_mac, EVP_MAC *, EVP_MAC_free)void cleanup_evp_mac(EVP_MAC * *__p) { if (*__p) EVP_MAC_free
(*__p); }
510#define __cleanup_evp_mac__attribute__((cleanup(cleanup_evp_mac))) __cleanup(cleanup_evp_mac)__attribute__((cleanup(cleanup_evp_mac)))
511
512__shr_public__attribute__((visibility("default"))) int libnvmf_gen_kxchap_key(struct libnvme_global_ctx *ctx,
513 char *hostnqn, enum libnvmf_hmac_alg hmac,
514 unsigned int key_len, unsigned char *secret,
515 unsigned char *key)
516{
517 const char hmac_seed[] = "NVMe-over-Fabrics";
518 __cleanup_ossl_lib_ctx__attribute__((cleanup(cleanup_ossl_lib_ctx))) OSSL_LIB_CTX *lib_ctx = NULL((void*)0);
519 __cleanup_evp_mac_ctx__attribute__((cleanup(cleanup_evp_mac_ctx))) EVP_MAC_CTX *mac_ctx = NULL((void*)0);
520 __cleanup_evp_mac__attribute__((cleanup(cleanup_evp_mac))) EVP_MAC *mac = NULL((void*)0);
521 OSSL_PARAM params[2], *p = params;
522 char *progq = NULL((void*)0);
523 char *digest;
524 size_t len;
525
526 lib_ctx = OSSL_LIB_CTX_new();
527 if (!lib_ctx)
528 return -ENOMEM12;
529
530 mac = EVP_MAC_fetch(lib_ctx, OSSL_MAC_NAME_HMAC"HMAC", progq);
531 if (!mac)
532 return -ENOMEM12;
533
534 mac_ctx = EVP_MAC_CTX_new(mac);
535 if (!mac_ctx)
536 return -ENOMEM12;
537
538 switch (hmac) {
539 case LIBNVMF_HMAC_ALG_NONE:
540 memcpy(key, secret, key_len);
541 return 0;
542 case LIBNVMF_HMAC_ALG_SHA2_256:
543 digest = OSSL_DIGEST_NAME_SHA2_256"SHA2-256";
544 break;
545 case LIBNVMF_HMAC_ALG_SHA2_384:
546 digest = OSSL_DIGEST_NAME_SHA2_384"SHA2-384";
547 break;
548 case LIBNVMF_HMAC_ALG_SHA2_512:
549 digest = OSSL_DIGEST_NAME_SHA2_512"SHA2-512";
550 break;
551 default:
552 return -EINVAL22;
553 }
554 *p++ = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST"digest",
555 digest,
556 0);
557 *p = OSSL_PARAM_construct_end();
558
559 if (!EVP_MAC_init(mac_ctx, secret, key_len, params))
560 return -ENOKEY126;
561
562 if (!EVP_MAC_update(mac_ctx, (unsigned char *)hostnqn,
563 strlen(hostnqn)))
564 return -ENOKEY126;
565
566 if (!EVP_MAC_update(mac_ctx, (unsigned char *)hmac_seed,
567 strlen(hmac_seed)))
568 return -ENOKEY126;
569
570 if (!EVP_MAC_final(mac_ctx, key, &len, key_len))
571 return -ENOKEY126;
572
573 if (len != key_len)
574 return -EMSGSIZE90;
575
576 return 0;
577}
578
579static int derive_psk_digest(struct libnvme_global_ctx *ctx,
580 const char *hostnqn, const char *subsysnqn,
581 int version, int cipher,
582 unsigned char *retained, size_t key_len,
583 char *digest, size_t digest_len)
584{
585 static const char hmac_seed[] = "NVMe-over-Fabrics";
586 __cleanup_ossl_lib_ctx__attribute__((cleanup(cleanup_ossl_lib_ctx))) OSSL_LIB_CTX *lib_ctx = NULL((void*)0);
587 __cleanup_evp_mac_ctx__attribute__((cleanup(cleanup_evp_mac_ctx))) EVP_MAC_CTX *mac_ctx = NULL((void*)0);
588 __cleanup_free__attribute__((cleanup(shr_freep))) unsigned char *psk_ctx = NULL((void*)0);
589 __cleanup_evp_mac__attribute__((cleanup(cleanup_evp_mac))) EVP_MAC *mac = NULL((void*)0);
590 OSSL_PARAM params[2], *p = params;
591 size_t hmac_len;
592 char *progq = NULL((void*)0);
593 char *dig = NULL((void*)0);
594 int len;
595
596 lib_ctx = OSSL_LIB_CTX_new();
597 if (!lib_ctx)
598 return -ENOMEM12;
599
600 mac = EVP_MAC_fetch(lib_ctx, OSSL_MAC_NAME_HMAC"HMAC", progq);
601 if (!mac)
602 return -ENOMEM12;
603
604 mac_ctx = EVP_MAC_CTX_new(mac);
605 if (!mac_ctx)
606 return -ENOMEM12;
607
608 switch (cipher) {
609 case LIBNVMF_HMAC_ALG_SHA2_256:
610 dig = OSSL_DIGEST_NAME_SHA2_256"SHA2-256";
611 break;
612 case LIBNVMF_HMAC_ALG_SHA2_384:
613 dig = OSSL_DIGEST_NAME_SHA2_384"SHA2-384";
614 break;
615 default:
616 return -EINVAL22;
617 }
618
619 *p++ = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST"digest",
620 dig, 0);
621 *p = OSSL_PARAM_construct_end();
622
623 psk_ctx = malloc(key_len);
624 if (!psk_ctx)
625 return -ENOMEM12;
626
627 if (!EVP_MAC_init(mac_ctx, retained, key_len, params))
628 return -ENOKEY126;
629
630 if (!EVP_MAC_update(mac_ctx, (unsigned char *)hostnqn,
631 strlen(hostnqn)))
632 return -ENOKEY126;
633
634 if (!EVP_MAC_update(mac_ctx, (unsigned char *)" ", 1))
635 return -ENOKEY126;
636
637 if (!EVP_MAC_update(mac_ctx, (unsigned char *)subsysnqn,
638 strlen(subsysnqn)))
639 return -ENOKEY126;
640
641 if (!EVP_MAC_update(mac_ctx, (unsigned char *)" ", 1))
642 return -ENOKEY126;
643
644 if (!EVP_MAC_update(mac_ctx, (unsigned char *)hmac_seed,
645 strlen(hmac_seed)))
646 return -ENOKEY126;
647
648 if (!EVP_MAC_final(mac_ctx, psk_ctx, &hmac_len, key_len))
649 return -ENOKEY126;
650
651 if (hmac_len > key_len)
652 return -EMSGSIZE90;
653
654 if (hmac_len * 2 > digest_len)
655 return -EINVAL22;
656
657 memset(digest, 0, digest_len);
658 len = shr_base64_encode(psk_ctx, hmac_len, digest);
659 if (len < 0)
660 return len;
661
662 return strlen(digest);
663}
664
665static ssize_t getrandom_bytes(void *buf, size_t buflen)
666{
667 ssize_t result;
668#if NVME_HAVE_SYS_RANDOM1
669 result = getrandom(buf, buflen, GRND_NONBLOCK0x01);
670#else
671 __cleanup_fd__attribute__((cleanup(shr_cleanup_fd))) int fd = -1;
672
673 fd = open("/dev/urandom", O_RDONLY00);
674 if (fd < 0)
675 return -errno(*__errno_location ());
676 result = read(fd, buf, buflen);
677#endif
678 if (result < 0)
679 return -errno(*__errno_location ());
680 return result;
681}
682
683static ssize_t getswordfish(struct libnvme_global_ctx *ctx,
684 const char *seed, void *buf, size_t buflen)
685{
686 unsigned char hash[EVP_MAX_MD_SIZE64];
687 unsigned int counter = 0;
688 EVP_MD_CTX *md_ctx;
689 size_t copied = 0;
690
691 md_ctx = EVP_MD_CTX_new();
692 if (!md_ctx)
693 return -ENOMEM12;
694
695 while (copied < buflen) {
696 beint32_t be_counter;
697 unsigned int hash_len;
698 size_t to_copy;
699
700 if (EVP_DigestInit_ex(md_ctx, EVP_sha256(), NULL((void*)0)) != 1)
701 goto err;
702
703 be_counter = cpu_to_be32(counter);
704
705 EVP_DigestUpdate(md_ctx, seed, strlen(seed));
706 EVP_DigestUpdate(md_ctx, &be_counter, sizeof(be_counter));
707
708 if (EVP_DigestFinal_ex(md_ctx, hash, &hash_len) != 1)
709 goto err;
710
711 to_copy = buflen - copied;
712 if (to_copy > hash_len)
713 to_copy = hash_len;
714
715 memcpy((unsigned char *)buf + copied, hash, to_copy);
716 copied += to_copy;
717 counter++;
718 }
719
720 EVP_MD_CTX_free(md_ctx);
721 return buflen;
722
723err:
724 EVP_MD_CTX_free(md_ctx);
725 return -EIO5;
726}
727
728__shr_public__attribute__((visibility("default"))) int libnvmf_create_raw_secret(struct libnvme_global_ctx *ctx,
729 const char *secret, size_t key_len, unsigned char **raw_secret)
730{
731 __cleanup_free__attribute__((cleanup(shr_freep))) unsigned char *buf = NULL((void*)0);
732 int secret_len = 0, i, err;
733
734 if (key_len != 32 && key_len != 48 && key_len != 64) {
735 libnvme_msg(ctx, LIBNVME_LOG_ERR,__libnvme_msg(ctx, LIBNVME_LOG_ERR, ((void*)0), "Invalid key length %zu"
, key_len)
736 "Invalid key length %zu", key_len)__libnvme_msg(ctx, LIBNVME_LOG_ERR, ((void*)0), "Invalid key length %zu"
, key_len)
;
737 return -EINVAL22;
738 }
739
740 buf = malloc(key_len);
741 if (!buf)
742 return -ENOMEM12;
743
744 if (!secret) {
745 err = getrandom_bytes(buf, key_len);
746 if (err < 0)
747 return err;
748
749 goto out;
750 }
751
752 if (strlen(secret) < 4) {
753 libnvme_msg(ctx, LIBNVME_LOG_ERR, "Input secret too short\n")__libnvme_msg(ctx, LIBNVME_LOG_ERR, ((void*)0), "Input secret too short\n"
)
;
754 return -EINVAL22;
755 }
756
757 if (!strncmp(secret, "pin:", 4)) {
758 err = getswordfish(ctx, &secret[4], buf, key_len);
759 if (err < 0)
760 return err;
761
762 goto out;
763 }
764
765 for (i = 0; i < strlen(secret); i += 2) {
766 int hi = shr_hex_to_int(secret[i]);
767 int lo = shr_hex_to_int(secret[i + 1]);
768
769 if (hi < 0 || lo < 0) {
770 libnvme_msg(ctx, LIBNVME_LOG_ERR,__libnvme_msg(ctx, LIBNVME_LOG_ERR, ((void*)0), "Invalid secret '%s'"
, secret)
771 "Invalid secret '%s'", secret)__libnvme_msg(ctx, LIBNVME_LOG_ERR, ((void*)0), "Invalid secret '%s'"
, secret)
;
772 return -EINVAL22;
773 }
774 if (i >= key_len * 2) {
775 libnvme_msg(ctx, LIBNVME_LOG_ERR,__libnvme_msg(ctx, LIBNVME_LOG_ERR, ((void*)0), "Skipping excess secret bytes\n"
)
776 "Skipping excess secret bytes\n")__libnvme_msg(ctx, LIBNVME_LOG_ERR, ((void*)0), "Skipping excess secret bytes\n"
)
;
777 break;
778 }
779 buf[secret_len++] = (unsigned char)(hi << 4 | lo);
780 }
781 if (secret_len != key_len) {
782 libnvme_msg(ctx, LIBNVME_LOG_ERR,__libnvme_msg(ctx, LIBNVME_LOG_ERR, ((void*)0), "Invalid key length (%d bytes)\n"
, secret_len)
783 "Invalid key length (%d bytes)\n", secret_len)__libnvme_msg(ctx, LIBNVME_LOG_ERR, ((void*)0), "Invalid key length (%d bytes)\n"
, secret_len)
;
784 return -EINVAL22;
785 }
786
787out:
788 *raw_secret = buf;
789 buf = NULL((void*)0);
790 return 0;
791}
792
793#endif /* CONFIG_OPENSSL */
794
795static int gen_tls_identity(const char *hostnqn, const char *subsysnqn,
796 int version, int cipher, char *digest,
797 char *identity)
798{
799 if (version == 0) {
800 sprintf(identity, "NVMe%01dR%02d %s %s",
801 version, cipher, hostnqn, subsysnqn);
802 return strlen(identity);
803 }
804 if (version > 1 || !digest)
805 return -EINVAL22;
806
807 sprintf(identity, "NVMe%01dR%02d %s %s %s",
808 version, cipher, hostnqn, subsysnqn, digest);
809 return strlen(identity);
810}
811
812static int derive_nvme_keys(struct libnvme_global_ctx *ctx,
813 const char *hostnqn, const char *subsysnqn,
814 char *identity, int version,
815 int hmac, unsigned char *configured,
816 unsigned char *psk, int key_len, bool_Bool compat)
817{
818 __cleanup_free__attribute__((cleanup(shr_freep))) unsigned char *retained = NULL((void*)0);
819 __cleanup_free__attribute__((cleanup(shr_freep))) char *digest = NULL((void*)0);
820 char *context = identity;
821 unsigned char cipher;
822 int ret = -1;
823
824 if (!hostnqn || !subsysnqn || !identity || !psk)
825 return -EINVAL22;
826
827 retained = malloc(key_len);
828 if (!retained)
829 return -ENOMEM12;
830
831 if (compat)
832 ret = derive_retained_key_compat(ctx, hmac, hostnqn, configured,
833 retained, key_len);
834 else
835 ret = derive_retained_key(ctx, hmac, hostnqn, configured,
836 retained, key_len);
837 if (ret < 0)
838 return ret;
839
840 if (hmac == LIBNVMF_HMAC_ALG_NONE)
841 cipher = default_hmac(key_len);
842 else
843 cipher = hmac;
844
845 if (version == 1) {
846 size_t digest_len = 2 * key_len;
847
848 digest = malloc(digest_len);
849 if (!digest)
850 return -ENOMEM12;
851
852 ret = derive_psk_digest(ctx, hostnqn, subsysnqn, version,
853 cipher, retained, key_len, digest,
854 digest_len);
855 if (ret < 0)
856 return ret;
857 context = digest;
858 }
859 ret = gen_tls_identity(hostnqn, subsysnqn, version, cipher,
860 digest, identity);
861 if (ret < 0)
862 return ret;
863 if (compat)
864 return derive_tls_key_compat(ctx, version, cipher, context,
865 retained, psk, key_len);
866 return derive_tls_key(ctx, version, cipher, context, retained,
867 psk, key_len);
868}
869
870static ssize_t nvme_identity_len(int hmac, int version, const char *hostnqn,
871 const char *subsysnqn)
872{
873 ssize_t len;
874
875 if (!hostnqn || !subsysnqn)
876 return -EINVAL22;
877
878 len = strlen(hostnqn) + strlen(subsysnqn) + 12;
879 if (version == 1) {
880 len += 66;
881 if (hmac == LIBNVMF_HMAC_ALG_SHA2_384)
882 len += 32;
883 } else if (version > 1) {
884 return -EINVAL22;
885 }
886 return len;
887}
888
889__shr_public__attribute__((visibility("default"))) int libnvmf_generate_tls_key_identity(
890 struct libnvme_global_ctx *ctx, const char *hostnqn,
891 const char *subsysnqn, int version, enum libnvmf_hmac_alg hmac,
892 unsigned char *configured_key, int key_len, char **ident)
893{
894 __cleanup_free__attribute__((cleanup(shr_freep))) unsigned char *psk = NULL((void*)0);
895 __cleanup_free__attribute__((cleanup(shr_freep))) char *identity = NULL((void*)0);
896 ssize_t identity_len;
897 int ret;
898
899 identity_len = nvme_identity_len(hmac, version, hostnqn, subsysnqn);
900 if (identity_len < 0)
901 return -EINVAL22;
902
903 identity = malloc(identity_len);
904 if (!identity)
905 return -ENOMEM12;
906
907 psk = malloc(key_len);
908 if (!psk)
909 return -ENOMEM12;
910
911 memset(psk, 0, key_len);
912 ret = derive_nvme_keys(ctx, hostnqn, subsysnqn, identity, version, hmac,
913 configured_key, psk, key_len, false0);
914 if (ret != key_len) {
915 if (ret < 0)
916 return ret;
917 return -ENOKEY126;
918 }
919
920 *ident = identity;
921 identity = NULL((void*)0);
922
923 return 0;
924}
925
926__shr_public__attribute__((visibility("default"))) int libnvmf_generate_tls_key_identity_compat(
927 struct libnvme_global_ctx *ctx, const char *hostnqn,
928 const char *subsysnqn, int version, enum libnvmf_hmac_alg hmac,
929 unsigned char *configured_key, int key_len, char **ident)
930{
931 __cleanup_free__attribute__((cleanup(shr_freep))) unsigned char *psk = NULL((void*)0);
932 __cleanup_free__attribute__((cleanup(shr_freep))) char *identity = NULL((void*)0);
933 ssize_t identity_len;
934 int ret;
935
936 identity_len = nvme_identity_len(hmac, version, hostnqn, subsysnqn);
937 if (identity_len < 0)
938 return -EINVAL22;
939
940 identity = malloc(identity_len);
941 if (!identity)
942 return -ENOMEM12;
943
944 psk = malloc(key_len);
945 if (!psk)
946 return -ENOMEM12;
947
948 memset(psk, 0, key_len);
949 ret = derive_nvme_keys(ctx, hostnqn, subsysnqn, identity, version, hmac,
950 configured_key, psk, key_len, true1);
951 if (ret != key_len) {
952 if (ret < 0)
953 return ret;
954 return -ENOKEY126;
955 }
956
957 *ident = identity;
958 identity = NULL((void*)0);
959
960 return 0;
961}
962
963#ifdef CONFIG_KEYUTILS
964__shr_public__attribute__((visibility("default"))) int libnvmf_lookup_keyring(
965 struct libnvme_global_ctx *ctx, const char *keyring, long *key)
966{
967 key_serial_t keyring_id;
968
969 if (!keyring)
970 keyring = NVME_TLS_DEFAULT_KEYRING".nvme";
971 keyring_id = find_key_by_type_and_desc("keyring", keyring, 0);
972 if (keyring_id < 0)
973 return -errno(*__errno_location ());
974
975 *key = keyring_id;
976 return 0;
977}
978
979__shr_public__attribute__((visibility("default"))) char *libnvmf_describe_key_serial(
980 struct libnvme_global_ctx *ctx, long key_id)
981{
982 __cleanup_free__attribute__((cleanup(shr_freep))) char *str = NULL((void*)0);
983 char *last;
984
985 if (keyctl_describe_alloc(key_id, &str) < 0)
986 return NULL((void*)0);
987
988 last = strrchr(str, ';')_Generic (0 ? (str) : (void *) 1, const void *: (const char *
) (strrchr (str, ';')), default: strrchr (str, ';'))
;
989 if (!last)
990 return NULL((void*)0);
991
992 last++;
993 if (strlen(last) == 0)
994 return NULL((void*)0);
995
996 return strdup(last);
997}
998
999__shr_public__attribute__((visibility("default"))) int libnvmf_lookup_key(
1000 struct libnvme_global_ctx *ctx, const char *type,
1001 const char *identity, long *keyp)
1002{
1003 key_serial_t key;
1004
1005 key = keyctl_search(KEY_SPEC_SESSION_KEYRING-3, type, identity, 0);
1006 if (key < 0)
1007 return -errno(*__errno_location ());
1008
1009 *keyp = key;
1010 return 0;
1011}
1012
1013__shr_public__attribute__((visibility("default"))) int libnvmf_set_keyring(
1014 struct libnvme_global_ctx *ctx, long key_id)
1015{
1016 long err;
1017
1018 if (key_id == 0) {
1019 if (libnvmf_lookup_keyring(ctx, NULL((void*)0), &key_id))
1020 return -ENOKEY126;
1021 }
1022
1023 err = keyctl_link(key_id, KEY_SPEC_SESSION_KEYRING-3);
1024 if (err < 0)
1025 return -errno(*__errno_location ());
1026 return 0;
1027}
1028
1029__shr_public__attribute__((visibility("default"))) int libnvmf_read_key(
1030 struct libnvme_global_ctx *ctx, long keyring_id, long key_id,
1031 int *len, unsigned char **key)
1032{
1033 void *buffer;
1034 int ret;
1035
1036 ret = libnvmf_set_keyring(ctx, keyring_id);
1037 if (ret < 0)
1038 return ret;
1039
1040 ret = keyctl_read_alloc(key_id, &buffer);
1041 if (ret < 0)
1042 return ret;
1043
1044 *len = ret;
1045 *key = buffer;
1046 return 0;
1047}
1048
1049__shr_public__attribute__((visibility("default"))) int libnvmf_update_key(
1050 struct libnvme_global_ctx *ctx, long keyring_id,
1051 const char *key_type, const char *identity,
1052 unsigned char *key_data, int key_len, long *keyp)
1053{
1054 long key;
1055
1056 key = keyctl_search(keyring_id, key_type, identity, 0);
1057 if (key > 0) {
1058 if (keyctl_revoke(key) < 0)
1059 return -errno(*__errno_location ());
1060 }
1061 key = add_key(key_type, identity,
1062 key_data, key_len, keyring_id);
1063 if (key < 0)
1064 return -errno(*__errno_location ());
1065
1066 *keyp = key;
1067 return 0;
1068}
1069
1070struct __scan_keys_data {
1071 struct libnvme_global_ctx *ctx;
1072 libnvmf_scan_tls_keys_cb_t cb;
1073 key_serial_t keyring;
1074 void *data;
1075};
1076
1077int __scan_keys_cb(key_serial_t parent, key_serial_t key, char *desc,
1078 int desc_len, void *data)
1079{
1080 struct __scan_keys_data *d = data;
1081 int ver, hmac, uid, gid, perm;
1082 char type, *ptr;
1083
1084 if (desc_len < 6)
1085 return 0;
1086 if (sscanf(desc, "psk;%d;%d;%08x;NVMe%01d%c%02d %*s",
1087 &uid, &gid, &perm, &ver, &type, &hmac) != 6)
1088 return 0;
1089 /* skip key type */
1090 ptr = strchr(desc, ';')_Generic (0 ? (desc) : (void *) 1, const void *: (const char *
) (strchr (desc, ';')), default: strchr (desc, ';'))
;
1091 if (!ptr)
1092 return 0;
1093 /* skip key uid */
1094 ptr = strchr(ptr + 1, ';')_Generic (0 ? (ptr + 1) : (void *) 1, const void *: (const char
*) (strchr (ptr + 1, ';')), default: strchr (ptr + 1, ';'))
;
1095 if (!ptr)
1096 return 0;
1097 /* skip key gid */
1098 ptr = strchr(ptr + 1, ';')_Generic (0 ? (ptr + 1) : (void *) 1, const void *: (const char
*) (strchr (ptr + 1, ';')), default: strchr (ptr + 1, ';'))
;
1099 if (!ptr)
1100 return 0;
1101 /* skip key permissions */
1102 ptr = strchr(ptr + 1, ';')_Generic (0 ? (ptr + 1) : (void *) 1, const void *: (const char
*) (strchr (ptr + 1, ';')), default: strchr (ptr + 1, ';'))
;
1103 if (!ptr)
1104 return 0;
1105 /* Only use the key description for the callback */
1106 (d->cb)(d->ctx, d->keyring, key, ptr + 1, strlen(ptr) - 1, d->data);
1107 return 1;
1108}
1109
1110__shr_public__attribute__((visibility("default"))) int libnvmf_scan_tls_keys(
1111 struct libnvme_global_ctx *ctx, const char *keyring,
1112 libnvmf_scan_tls_keys_cb_t cb, void *data)
1113{
1114 struct __scan_keys_data d;
1115 long keyring_id = 0;
1116 int ret;
1117
1118 ret = libnvmf_lookup_keyring(ctx, keyring, &keyring_id);
1119 if (ret)
1120 return ret;
1121
1122 if (!keyring_id)
1123 return -EINVAL22;
1124
1125 ret = libnvmf_set_keyring(ctx, keyring_id);
1126 if (ret < 0)
1127 return ret;
1128
1129 d.ctx = ctx;
1130 d.keyring = keyring_id;
1131 d.cb = cb;
1132 d.data = data;
1133 ret = recursive_key_scan(keyring_id, __scan_keys_cb, &d);
1134 return ret;
1135}
1136
1137static int __nvme_insert_tls_key(struct libnvme_global_ctx *ctx,
1138 key_serial_t keyring_id, const char *key_type,
1139 const char *hostnqn, const char *subsysnqn,
1140 int version, int hmac, unsigned char *configured_key,
1141 int key_len, bool_Bool compat, long *keyp)
1142{
1143 __cleanup_free__attribute__((cleanup(shr_freep))) unsigned char *psk = NULL((void*)0);
1144 __cleanup_free__attribute__((cleanup(shr_freep))) char *identity = NULL((void*)0);
1145 ssize_t identity_len;
1146 long key = 0;
1147 int ret;
1148
1149 identity_len = nvme_identity_len(hmac, version, hostnqn, subsysnqn);
1150 if (identity_len < 0)
5
Assuming 'identity_len' is >= 0
6
Taking false branch
1151 return identity_len;
1152
1153 identity = malloc(identity_len);
7
Memory is allocated
1154 if (!identity)
8
Assuming 'identity' is non-null
9
Taking false branch
1155 return -ENOMEM12;
1156 memset(identity, 0, identity_len);
1157
1158 psk = malloc(key_len);
1159 if (!psk)
10
Assuming 'psk' is null
11
Taking true branch
1160 return -ENOMEM12;
12
Potential leak of memory pointed to by 'identity'
1161 memset(psk, 0, key_len);
1162 ret = derive_nvme_keys(ctx, hostnqn, subsysnqn, identity, version, hmac,
1163 configured_key, psk, key_len, compat);
1164 if (ret != key_len) {
1165 if (ret < 0)
1166 return ret;
1167 return -ENOKEY126;
1168 }
1169
1170 ret = libnvmf_update_key(ctx, keyring_id, key_type, identity,
1171 psk, key_len, &key);
1172 if (ret)
1173 return ret;
1174
1175 *keyp = key;
1176 return 0;
1177}
1178
1179__shr_public__attribute__((visibility("default"))) int libnvmf_insert_tls_key_versioned(
1180 struct libnvme_global_ctx *ctx,
1181 const char *keyring, const char *key_type,
1182 const char *hostnqn, const char *subsysnqn,
1183 int version, enum libnvmf_hmac_alg hmac,
1184 unsigned char *configured_key, int key_len,
1185 long *key)
1186{
1187 long keyring_id = 0;
1188 int ret;
1189
1190 ret = libnvmf_lookup_keyring(ctx, keyring, &keyring_id);
1191 if (ret
1.1
'ret' is 0
)
2
Taking false branch
1192 return ret;
1193
1194 ret = libnvmf_set_keyring(ctx, keyring_id);
1195 if (ret
2.1
'ret' is >= 0
< 0)
3
Taking false branch
1196 return ret;
1197
1198 return __nvme_insert_tls_key(ctx, keyring_id, key_type,
4
Calling '__nvme_insert_tls_key'
1199 hostnqn, subsysnqn, version, hmac,
1200 configured_key, key_len, false0, key);
1201}
1202
1203__shr_public__attribute__((visibility("default"))) int libnvmf_insert_tls_key_compat(
1204 struct libnvme_global_ctx *ctx,
1205 const char *keyring, const char *key_type,
1206 const char *hostnqn, const char *subsysnqn,
1207 int version, enum libnvmf_hmac_alg hmac,
1208 unsigned char *configured_key, int key_len,
1209 long *key)
1210{
1211 long keyring_id = 0;
1212 int ret;
1213
1214 ret = libnvmf_lookup_keyring(ctx, keyring, &keyring_id);
1215 if (ret)
1216 return ret;
1217
1218 ret = libnvmf_set_keyring(ctx, keyring_id);
1219 if (ret < 0)
1220 return ret;
1221
1222 return __nvme_insert_tls_key(ctx, keyring_id, key_type,
1223 hostnqn, subsysnqn, version, hmac,
1224 configured_key, key_len, true1, key);
1225}
1226
1227__shr_public__attribute__((visibility("default"))) int libnvmf_revoke_tls_key(struct libnvme_global_ctx *ctx,
1228 const char *keyring, const char *key_type,
1229 const char *identity)
1230{
1231 long keyring_id = 0, key;
1232 int ret;
1233
1234 ret = libnvmf_lookup_keyring(ctx, keyring, &keyring_id);
1235 if (ret)
1236 return ret;
1237
1238 key = keyctl_search(keyring_id, key_type, identity, 0);
1239 if (key < 0)
1240 return -errno(*__errno_location ());
1241
1242 key = keyctl_revoke(key);
1243 if (key < 0)
1244 return -errno(*__errno_location ());
1245
1246 return 0;
1247}
1248
1249static int __nvme_import_tls_key(struct libnvme_global_ctx *ctx, long keyring_id,
1250 const char *hostnqn, const char *subsysnqn,
1251 const char *identity, const char *key,
1252 long *keyp)
1253{
1254 __cleanup_free__attribute__((cleanup(shr_freep))) unsigned char *key_data = NULL((void*)0);
1255 unsigned char version;
1256 enum libnvmf_hmac_alg hmac;
1257 size_t key_len;
1258 int ret;
1259
1260 ret = libnvmf_import_tls_key_versioned(ctx, key, &version,
1261 &hmac, &key_len, &key_data);
1262 if (ret)
1263 return ret;
1264
1265 if (hmac == LIBNVMF_HMAC_ALG_NONE || !identity) {
1266 /*
1267 * This is a configured PSK (hmac 0) or we don't know the
1268 * identity and so the assumption is it is also a
1269 * configured PSK. Derive a TLS PSK from it and load the
1270 * newly created key into the keystore.
1271 */
1272 return __nvme_insert_tls_key(ctx, keyring_id, "psk",
1273 hostnqn, subsysnqn, version, hmac,
1274 key_data, key_len, false0, keyp);
1275 }
1276
1277 return libnvmf_update_key(ctx, keyring_id, "psk", identity,
1278 key_data, key_len, keyp);
1279}
1280
1281int __libnvmf_import_keys_from_config(struct libnvme_host *h, struct libnvme_ctrl *c,
1282 long *keyring_id, long *key_id)
1283{
1284 const char *hostnqn = libnvme_host_get_hostnqn(h);
1285 const char *subsysnqn = libnvme_ctrl_get_subsysnqn(c);
1286 const char *keyring, *key, *identity;
1287 long kr_id = 0, id = 0;
1288 int ret;
1289
1290 if (!hostnqn || !subsysnqn) {
1291 libnvme_msg(h->ctx, LIBNVME_LOG_ERR, "Invalid NQNs (%s, %s)\n",__libnvme_msg(h->ctx, LIBNVME_LOG_ERR, ((void*)0), "Invalid NQNs (%s, %s)\n"
, hostnqn, subsysnqn)
1292 hostnqn, subsysnqn)__libnvme_msg(h->ctx, LIBNVME_LOG_ERR, ((void*)0), "Invalid NQNs (%s, %s)\n"
, hostnqn, subsysnqn)
;
1293 return -EINVAL22;
1294 }
1295
1296 /* If we don't have a key avoid all keyring operations */
1297 key = libnvme_ctrl_get_tls_key(c);
1298 if (!key)
1299 goto out;
1300
1301 if (libnvme_ctrl_get_keyring(c, &keyring, NULL((void*)0)) == 0) {
1302 ret = libnvmf_lookup_keyring(h->ctx, keyring, &kr_id);
1303 if (ret)
1304 return ret;
1305 } else
1306 kr_id = c->cfg.keyring_id;
1307
1308 /*
1309 * Fallback to the default keyring. This makes the keyring
1310 * explicit on the ctrl rather than left unset, which matters
1311 * to anything downstream that inspects this connection's
1312 * parameters.
1313 */
1314 if (!kr_id) {
1315 ret = libnvmf_lookup_keyring(h->ctx, ".nvme", &kr_id);
1316 if (ret)
1317 return ret;
1318 }
1319
1320 if (libnvmf_set_keyring(h->ctx, kr_id) < 0) {
1321 libnvme_msg(h->ctx, LIBNVME_LOG_ERR, "Failed to set keyring\n")__libnvme_msg(h->ctx, LIBNVME_LOG_ERR, ((void*)0), "Failed to set keyring\n"
)
;
1322 return -errno(*__errno_location ());
1323 }
1324
1325 identity = libnvme_ctrl_get_tls_key_identity(c);
1326 if (identity) {
1327 ret = libnvmf_lookup_key(h->ctx, "psk", identity, &id);
1328 if (ret && !(ret == -ENOKEY126 || ret == -EKEYREVOKED128)) {
1329 libnvme_msg(h->ctx, LIBNVME_LOG_ERR,__libnvme_msg(h->ctx, LIBNVME_LOG_ERR, ((void*)0), "Failed to lookup key for identity %s, error %d\n"
, identity, ret)
1330 "Failed to lookup key for identity %s, error %d\n",__libnvme_msg(h->ctx, LIBNVME_LOG_ERR, ((void*)0), "Failed to lookup key for identity %s, error %d\n"
, identity, ret)
1331 identity, ret)__libnvme_msg(h->ctx, LIBNVME_LOG_ERR, ((void*)0), "Failed to lookup key for identity %s, error %d\n"
, identity, ret)
;
1332 return ret;
1333 }
1334 }
1335
1336 if (!id) {
1337 ret = __nvme_import_tls_key(h->ctx, kr_id, hostnqn,
1338 subsysnqn, identity, key, &id);
1339 if (ret) {
1340 libnvme_msg(h->ctx, LIBNVME_LOG_ERR,__libnvme_msg(h->ctx, LIBNVME_LOG_ERR, ((void*)0), "Failed to insert TLS PSK, error %d\n"
, ret)
1341 "Failed to insert TLS PSK, error %d\n", ret)__libnvme_msg(h->ctx, LIBNVME_LOG_ERR, ((void*)0), "Failed to insert TLS PSK, error %d\n"
, ret)
;
1342 return ret;
1343 }
1344 }
1345
1346out:
1347 *keyring_id = kr_id;
1348 *key_id = id;
1349
1350 return 0;
1351}
1352#else
1353__shr_public__attribute__((visibility("default"))) int libnvmf_lookup_keyring(
1354 struct libnvme_global_ctx *ctx, const char *keyring, long *key)
1355{
1356 libnvme_msg(ctx, LIBNVME_LOG_ERR, "key operations not supported; "__libnvme_msg(ctx, LIBNVME_LOG_ERR, ((void*)0), "key operations not supported; "
"recompile with keyutils support.\n")
1357 "recompile with keyutils support.\n")__libnvme_msg(ctx, LIBNVME_LOG_ERR, ((void*)0), "key operations not supported; "
"recompile with keyutils support.\n")
;
1358 return -ENOTSUP95;
1359}
1360
1361__shr_public__attribute__((visibility("default"))) char *libnvmf_describe_key_serial(
1362 struct libnvme_global_ctx *ctx, long key_id)
1363{
1364 libnvme_msg(ctx, LIBNVME_LOG_ERR, "key operations not supported; "__libnvme_msg(ctx, LIBNVME_LOG_ERR, ((void*)0), "key operations not supported; "
"recompile with keyutils support.\n")
1365 "recompile with keyutils support.\n")__libnvme_msg(ctx, LIBNVME_LOG_ERR, ((void*)0), "key operations not supported; "
"recompile with keyutils support.\n")
;
1366 return NULL((void*)0);
1367}
1368
1369__shr_public__attribute__((visibility("default"))) int libnvmf_lookup_key(
1370 struct libnvme_global_ctx *ctx, const char *type,
1371 const char *identity, long *key)
1372{
1373 libnvme_msg(ctx, LIBNVME_LOG_ERR, "key operations not supported; "__libnvme_msg(ctx, LIBNVME_LOG_ERR, ((void*)0), "key operations not supported; "
"recompile with keyutils support.\n")
1374 "recompile with keyutils support.\n")__libnvme_msg(ctx, LIBNVME_LOG_ERR, ((void*)0), "key operations not supported; "
"recompile with keyutils support.\n")
;
1375 return -ENOTSUP95;
1376}
1377
1378__shr_public__attribute__((visibility("default"))) int libnvmf_set_keyring(
1379 struct libnvme_global_ctx *ctx, long key_id)
1380{
1381 libnvme_msg(ctx, LIBNVME_LOG_ERR, "key operations not supported; "__libnvme_msg(ctx, LIBNVME_LOG_ERR, ((void*)0), "key operations not supported; "
"recompile with keyutils support.\n")
1382 "recompile with keyutils support.\n")__libnvme_msg(ctx, LIBNVME_LOG_ERR, ((void*)0), "key operations not supported; "
"recompile with keyutils support.\n")
;
1383 return -ENOTSUP95;
1384}
1385
1386__shr_public__attribute__((visibility("default"))) int libnvmf_read_key(
1387 struct libnvme_global_ctx *ctx, long keyring_id, long key_id,
1388 int *len, unsigned char **key)
1389{
1390 libnvme_msg(ctx, LIBNVME_LOG_ERR, "key operations not supported; "__libnvme_msg(ctx, LIBNVME_LOG_ERR, ((void*)0), "key operations not supported; "
"recompile with keyutils support.\n")
1391 "recompile with keyutils support.\n")__libnvme_msg(ctx, LIBNVME_LOG_ERR, ((void*)0), "key operations not supported; "
"recompile with keyutils support.\n")
;
1392 return -ENOTSUP95;
1393}
1394
1395__shr_public__attribute__((visibility("default"))) int libnvmf_update_key(
1396 struct libnvme_global_ctx *ctx, long keyring_id,
1397 const char *key_type, const char *identity,
1398 unsigned char *key_data, int key_len, long *key)
1399{
1400 libnvme_msg(ctx, LIBNVME_LOG_ERR, "key operations not supported; "__libnvme_msg(ctx, LIBNVME_LOG_ERR, ((void*)0), "key operations not supported; "
"recompile with keyutils support.\n")
1401 "recompile with keyutils support.\n")__libnvme_msg(ctx, LIBNVME_LOG_ERR, ((void*)0), "key operations not supported; "
"recompile with keyutils support.\n")
;
1402 return -ENOTSUP95;
1403}
1404
1405__shr_public__attribute__((visibility("default"))) int libnvmf_scan_tls_keys(
1406 struct libnvme_global_ctx *ctx, const char *keyring,
1407 libnvmf_scan_tls_keys_cb_t cb, void *data)
1408{
1409 libnvme_msg(ctx, LIBNVME_LOG_ERR, "key operations not supported; "__libnvme_msg(ctx, LIBNVME_LOG_ERR, ((void*)0), "key operations not supported; "
"recompile with keyutils support.\n")
1410 "recompile with keyutils support.\n")__libnvme_msg(ctx, LIBNVME_LOG_ERR, ((void*)0), "key operations not supported; "
"recompile with keyutils support.\n")
;
1411 return -ENOTSUP95;
1412}
1413
1414__shr_public__attribute__((visibility("default"))) int libnvmf_insert_tls_key_versioned(
1415 struct libnvme_global_ctx *ctx,
1416 const char *keyring, const char *key_type,
1417 const char *hostnqn, const char *subsysnqn,
1418 int version, enum libnvmf_hmac_alg hmac,
1419 unsigned char *configured_key, int key_len,
1420 long *keyp)
1421{
1422 libnvme_msg(ctx, LIBNVME_LOG_ERR, "key operations not supported; "__libnvme_msg(ctx, LIBNVME_LOG_ERR, ((void*)0), "key operations not supported; "
"recompile with keyutils support.\n")
1423 "recompile with keyutils support.\n")__libnvme_msg(ctx, LIBNVME_LOG_ERR, ((void*)0), "key operations not supported; "
"recompile with keyutils support.\n")
;
1424 return -ENOTSUP95;
1425}
1426
1427__shr_public__attribute__((visibility("default"))) int libnvmf_insert_tls_key_compat(
1428 struct libnvme_global_ctx *ctx,
1429 const char *keyring, const char *key_type,
1430 const char *hostnqn, const char *subsysnqn,
1431 int version, enum libnvmf_hmac_alg hmac,
1432 unsigned char *configured_key, int key_len,
1433 long *keyp)
1434{
1435 libnvme_msg(ctx, LIBNVME_LOG_ERR, "key operations not supported; "__libnvme_msg(ctx, LIBNVME_LOG_ERR, ((void*)0), "key operations not supported; "
"recompile with keyutils support.\n")
1436 "recompile with keyutils support.\n")__libnvme_msg(ctx, LIBNVME_LOG_ERR, ((void*)0), "key operations not supported; "
"recompile with keyutils support.\n")
;
1437 return -ENOTSUP95;
1438}
1439
1440__shr_public__attribute__((visibility("default"))) int libnvmf_revoke_tls_key(struct libnvme_global_ctx *ctx,
1441 const char *keyring, const char *key_type,
1442 const char *identity)
1443{
1444 libnvme_msg(ctx, LIBNVME_LOG_ERR, "key operations not supported; "__libnvme_msg(ctx, LIBNVME_LOG_ERR, ((void*)0), "key operations not supported; "
"recompile with keyutils support.\n")
1445 "recompile with keyutils support.\n")__libnvme_msg(ctx, LIBNVME_LOG_ERR, ((void*)0), "key operations not supported; "
"recompile with keyutils support.\n")
;
1446 return -ENOTSUP95;
1447}
1448
1449int __libnvmf_import_keys_from_config(struct libnvme_host *h, struct libnvme_ctrl *c,
1450 long *keyring_id, long *key_id)
1451{
1452 *keyring_id = 0;
1453 *key_id = 0;
1454
1455 return 0;
1456}
1457#endif
1458
1459__shr_public__attribute__((visibility("default"))) int libnvmf_insert_tls_key(struct libnvme_global_ctx *ctx,
1460 const char *keyring, const char *key_type,
1461 const char *hostnqn, const char *subsysnqn,
1462 enum libnvmf_hmac_alg hmac,
1463 unsigned char *configured_key, int key_len, long *key)
1464{
1465 return libnvmf_insert_tls_key_versioned(ctx, keyring, key_type,
1
Calling 'libnvmf_insert_tls_key_versioned'
1466 hostnqn, subsysnqn, 0, hmac,
1467 configured_key, key_len, key);
1468}
1469
1470/*
1471 * PSK Interchange Format
1472 * NVMeTLSkey-<v>:<xx>:<s>:
1473 *
1474 * x: version as one ASCII char
1475 * yy: hmac encoded as two ASCII chars
1476 * 00: no transform ('configured PSK')
1477 * 01: SHA-256
1478 * 02: SHA-384
1479 * s: 32 or 48 bytes binary followed by a CRC-32 of the configured PSK
1480 * (4 bytes) encoded as base64
1481 */
1482__shr_public__attribute__((visibility("default"))) int libnvmf_export_tls_key_versioned(
1483 struct libnvme_global_ctx *ctx, unsigned char version,
1484 enum libnvmf_hmac_alg hmac, const unsigned char *key_data,
1485 size_t key_len, char **encoded_keyp)
1486{
1487 unsigned int raw_len, encoded_len, len;
1488 unsigned long crc = shr_crc32(0L, NULL((void*)0), 0);
1489 unsigned char raw_secret[52];
1490 char *encoded_key;
1491
1492 switch (hmac) {
1493 case LIBNVMF_HMAC_ALG_NONE:
1494 if (key_len != 32 && key_len != 48)
1495 return -EINVAL22;
1496 break;
1497 case LIBNVMF_HMAC_ALG_SHA2_256:
1498 if (key_len != 32)
1499 return -EINVAL22;
1500 break;
1501 case LIBNVMF_HMAC_ALG_SHA2_384:
1502 if (key_len != 48)
1503 return -EINVAL22;
1504 break;
1505 default:
1506 return -EINVAL22;
1507 }
1508 raw_len = key_len;
1509
1510 memcpy(raw_secret, key_data, raw_len);
1511 crc = shr_crc32(crc, raw_secret, raw_len);
1512 raw_secret[raw_len++] = crc & 0xff;
1513 raw_secret[raw_len++] = (crc >> 8) & 0xff;
1514 raw_secret[raw_len++] = (crc >> 16) & 0xff;
1515 raw_secret[raw_len++] = (crc >> 24) & 0xff;
1516
1517 encoded_len = (raw_len * 2) + 20;
1518 encoded_key = malloc(encoded_len);
1519 if (!encoded_key)
1520 return -ENOMEM12;
1521
1522 memset(encoded_key, 0, encoded_len);
1523 len = sprintf(encoded_key, "NVMeTLSkey-%x:%02x:", version, hmac);
1524 len += shr_base64_encode(raw_secret, raw_len, encoded_key + len);
1525 encoded_key[len++] = ':';
1526 encoded_key[len++] = '\0';
1527
1528 *encoded_keyp = encoded_key;
1529 return 0;
1530}
1531
1532__shr_public__attribute__((visibility("default"))) int libnvmf_export_tls_key(struct libnvme_global_ctx *ctx,
1533 const unsigned char *key_data, int key_len, char **encoded_keyp)
1534{
1535 enum libnvmf_hmac_alg hmac;
1536
1537 if (key_len == 32)
1538 hmac = LIBNVMF_HMAC_ALG_SHA2_256;
1539 else
1540 hmac = LIBNVMF_HMAC_ALG_SHA2_384;
1541
1542 return libnvmf_export_tls_key_versioned(ctx, 1, hmac, key_data,
1543 key_len, encoded_keyp);
1544}
1545
1546__shr_public__attribute__((visibility("default"))) int libnvmf_import_tls_key_versioned(
1547 struct libnvme_global_ctx *ctx, const char *encoded_key,
1548 unsigned char *version, enum libnvmf_hmac_alg *hmac,
1549 size_t *key_len, unsigned char **keyp)
1550{
1551 unsigned char decoded_key[128], *key_data;
1552 unsigned int crc = shr_crc32(0L, NULL((void*)0), 0);
1553 unsigned int key_crc;
1554 int err, _version, _hmac, decoded_len;
1555 size_t len;
1556
1557 if (sscanf(encoded_key, "NVMeTLSkey-%d:%02x:*s",
1558 &_version, &_hmac) != 2)
1559 return -EINVAL22;
1560
1561 if (_version != 1)
1562 return -EINVAL22;
1563
1564 *version = _version;
1565
1566 len = strlen(encoded_key);
1567 switch (_hmac) {
1568 case LIBNVMF_HMAC_ALG_NONE:
1569 if (len != 65 && len != 89)
1570 return -EINVAL22;
1571 break;
1572 case LIBNVMF_HMAC_ALG_SHA2_256:
1573 if (len != 65)
1574 return -EINVAL22;
1575 break;
1576 case LIBNVMF_HMAC_ALG_SHA2_384:
1577 if (len != 89)
1578 return -EINVAL22;
1579 break;
1580 default:
1581 return -EINVAL22;
1582 }
1583 *hmac = _hmac;
1584
1585 err = shr_base64_decode(encoded_key + 16, len - 17, decoded_key);
1586 if (err < 0)
1587 return -ENOKEY126;
1588
1589 decoded_len = err;
1590 decoded_len -= 4;
1591 if (decoded_len != 32 && decoded_len != 48)
1592 return -ENOKEY126;
1593
1594 crc = shr_crc32(crc, decoded_key, decoded_len);
1595 key_crc = ((uint32_t)decoded_key[decoded_len]) |
1596 ((uint32_t)decoded_key[decoded_len + 1] << 8) |
1597 ((uint32_t)decoded_key[decoded_len + 2] << 16) |
1598 ((uint32_t)decoded_key[decoded_len + 3] << 24);
1599 if (key_crc != crc) {
1600 libnvme_msg(ctx, LIBNVME_LOG_ERR, "CRC mismatch (key %08x, crc %08x)",__libnvme_msg(ctx, LIBNVME_LOG_ERR, ((void*)0), "CRC mismatch (key %08x, crc %08x)"
, key_crc, crc)
1601 key_crc, crc)__libnvme_msg(ctx, LIBNVME_LOG_ERR, ((void*)0), "CRC mismatch (key %08x, crc %08x)"
, key_crc, crc)
;
1602 return -ENOKEY126;
1603 }
1604
1605 key_data = malloc(decoded_len);
1606 if (!key_data)
1607 return -ENOMEM12;
1608 memcpy(key_data, decoded_key, decoded_len);
1609
1610 *key_len = decoded_len;
1611 *keyp = key_data;
1612 return 0;
1613}
1614
1615__shr_public__attribute__((visibility("default"))) int libnvmf_import_tls_key(
1616 struct libnvme_global_ctx *ctx, const char *encoded_key,
1617 int *key_len, enum libnvmf_hmac_alg *hmac, unsigned char **keyp)
1618{
1619 unsigned char version;
1620 enum libnvmf_hmac_alg _hmac;
1621 unsigned char *psk;
1622 size_t len;
1623 int ret;
1624
1625 ret = libnvmf_import_tls_key_versioned(ctx, encoded_key, &version,
1626 &_hmac, &len, &psk);
1627 if (ret)
1628 return ret;
1629
1630 *hmac = _hmac;
1631 *key_len = len;
1632 *keyp = psk;
1633 return 0;
1634}
1635