1 // SPDX-License-Identifier: GPL-2.0
3 * NVMe over Fabrics DH-HMAC-CHAP authentication.
4 * Copyright (c) 2020 Hannes Reinecke, SUSE Software Solutions.
7 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
8 #include <linux/module.h>
9 #include <linux/init.h>
10 #include <linux/slab.h>
11 #include <linux/err.h>
12 #include <crypto/hash.h>
13 #include <linux/crc32.h>
14 #include <linux/base64.h>
15 #include <linux/ctype.h>
16 #include <linux/random.h>
17 #include <linux/nvme-auth.h>
18 #include <linux/unaligned.h>
22 int nvmet_auth_set_key(struct nvmet_host
*host
, const char *secret
,
25 unsigned char key_hash
;
28 if (!strlen(secret
)) {
30 kfree(host
->dhchap_ctrl_secret
);
31 host
->dhchap_ctrl_secret
= NULL
;
32 host
->dhchap_ctrl_key_hash
= 0;
34 kfree(host
->dhchap_secret
);
35 host
->dhchap_secret
= NULL
;
36 host
->dhchap_key_hash
= 0;
40 if (sscanf(secret
, "DHHC-1:%hhd:%*s", &key_hash
) != 1)
43 pr_warn("Invalid DH-HMAC-CHAP hash id %d\n",
48 /* Validate selected hash algorithm */
49 const char *hmac
= nvme_auth_hmac_name(key_hash
);
51 if (!crypto_has_shash(hmac
, 0, 0)) {
52 pr_err("DH-HMAC-CHAP hash %s unsupported\n", hmac
);
56 dhchap_secret
= kstrdup(secret
, GFP_KERNEL
);
59 down_write(&nvmet_config_sem
);
61 kfree(host
->dhchap_ctrl_secret
);
62 host
->dhchap_ctrl_secret
= strim(dhchap_secret
);
63 host
->dhchap_ctrl_key_hash
= key_hash
;
65 kfree(host
->dhchap_secret
);
66 host
->dhchap_secret
= strim(dhchap_secret
);
67 host
->dhchap_key_hash
= key_hash
;
69 up_write(&nvmet_config_sem
);
73 int nvmet_setup_dhgroup(struct nvmet_ctrl
*ctrl
, u8 dhgroup_id
)
75 const char *dhgroup_kpp
;
78 pr_debug("%s: ctrl %d selecting dhgroup %d\n",
79 __func__
, ctrl
->cntlid
, dhgroup_id
);
82 if (ctrl
->dh_gid
== dhgroup_id
) {
83 pr_debug("%s: ctrl %d reuse existing DH group %d\n",
84 __func__
, ctrl
->cntlid
, dhgroup_id
);
87 crypto_free_kpp(ctrl
->dh_tfm
);
92 if (dhgroup_id
== NVME_AUTH_DHGROUP_NULL
)
95 dhgroup_kpp
= nvme_auth_dhgroup_kpp(dhgroup_id
);
97 pr_debug("%s: ctrl %d invalid DH group %d\n",
98 __func__
, ctrl
->cntlid
, dhgroup_id
);
101 ctrl
->dh_tfm
= crypto_alloc_kpp(dhgroup_kpp
, 0, 0);
102 if (IS_ERR(ctrl
->dh_tfm
)) {
103 pr_debug("%s: ctrl %d failed to setup DH group %d, err %ld\n",
104 __func__
, ctrl
->cntlid
, dhgroup_id
,
105 PTR_ERR(ctrl
->dh_tfm
));
106 ret
= PTR_ERR(ctrl
->dh_tfm
);
110 ctrl
->dh_gid
= dhgroup_id
;
111 pr_debug("%s: ctrl %d setup DH group %d\n",
112 __func__
, ctrl
->cntlid
, ctrl
->dh_gid
);
113 ret
= nvme_auth_gen_privkey(ctrl
->dh_tfm
, ctrl
->dh_gid
);
115 pr_debug("%s: ctrl %d failed to generate private key, err %d\n",
116 __func__
, ctrl
->cntlid
, ret
);
117 kfree_sensitive(ctrl
->dh_key
);
121 ctrl
->dh_keysize
= crypto_kpp_maxsize(ctrl
->dh_tfm
);
122 kfree_sensitive(ctrl
->dh_key
);
123 ctrl
->dh_key
= kzalloc(ctrl
->dh_keysize
, GFP_KERNEL
);
125 pr_warn("ctrl %d failed to allocate public key\n",
129 ret
= nvme_auth_gen_pubkey(ctrl
->dh_tfm
, ctrl
->dh_key
,
132 pr_warn("ctrl %d failed to generate public key\n",
142 u8
nvmet_setup_auth(struct nvmet_ctrl
*ctrl
)
145 struct nvmet_host_link
*p
;
146 struct nvmet_host
*host
= NULL
;
148 down_read(&nvmet_config_sem
);
149 if (nvmet_is_disc_subsys(ctrl
->subsys
))
152 if (ctrl
->subsys
->allow_any_host
)
155 list_for_each_entry(p
, &ctrl
->subsys
->hosts
, entry
) {
156 pr_debug("check %s\n", nvmet_host_name(p
->host
));
157 if (strcmp(nvmet_host_name(p
->host
), ctrl
->hostnqn
))
163 pr_debug("host %s not found\n", ctrl
->hostnqn
);
164 ret
= NVME_AUTH_DHCHAP_FAILURE_FAILED
;
168 ret
= nvmet_setup_dhgroup(ctrl
, host
->dhchap_dhgroup_id
);
170 pr_warn("Failed to setup DH group");
171 ret
= NVME_AUTH_DHCHAP_FAILURE_DHGROUP_UNUSABLE
;
175 if (!host
->dhchap_secret
) {
176 pr_debug("No authentication provided\n");
180 if (host
->dhchap_hash_id
== ctrl
->shash_id
) {
181 pr_debug("Re-use existing hash ID %d\n",
184 ctrl
->shash_id
= host
->dhchap_hash_id
;
187 /* Skip the 'DHHC-1:XX:' prefix */
188 nvme_auth_free_key(ctrl
->host_key
);
189 ctrl
->host_key
= nvme_auth_extract_key(host
->dhchap_secret
+ 10,
190 host
->dhchap_key_hash
);
191 if (IS_ERR(ctrl
->host_key
)) {
192 ret
= NVME_AUTH_DHCHAP_FAILURE_NOT_USABLE
;
193 ctrl
->host_key
= NULL
;
196 pr_debug("%s: using hash %s key %*ph\n", __func__
,
197 ctrl
->host_key
->hash
> 0 ?
198 nvme_auth_hmac_name(ctrl
->host_key
->hash
) : "none",
199 (int)ctrl
->host_key
->len
, ctrl
->host_key
->key
);
201 nvme_auth_free_key(ctrl
->ctrl_key
);
202 if (!host
->dhchap_ctrl_secret
) {
203 ctrl
->ctrl_key
= NULL
;
207 ctrl
->ctrl_key
= nvme_auth_extract_key(host
->dhchap_ctrl_secret
+ 10,
208 host
->dhchap_ctrl_key_hash
);
209 if (IS_ERR(ctrl
->ctrl_key
)) {
210 ret
= NVME_AUTH_DHCHAP_FAILURE_NOT_USABLE
;
211 ctrl
->ctrl_key
= NULL
;
214 pr_debug("%s: using ctrl hash %s key %*ph\n", __func__
,
215 ctrl
->ctrl_key
->hash
> 0 ?
216 nvme_auth_hmac_name(ctrl
->ctrl_key
->hash
) : "none",
217 (int)ctrl
->ctrl_key
->len
, ctrl
->ctrl_key
->key
);
221 if (ctrl
->host_key
) {
222 nvme_auth_free_key(ctrl
->host_key
);
223 ctrl
->host_key
= NULL
;
228 up_read(&nvmet_config_sem
);
233 void nvmet_auth_sq_free(struct nvmet_sq
*sq
)
235 cancel_delayed_work(&sq
->auth_expired_work
);
236 kfree(sq
->dhchap_c1
);
237 sq
->dhchap_c1
= NULL
;
238 kfree(sq
->dhchap_c2
);
239 sq
->dhchap_c2
= NULL
;
240 kfree(sq
->dhchap_skey
);
241 sq
->dhchap_skey
= NULL
;
244 void nvmet_destroy_auth(struct nvmet_ctrl
*ctrl
)
249 crypto_free_kpp(ctrl
->dh_tfm
);
253 kfree_sensitive(ctrl
->dh_key
);
256 if (ctrl
->host_key
) {
257 nvme_auth_free_key(ctrl
->host_key
);
258 ctrl
->host_key
= NULL
;
260 if (ctrl
->ctrl_key
) {
261 nvme_auth_free_key(ctrl
->ctrl_key
);
262 ctrl
->ctrl_key
= NULL
;
266 bool nvmet_check_auth_status(struct nvmet_req
*req
)
268 if (req
->sq
->ctrl
->host_key
&&
269 !req
->sq
->authenticated
)
274 int nvmet_auth_host_hash(struct nvmet_req
*req
, u8
*response
,
275 unsigned int shash_len
)
277 struct crypto_shash
*shash_tfm
;
278 struct shash_desc
*shash
;
279 struct nvmet_ctrl
*ctrl
= req
->sq
->ctrl
;
280 const char *hash_name
;
281 u8
*challenge
= req
->sq
->dhchap_c1
;
282 struct nvme_dhchap_key
*transformed_key
;
286 hash_name
= nvme_auth_hmac_name(ctrl
->shash_id
);
288 pr_warn("Hash ID %d invalid\n", ctrl
->shash_id
);
292 shash_tfm
= crypto_alloc_shash(hash_name
, 0, 0);
293 if (IS_ERR(shash_tfm
)) {
294 pr_err("failed to allocate shash %s\n", hash_name
);
295 return PTR_ERR(shash_tfm
);
298 if (shash_len
!= crypto_shash_digestsize(shash_tfm
)) {
299 pr_err("%s: hash len mismatch (len %d digest %d)\n",
301 crypto_shash_digestsize(shash_tfm
));
306 transformed_key
= nvme_auth_transform_key(ctrl
->host_key
,
308 if (IS_ERR(transformed_key
)) {
309 ret
= PTR_ERR(transformed_key
);
313 ret
= crypto_shash_setkey(shash_tfm
, transformed_key
->key
,
314 transformed_key
->len
);
316 goto out_free_response
;
318 if (ctrl
->dh_gid
!= NVME_AUTH_DHGROUP_NULL
) {
319 challenge
= kmalloc(shash_len
, GFP_KERNEL
);
322 goto out_free_response
;
324 ret
= nvme_auth_augmented_challenge(ctrl
->shash_id
,
325 req
->sq
->dhchap_skey
,
326 req
->sq
->dhchap_skey_len
,
328 challenge
, shash_len
);
330 goto out_free_challenge
;
333 pr_debug("ctrl %d qid %d host response seq %u transaction %d\n",
334 ctrl
->cntlid
, req
->sq
->qid
, req
->sq
->dhchap_s1
,
335 req
->sq
->dhchap_tid
);
337 shash
= kzalloc(sizeof(*shash
) + crypto_shash_descsize(shash_tfm
),
341 goto out_free_challenge
;
343 shash
->tfm
= shash_tfm
;
344 ret
= crypto_shash_init(shash
);
347 ret
= crypto_shash_update(shash
, challenge
, shash_len
);
350 put_unaligned_le32(req
->sq
->dhchap_s1
, buf
);
351 ret
= crypto_shash_update(shash
, buf
, 4);
354 put_unaligned_le16(req
->sq
->dhchap_tid
, buf
);
355 ret
= crypto_shash_update(shash
, buf
, 2);
359 ret
= crypto_shash_update(shash
, buf
, 1);
362 ret
= crypto_shash_update(shash
, "HostHost", 8);
365 ret
= crypto_shash_update(shash
, ctrl
->hostnqn
, strlen(ctrl
->hostnqn
));
368 ret
= crypto_shash_update(shash
, buf
, 1);
371 ret
= crypto_shash_update(shash
, ctrl
->subsysnqn
,
372 strlen(ctrl
->subsysnqn
));
375 ret
= crypto_shash_final(shash
, response
);
379 if (challenge
!= req
->sq
->dhchap_c1
)
382 nvme_auth_free_key(transformed_key
);
384 crypto_free_shash(shash_tfm
);
388 int nvmet_auth_ctrl_hash(struct nvmet_req
*req
, u8
*response
,
389 unsigned int shash_len
)
391 struct crypto_shash
*shash_tfm
;
392 struct shash_desc
*shash
;
393 struct nvmet_ctrl
*ctrl
= req
->sq
->ctrl
;
394 const char *hash_name
;
395 u8
*challenge
= req
->sq
->dhchap_c2
;
396 struct nvme_dhchap_key
*transformed_key
;
400 hash_name
= nvme_auth_hmac_name(ctrl
->shash_id
);
402 pr_warn("Hash ID %d invalid\n", ctrl
->shash_id
);
406 shash_tfm
= crypto_alloc_shash(hash_name
, 0, 0);
407 if (IS_ERR(shash_tfm
)) {
408 pr_err("failed to allocate shash %s\n", hash_name
);
409 return PTR_ERR(shash_tfm
);
412 if (shash_len
!= crypto_shash_digestsize(shash_tfm
)) {
413 pr_debug("%s: hash len mismatch (len %d digest %d)\n",
415 crypto_shash_digestsize(shash_tfm
));
420 transformed_key
= nvme_auth_transform_key(ctrl
->ctrl_key
,
422 if (IS_ERR(transformed_key
)) {
423 ret
= PTR_ERR(transformed_key
);
427 ret
= crypto_shash_setkey(shash_tfm
, transformed_key
->key
,
428 transformed_key
->len
);
430 goto out_free_response
;
432 if (ctrl
->dh_gid
!= NVME_AUTH_DHGROUP_NULL
) {
433 challenge
= kmalloc(shash_len
, GFP_KERNEL
);
436 goto out_free_response
;
438 ret
= nvme_auth_augmented_challenge(ctrl
->shash_id
,
439 req
->sq
->dhchap_skey
,
440 req
->sq
->dhchap_skey_len
,
442 challenge
, shash_len
);
444 goto out_free_challenge
;
447 shash
= kzalloc(sizeof(*shash
) + crypto_shash_descsize(shash_tfm
),
451 goto out_free_challenge
;
453 shash
->tfm
= shash_tfm
;
455 ret
= crypto_shash_init(shash
);
458 ret
= crypto_shash_update(shash
, challenge
, shash_len
);
461 put_unaligned_le32(req
->sq
->dhchap_s2
, buf
);
462 ret
= crypto_shash_update(shash
, buf
, 4);
465 put_unaligned_le16(req
->sq
->dhchap_tid
, buf
);
466 ret
= crypto_shash_update(shash
, buf
, 2);
470 ret
= crypto_shash_update(shash
, buf
, 1);
473 ret
= crypto_shash_update(shash
, "Controller", 10);
476 ret
= crypto_shash_update(shash
, ctrl
->subsysnqn
,
477 strlen(ctrl
->subsysnqn
));
480 ret
= crypto_shash_update(shash
, buf
, 1);
483 ret
= crypto_shash_update(shash
, ctrl
->hostnqn
, strlen(ctrl
->hostnqn
));
486 ret
= crypto_shash_final(shash
, response
);
490 if (challenge
!= req
->sq
->dhchap_c2
)
493 nvme_auth_free_key(transformed_key
);
495 crypto_free_shash(shash_tfm
);
499 int nvmet_auth_ctrl_exponential(struct nvmet_req
*req
,
500 u8
*buf
, int buf_size
)
502 struct nvmet_ctrl
*ctrl
= req
->sq
->ctrl
;
506 pr_warn("ctrl %d no DH public key!\n", ctrl
->cntlid
);
509 if (buf_size
!= ctrl
->dh_keysize
) {
510 pr_warn("ctrl %d DH public key size mismatch, need %zu is %d\n",
511 ctrl
->cntlid
, ctrl
->dh_keysize
, buf_size
);
514 memcpy(buf
, ctrl
->dh_key
, buf_size
);
515 pr_debug("%s: ctrl %d public key %*ph\n", __func__
,
516 ctrl
->cntlid
, (int)buf_size
, buf
);
522 int nvmet_auth_ctrl_sesskey(struct nvmet_req
*req
,
523 u8
*pkey
, int pkey_size
)
525 struct nvmet_ctrl
*ctrl
= req
->sq
->ctrl
;
528 req
->sq
->dhchap_skey_len
= ctrl
->dh_keysize
;
529 req
->sq
->dhchap_skey
= kzalloc(req
->sq
->dhchap_skey_len
, GFP_KERNEL
);
530 if (!req
->sq
->dhchap_skey
)
532 ret
= nvme_auth_gen_shared_secret(ctrl
->dh_tfm
,
534 req
->sq
->dhchap_skey
,
535 req
->sq
->dhchap_skey_len
);
537 pr_debug("failed to compute shared secret, err %d\n", ret
);
539 pr_debug("%s: shared secret %*ph\n", __func__
,
540 (int)req
->sq
->dhchap_skey_len
,
541 req
->sq
->dhchap_skey
);