Bug Summary

File:.build-ci/../libnvme/src/nvme/crypto.c
Warning:line 1186, column 8
2nd function call argument is an uninitialized value

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