1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * NVMe over Fabrics DH-HMAC-CHAP authentication.
4 * Copyright (c) 2020 Hannes Reinecke, SUSE Software Solutions.
5 * All rights reserved.
6 */
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/nvme-keyring.h>
19 #include <linux/unaligned.h>
20
21 #include "nvmet.h"
22
nvmet_auth_set_key(struct nvmet_host * host,const char * secret,bool set_ctrl)23 int nvmet_auth_set_key(struct nvmet_host *host, const char *secret,
24 bool set_ctrl)
25 {
26 unsigned char key_hash;
27 char *dhchap_secret;
28
29 if (!strlen(secret)) {
30 if (set_ctrl) {
31 kfree(host->dhchap_ctrl_secret);
32 host->dhchap_ctrl_secret = NULL;
33 host->dhchap_ctrl_key_hash = 0;
34 } else {
35 kfree(host->dhchap_secret);
36 host->dhchap_secret = NULL;
37 host->dhchap_key_hash = 0;
38 }
39 return 0;
40 }
41 if (sscanf(secret, "DHHC-1:%hhd:%*s", &key_hash) != 1)
42 return -EINVAL;
43 if (key_hash > 3) {
44 pr_warn("Invalid DH-HMAC-CHAP hash id %d\n",
45 key_hash);
46 return -EINVAL;
47 }
48 if (key_hash > 0) {
49 /* Validate selected hash algorithm */
50 const char *hmac = nvme_auth_hmac_name(key_hash);
51
52 if (!crypto_has_shash(hmac, 0, 0)) {
53 pr_err("DH-HMAC-CHAP hash %s unsupported\n", hmac);
54 return -ENOTSUPP;
55 }
56 }
57 dhchap_secret = kstrdup(secret, GFP_KERNEL);
58 if (!dhchap_secret)
59 return -ENOMEM;
60 down_write(&nvmet_config_sem);
61 if (set_ctrl) {
62 kfree(host->dhchap_ctrl_secret);
63 host->dhchap_ctrl_secret = strim(dhchap_secret);
64 host->dhchap_ctrl_key_hash = key_hash;
65 } else {
66 kfree(host->dhchap_secret);
67 host->dhchap_secret = strim(dhchap_secret);
68 host->dhchap_key_hash = key_hash;
69 }
70 up_write(&nvmet_config_sem);
71 return 0;
72 }
73
nvmet_setup_dhgroup(struct nvmet_ctrl * ctrl,u8 dhgroup_id)74 int nvmet_setup_dhgroup(struct nvmet_ctrl *ctrl, u8 dhgroup_id)
75 {
76 const char *dhgroup_kpp;
77 int ret = 0;
78
79 pr_debug("%s: ctrl %d selecting dhgroup %d\n",
80 __func__, ctrl->cntlid, dhgroup_id);
81
82 if (ctrl->dh_tfm) {
83 if (ctrl->dh_gid == dhgroup_id) {
84 pr_debug("%s: ctrl %d reuse existing DH group %d\n",
85 __func__, ctrl->cntlid, dhgroup_id);
86 return 0;
87 }
88 crypto_free_kpp(ctrl->dh_tfm);
89 ctrl->dh_tfm = NULL;
90 ctrl->dh_gid = 0;
91 }
92
93 if (dhgroup_id == NVME_AUTH_DHGROUP_NULL)
94 return 0;
95
96 dhgroup_kpp = nvme_auth_dhgroup_kpp(dhgroup_id);
97 if (!dhgroup_kpp) {
98 pr_debug("%s: ctrl %d invalid DH group %d\n",
99 __func__, ctrl->cntlid, dhgroup_id);
100 return -EINVAL;
101 }
102 ctrl->dh_tfm = crypto_alloc_kpp(dhgroup_kpp, 0, 0);
103 if (IS_ERR(ctrl->dh_tfm)) {
104 pr_debug("%s: ctrl %d failed to setup DH group %d, err %ld\n",
105 __func__, ctrl->cntlid, dhgroup_id,
106 PTR_ERR(ctrl->dh_tfm));
107 ret = PTR_ERR(ctrl->dh_tfm);
108 ctrl->dh_tfm = NULL;
109 ctrl->dh_gid = 0;
110 } else {
111 ctrl->dh_gid = dhgroup_id;
112 pr_debug("%s: ctrl %d setup DH group %d\n",
113 __func__, ctrl->cntlid, ctrl->dh_gid);
114 ret = nvme_auth_gen_privkey(ctrl->dh_tfm, ctrl->dh_gid);
115 if (ret < 0) {
116 pr_debug("%s: ctrl %d failed to generate private key, err %d\n",
117 __func__, ctrl->cntlid, ret);
118 kfree_sensitive(ctrl->dh_key);
119 ctrl->dh_key = NULL;
120 return ret;
121 }
122 ctrl->dh_keysize = crypto_kpp_maxsize(ctrl->dh_tfm);
123 kfree_sensitive(ctrl->dh_key);
124 ctrl->dh_key = kzalloc(ctrl->dh_keysize, GFP_KERNEL);
125 if (!ctrl->dh_key) {
126 pr_warn("ctrl %d failed to allocate public key\n",
127 ctrl->cntlid);
128 return -ENOMEM;
129 }
130 ret = nvme_auth_gen_pubkey(ctrl->dh_tfm, ctrl->dh_key,
131 ctrl->dh_keysize);
132 if (ret < 0) {
133 pr_warn("ctrl %d failed to generate public key\n",
134 ctrl->cntlid);
135 kfree(ctrl->dh_key);
136 ctrl->dh_key = NULL;
137 }
138 }
139
140 return ret;
141 }
142
nvmet_setup_auth(struct nvmet_ctrl * ctrl,struct nvmet_sq * sq)143 u8 nvmet_setup_auth(struct nvmet_ctrl *ctrl, struct nvmet_sq *sq)
144 {
145 int ret = 0;
146 struct nvmet_host_link *p;
147 struct nvmet_host *host = NULL;
148
149 down_read(&nvmet_config_sem);
150 if (nvmet_is_disc_subsys(ctrl->subsys))
151 goto out_unlock;
152
153 if (ctrl->subsys->allow_any_host)
154 goto out_unlock;
155
156 list_for_each_entry(p, &ctrl->subsys->hosts, entry) {
157 pr_debug("check %s\n", nvmet_host_name(p->host));
158 if (strcmp(nvmet_host_name(p->host), ctrl->hostnqn))
159 continue;
160 host = p->host;
161 break;
162 }
163 if (!host) {
164 pr_debug("host %s not found\n", ctrl->hostnqn);
165 ret = NVME_AUTH_DHCHAP_FAILURE_FAILED;
166 goto out_unlock;
167 }
168
169 if (nvmet_queue_tls_keyid(sq)) {
170 pr_debug("host %s tls enabled\n", ctrl->hostnqn);
171 goto out_unlock;
172 }
173
174 ret = nvmet_setup_dhgroup(ctrl, host->dhchap_dhgroup_id);
175 if (ret < 0) {
176 pr_warn("Failed to setup DH group");
177 ret = NVME_AUTH_DHCHAP_FAILURE_DHGROUP_UNUSABLE;
178 goto out_unlock;
179 }
180
181 if (!host->dhchap_secret) {
182 pr_debug("No authentication provided\n");
183 goto out_unlock;
184 }
185
186 if (host->dhchap_hash_id == ctrl->shash_id) {
187 pr_debug("Re-use existing hash ID %d\n",
188 ctrl->shash_id);
189 } else {
190 ctrl->shash_id = host->dhchap_hash_id;
191 }
192
193 /* Skip the 'DHHC-1:XX:' prefix */
194 nvme_auth_free_key(ctrl->host_key);
195 ctrl->host_key = nvme_auth_extract_key(host->dhchap_secret + 10,
196 host->dhchap_key_hash);
197 if (IS_ERR(ctrl->host_key)) {
198 ret = NVME_AUTH_DHCHAP_FAILURE_NOT_USABLE;
199 ctrl->host_key = NULL;
200 goto out_free_hash;
201 }
202 pr_debug("%s: using hash %s key %*ph\n", __func__,
203 ctrl->host_key->hash > 0 ?
204 nvme_auth_hmac_name(ctrl->host_key->hash) : "none",
205 (int)ctrl->host_key->len, ctrl->host_key->key);
206
207 nvme_auth_free_key(ctrl->ctrl_key);
208 if (!host->dhchap_ctrl_secret) {
209 ctrl->ctrl_key = NULL;
210 goto out_unlock;
211 }
212
213 ctrl->ctrl_key = nvme_auth_extract_key(host->dhchap_ctrl_secret + 10,
214 host->dhchap_ctrl_key_hash);
215 if (IS_ERR(ctrl->ctrl_key)) {
216 ret = NVME_AUTH_DHCHAP_FAILURE_NOT_USABLE;
217 ctrl->ctrl_key = NULL;
218 goto out_free_hash;
219 }
220 pr_debug("%s: using ctrl hash %s key %*ph\n", __func__,
221 ctrl->ctrl_key->hash > 0 ?
222 nvme_auth_hmac_name(ctrl->ctrl_key->hash) : "none",
223 (int)ctrl->ctrl_key->len, ctrl->ctrl_key->key);
224
225 out_free_hash:
226 if (ret) {
227 if (ctrl->host_key) {
228 nvme_auth_free_key(ctrl->host_key);
229 ctrl->host_key = NULL;
230 }
231 ctrl->shash_id = 0;
232 }
233 out_unlock:
234 up_read(&nvmet_config_sem);
235
236 return ret;
237 }
238
nvmet_auth_sq_free(struct nvmet_sq * sq)239 void nvmet_auth_sq_free(struct nvmet_sq *sq)
240 {
241 cancel_delayed_work(&sq->auth_expired_work);
242 #ifdef CONFIG_NVME_TARGET_TCP_TLS
243 sq->tls_key = NULL;
244 #endif
245 kfree(sq->dhchap_c1);
246 sq->dhchap_c1 = NULL;
247 kfree(sq->dhchap_c2);
248 sq->dhchap_c2 = NULL;
249 kfree(sq->dhchap_skey);
250 sq->dhchap_skey = NULL;
251 }
252
nvmet_destroy_auth(struct nvmet_ctrl * ctrl)253 void nvmet_destroy_auth(struct nvmet_ctrl *ctrl)
254 {
255 ctrl->shash_id = 0;
256
257 if (ctrl->dh_tfm) {
258 crypto_free_kpp(ctrl->dh_tfm);
259 ctrl->dh_tfm = NULL;
260 ctrl->dh_gid = 0;
261 }
262 kfree_sensitive(ctrl->dh_key);
263 ctrl->dh_key = NULL;
264
265 if (ctrl->host_key) {
266 nvme_auth_free_key(ctrl->host_key);
267 ctrl->host_key = NULL;
268 }
269 if (ctrl->ctrl_key) {
270 nvme_auth_free_key(ctrl->ctrl_key);
271 ctrl->ctrl_key = NULL;
272 }
273 #ifdef CONFIG_NVME_TARGET_TCP_TLS
274 if (ctrl->tls_key) {
275 key_put(ctrl->tls_key);
276 ctrl->tls_key = NULL;
277 }
278 #endif
279 }
280
nvmet_check_auth_status(struct nvmet_req * req)281 bool nvmet_check_auth_status(struct nvmet_req *req)
282 {
283 if (req->sq->ctrl->host_key) {
284 if (req->sq->qid > 0)
285 return true;
286 if (!req->sq->authenticated)
287 return false;
288 }
289 return true;
290 }
291
nvmet_auth_host_hash(struct nvmet_req * req,u8 * response,unsigned int shash_len)292 int nvmet_auth_host_hash(struct nvmet_req *req, u8 *response,
293 unsigned int shash_len)
294 {
295 struct crypto_shash *shash_tfm;
296 SHASH_DESC_ON_STACK(shash, shash_tfm);
297 struct nvmet_ctrl *ctrl = req->sq->ctrl;
298 const char *hash_name;
299 u8 *challenge = req->sq->dhchap_c1;
300 struct nvme_dhchap_key *transformed_key;
301 u8 buf[4], sc_c = ctrl->concat ? 1 : 0;
302 int ret;
303
304 hash_name = nvme_auth_hmac_name(ctrl->shash_id);
305 if (!hash_name) {
306 pr_warn("Hash ID %d invalid\n", ctrl->shash_id);
307 return -EINVAL;
308 }
309
310 shash_tfm = crypto_alloc_shash(hash_name, 0, 0);
311 if (IS_ERR(shash_tfm)) {
312 pr_err("failed to allocate shash %s\n", hash_name);
313 return PTR_ERR(shash_tfm);
314 }
315
316 if (shash_len != crypto_shash_digestsize(shash_tfm)) {
317 pr_err("%s: hash len mismatch (len %d digest %d)\n",
318 __func__, shash_len,
319 crypto_shash_digestsize(shash_tfm));
320 ret = -EINVAL;
321 goto out_free_tfm;
322 }
323
324 transformed_key = nvme_auth_transform_key(ctrl->host_key,
325 ctrl->hostnqn);
326 if (IS_ERR(transformed_key)) {
327 ret = PTR_ERR(transformed_key);
328 goto out_free_tfm;
329 }
330
331 ret = crypto_shash_setkey(shash_tfm, transformed_key->key,
332 transformed_key->len);
333 if (ret)
334 goto out_free_response;
335
336 if (ctrl->dh_gid != NVME_AUTH_DHGROUP_NULL) {
337 challenge = kmalloc(shash_len, GFP_KERNEL);
338 if (!challenge) {
339 ret = -ENOMEM;
340 goto out_free_response;
341 }
342 ret = nvme_auth_augmented_challenge(ctrl->shash_id,
343 req->sq->dhchap_skey,
344 req->sq->dhchap_skey_len,
345 req->sq->dhchap_c1,
346 challenge, shash_len);
347 if (ret)
348 goto out;
349 }
350
351 pr_debug("ctrl %d qid %d host response seq %u transaction %d\n",
352 ctrl->cntlid, req->sq->qid, req->sq->dhchap_s1,
353 req->sq->dhchap_tid);
354
355 shash->tfm = shash_tfm;
356 ret = crypto_shash_init(shash);
357 if (ret)
358 goto out;
359 ret = crypto_shash_update(shash, challenge, shash_len);
360 if (ret)
361 goto out;
362 put_unaligned_le32(req->sq->dhchap_s1, buf);
363 ret = crypto_shash_update(shash, buf, 4);
364 if (ret)
365 goto out;
366 put_unaligned_le16(req->sq->dhchap_tid, buf);
367 ret = crypto_shash_update(shash, buf, 2);
368 if (ret)
369 goto out;
370 *buf = sc_c;
371 ret = crypto_shash_update(shash, buf, 1);
372 if (ret)
373 goto out;
374 ret = crypto_shash_update(shash, "HostHost", 8);
375 if (ret)
376 goto out;
377 memset(buf, 0, 4);
378 ret = crypto_shash_update(shash, ctrl->hostnqn, strlen(ctrl->hostnqn));
379 if (ret)
380 goto out;
381 ret = crypto_shash_update(shash, buf, 1);
382 if (ret)
383 goto out;
384 ret = crypto_shash_update(shash, ctrl->subsysnqn,
385 strlen(ctrl->subsysnqn));
386 if (ret)
387 goto out;
388 ret = crypto_shash_final(shash, response);
389 out:
390 if (challenge != req->sq->dhchap_c1)
391 kfree(challenge);
392 out_free_response:
393 nvme_auth_free_key(transformed_key);
394 out_free_tfm:
395 crypto_free_shash(shash_tfm);
396 return ret;
397 }
398
nvmet_auth_ctrl_hash(struct nvmet_req * req,u8 * response,unsigned int shash_len)399 int nvmet_auth_ctrl_hash(struct nvmet_req *req, u8 *response,
400 unsigned int shash_len)
401 {
402 struct crypto_shash *shash_tfm;
403 struct shash_desc *shash;
404 struct nvmet_ctrl *ctrl = req->sq->ctrl;
405 const char *hash_name;
406 u8 *challenge = req->sq->dhchap_c2;
407 struct nvme_dhchap_key *transformed_key;
408 u8 buf[4];
409 int ret;
410
411 hash_name = nvme_auth_hmac_name(ctrl->shash_id);
412 if (!hash_name) {
413 pr_warn("Hash ID %d invalid\n", ctrl->shash_id);
414 return -EINVAL;
415 }
416
417 shash_tfm = crypto_alloc_shash(hash_name, 0, 0);
418 if (IS_ERR(shash_tfm)) {
419 pr_err("failed to allocate shash %s\n", hash_name);
420 return PTR_ERR(shash_tfm);
421 }
422
423 if (shash_len != crypto_shash_digestsize(shash_tfm)) {
424 pr_debug("%s: hash len mismatch (len %d digest %d)\n",
425 __func__, shash_len,
426 crypto_shash_digestsize(shash_tfm));
427 ret = -EINVAL;
428 goto out_free_tfm;
429 }
430
431 transformed_key = nvme_auth_transform_key(ctrl->ctrl_key,
432 ctrl->subsysnqn);
433 if (IS_ERR(transformed_key)) {
434 ret = PTR_ERR(transformed_key);
435 goto out_free_tfm;
436 }
437
438 ret = crypto_shash_setkey(shash_tfm, transformed_key->key,
439 transformed_key->len);
440 if (ret)
441 goto out_free_response;
442
443 if (ctrl->dh_gid != NVME_AUTH_DHGROUP_NULL) {
444 challenge = kmalloc(shash_len, GFP_KERNEL);
445 if (!challenge) {
446 ret = -ENOMEM;
447 goto out_free_response;
448 }
449 ret = nvme_auth_augmented_challenge(ctrl->shash_id,
450 req->sq->dhchap_skey,
451 req->sq->dhchap_skey_len,
452 req->sq->dhchap_c2,
453 challenge, shash_len);
454 if (ret)
455 goto out_free_challenge;
456 }
457
458 shash = kzalloc(sizeof(*shash) + crypto_shash_descsize(shash_tfm),
459 GFP_KERNEL);
460 if (!shash) {
461 ret = -ENOMEM;
462 goto out_free_challenge;
463 }
464 shash->tfm = shash_tfm;
465
466 ret = crypto_shash_init(shash);
467 if (ret)
468 goto out;
469 ret = crypto_shash_update(shash, challenge, shash_len);
470 if (ret)
471 goto out;
472 put_unaligned_le32(req->sq->dhchap_s2, buf);
473 ret = crypto_shash_update(shash, buf, 4);
474 if (ret)
475 goto out;
476 put_unaligned_le16(req->sq->dhchap_tid, buf);
477 ret = crypto_shash_update(shash, buf, 2);
478 if (ret)
479 goto out;
480 memset(buf, 0, 4);
481 ret = crypto_shash_update(shash, buf, 1);
482 if (ret)
483 goto out;
484 ret = crypto_shash_update(shash, "Controller", 10);
485 if (ret)
486 goto out;
487 ret = crypto_shash_update(shash, ctrl->subsysnqn,
488 strlen(ctrl->subsysnqn));
489 if (ret)
490 goto out;
491 ret = crypto_shash_update(shash, buf, 1);
492 if (ret)
493 goto out;
494 ret = crypto_shash_update(shash, ctrl->hostnqn, strlen(ctrl->hostnqn));
495 if (ret)
496 goto out;
497 ret = crypto_shash_final(shash, response);
498 out:
499 kfree(shash);
500 out_free_challenge:
501 if (challenge != req->sq->dhchap_c2)
502 kfree(challenge);
503 out_free_response:
504 nvme_auth_free_key(transformed_key);
505 out_free_tfm:
506 crypto_free_shash(shash_tfm);
507 return ret;
508 }
509
nvmet_auth_ctrl_exponential(struct nvmet_req * req,u8 * buf,int buf_size)510 int nvmet_auth_ctrl_exponential(struct nvmet_req *req,
511 u8 *buf, int buf_size)
512 {
513 struct nvmet_ctrl *ctrl = req->sq->ctrl;
514 int ret = 0;
515
516 if (!ctrl->dh_key) {
517 pr_warn("ctrl %d no DH public key!\n", ctrl->cntlid);
518 return -ENOKEY;
519 }
520 if (buf_size != ctrl->dh_keysize) {
521 pr_warn("ctrl %d DH public key size mismatch, need %zu is %d\n",
522 ctrl->cntlid, ctrl->dh_keysize, buf_size);
523 ret = -EINVAL;
524 } else {
525 memcpy(buf, ctrl->dh_key, buf_size);
526 pr_debug("%s: ctrl %d public key %*ph\n", __func__,
527 ctrl->cntlid, (int)buf_size, buf);
528 }
529
530 return ret;
531 }
532
nvmet_auth_ctrl_sesskey(struct nvmet_req * req,u8 * pkey,int pkey_size)533 int nvmet_auth_ctrl_sesskey(struct nvmet_req *req,
534 u8 *pkey, int pkey_size)
535 {
536 struct nvmet_ctrl *ctrl = req->sq->ctrl;
537 int ret;
538
539 req->sq->dhchap_skey_len = ctrl->dh_keysize;
540 req->sq->dhchap_skey = kzalloc(req->sq->dhchap_skey_len, GFP_KERNEL);
541 if (!req->sq->dhchap_skey)
542 return -ENOMEM;
543 ret = nvme_auth_gen_shared_secret(ctrl->dh_tfm,
544 pkey, pkey_size,
545 req->sq->dhchap_skey,
546 req->sq->dhchap_skey_len);
547 if (ret)
548 pr_debug("failed to compute shared secret, err %d\n", ret);
549 else
550 pr_debug("%s: shared secret %*ph\n", __func__,
551 (int)req->sq->dhchap_skey_len,
552 req->sq->dhchap_skey);
553
554 return ret;
555 }
556
nvmet_auth_insert_psk(struct nvmet_sq * sq)557 void nvmet_auth_insert_psk(struct nvmet_sq *sq)
558 {
559 int hash_len = nvme_auth_hmac_hash_len(sq->ctrl->shash_id);
560 u8 *psk, *digest, *tls_psk;
561 size_t psk_len;
562 int ret;
563 #ifdef CONFIG_NVME_TARGET_TCP_TLS
564 struct key *tls_key = NULL;
565 #endif
566
567 ret = nvme_auth_generate_psk(sq->ctrl->shash_id,
568 sq->dhchap_skey,
569 sq->dhchap_skey_len,
570 sq->dhchap_c1, sq->dhchap_c2,
571 hash_len, &psk, &psk_len);
572 if (ret) {
573 pr_warn("%s: ctrl %d qid %d failed to generate PSK, error %d\n",
574 __func__, sq->ctrl->cntlid, sq->qid, ret);
575 return;
576 }
577 ret = nvme_auth_generate_digest(sq->ctrl->shash_id, psk, psk_len,
578 sq->ctrl->subsysnqn,
579 sq->ctrl->hostnqn, &digest);
580 if (ret) {
581 pr_warn("%s: ctrl %d qid %d failed to generate digest, error %d\n",
582 __func__, sq->ctrl->cntlid, sq->qid, ret);
583 goto out_free_psk;
584 }
585 ret = nvme_auth_derive_tls_psk(sq->ctrl->shash_id, psk, psk_len,
586 digest, &tls_psk);
587 if (ret) {
588 pr_warn("%s: ctrl %d qid %d failed to derive TLS PSK, error %d\n",
589 __func__, sq->ctrl->cntlid, sq->qid, ret);
590 goto out_free_digest;
591 }
592 #ifdef CONFIG_NVME_TARGET_TCP_TLS
593 tls_key = nvme_tls_psk_refresh(NULL, sq->ctrl->hostnqn, sq->ctrl->subsysnqn,
594 sq->ctrl->shash_id, tls_psk, psk_len, digest);
595 if (IS_ERR(tls_key)) {
596 pr_warn("%s: ctrl %d qid %d failed to refresh key, error %ld\n",
597 __func__, sq->ctrl->cntlid, sq->qid, PTR_ERR(tls_key));
598 tls_key = NULL;
599 }
600 if (sq->ctrl->tls_key)
601 key_put(sq->ctrl->tls_key);
602 sq->ctrl->tls_key = tls_key;
603 #endif
604 kfree_sensitive(tls_psk);
605 out_free_digest:
606 kfree_sensitive(digest);
607 out_free_psk:
608 kfree_sensitive(psk);
609 }
610