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 !req->sq->authenticated)
285 return false;
286 return true;
287 }
288
nvmet_auth_host_hash(struct nvmet_req * req,u8 * response,unsigned int shash_len)289 int nvmet_auth_host_hash(struct nvmet_req *req, u8 *response,
290 unsigned int shash_len)
291 {
292 struct crypto_shash *shash_tfm;
293 struct shash_desc *shash;
294 struct nvmet_ctrl *ctrl = req->sq->ctrl;
295 const char *hash_name;
296 u8 *challenge = req->sq->dhchap_c1;
297 struct nvme_dhchap_key *transformed_key;
298 u8 buf[4];
299 int ret;
300
301 hash_name = nvme_auth_hmac_name(ctrl->shash_id);
302 if (!hash_name) {
303 pr_warn("Hash ID %d invalid\n", ctrl->shash_id);
304 return -EINVAL;
305 }
306
307 shash_tfm = crypto_alloc_shash(hash_name, 0, 0);
308 if (IS_ERR(shash_tfm)) {
309 pr_err("failed to allocate shash %s\n", hash_name);
310 return PTR_ERR(shash_tfm);
311 }
312
313 if (shash_len != crypto_shash_digestsize(shash_tfm)) {
314 pr_err("%s: hash len mismatch (len %d digest %d)\n",
315 __func__, shash_len,
316 crypto_shash_digestsize(shash_tfm));
317 ret = -EINVAL;
318 goto out_free_tfm;
319 }
320
321 transformed_key = nvme_auth_transform_key(ctrl->host_key,
322 ctrl->hostnqn);
323 if (IS_ERR(transformed_key)) {
324 ret = PTR_ERR(transformed_key);
325 goto out_free_tfm;
326 }
327
328 ret = crypto_shash_setkey(shash_tfm, transformed_key->key,
329 transformed_key->len);
330 if (ret)
331 goto out_free_response;
332
333 if (ctrl->dh_gid != NVME_AUTH_DHGROUP_NULL) {
334 challenge = kmalloc(shash_len, GFP_KERNEL);
335 if (!challenge) {
336 ret = -ENOMEM;
337 goto out_free_response;
338 }
339 ret = nvme_auth_augmented_challenge(ctrl->shash_id,
340 req->sq->dhchap_skey,
341 req->sq->dhchap_skey_len,
342 req->sq->dhchap_c1,
343 challenge, shash_len);
344 if (ret)
345 goto out_free_challenge;
346 }
347
348 pr_debug("ctrl %d qid %d host response seq %u transaction %d\n",
349 ctrl->cntlid, req->sq->qid, req->sq->dhchap_s1,
350 req->sq->dhchap_tid);
351
352 shash = kzalloc(sizeof(*shash) + crypto_shash_descsize(shash_tfm),
353 GFP_KERNEL);
354 if (!shash) {
355 ret = -ENOMEM;
356 goto out_free_challenge;
357 }
358 shash->tfm = shash_tfm;
359 ret = crypto_shash_init(shash);
360 if (ret)
361 goto out;
362 ret = crypto_shash_update(shash, challenge, shash_len);
363 if (ret)
364 goto out;
365 put_unaligned_le32(req->sq->dhchap_s1, buf);
366 ret = crypto_shash_update(shash, buf, 4);
367 if (ret)
368 goto out;
369 put_unaligned_le16(req->sq->dhchap_tid, buf);
370 ret = crypto_shash_update(shash, buf, 2);
371 if (ret)
372 goto out;
373 memset(buf, 0, 4);
374 ret = crypto_shash_update(shash, buf, 1);
375 if (ret)
376 goto out;
377 ret = crypto_shash_update(shash, "HostHost", 8);
378 if (ret)
379 goto out;
380 ret = crypto_shash_update(shash, ctrl->hostnqn, strlen(ctrl->hostnqn));
381 if (ret)
382 goto out;
383 ret = crypto_shash_update(shash, buf, 1);
384 if (ret)
385 goto out;
386 ret = crypto_shash_update(shash, ctrl->subsysnqn,
387 strlen(ctrl->subsysnqn));
388 if (ret)
389 goto out;
390 ret = crypto_shash_final(shash, response);
391 out:
392 kfree(shash);
393 out_free_challenge:
394 if (challenge != req->sq->dhchap_c1)
395 kfree(challenge);
396 out_free_response:
397 nvme_auth_free_key(transformed_key);
398 out_free_tfm:
399 crypto_free_shash(shash_tfm);
400 return ret;
401 }
402
nvmet_auth_ctrl_hash(struct nvmet_req * req,u8 * response,unsigned int shash_len)403 int nvmet_auth_ctrl_hash(struct nvmet_req *req, u8 *response,
404 unsigned int shash_len)
405 {
406 struct crypto_shash *shash_tfm;
407 struct shash_desc *shash;
408 struct nvmet_ctrl *ctrl = req->sq->ctrl;
409 const char *hash_name;
410 u8 *challenge = req->sq->dhchap_c2;
411 struct nvme_dhchap_key *transformed_key;
412 u8 buf[4];
413 int ret;
414
415 hash_name = nvme_auth_hmac_name(ctrl->shash_id);
416 if (!hash_name) {
417 pr_warn("Hash ID %d invalid\n", ctrl->shash_id);
418 return -EINVAL;
419 }
420
421 shash_tfm = crypto_alloc_shash(hash_name, 0, 0);
422 if (IS_ERR(shash_tfm)) {
423 pr_err("failed to allocate shash %s\n", hash_name);
424 return PTR_ERR(shash_tfm);
425 }
426
427 if (shash_len != crypto_shash_digestsize(shash_tfm)) {
428 pr_debug("%s: hash len mismatch (len %d digest %d)\n",
429 __func__, shash_len,
430 crypto_shash_digestsize(shash_tfm));
431 ret = -EINVAL;
432 goto out_free_tfm;
433 }
434
435 transformed_key = nvme_auth_transform_key(ctrl->ctrl_key,
436 ctrl->subsysnqn);
437 if (IS_ERR(transformed_key)) {
438 ret = PTR_ERR(transformed_key);
439 goto out_free_tfm;
440 }
441
442 ret = crypto_shash_setkey(shash_tfm, transformed_key->key,
443 transformed_key->len);
444 if (ret)
445 goto out_free_response;
446
447 if (ctrl->dh_gid != NVME_AUTH_DHGROUP_NULL) {
448 challenge = kmalloc(shash_len, GFP_KERNEL);
449 if (!challenge) {
450 ret = -ENOMEM;
451 goto out_free_response;
452 }
453 ret = nvme_auth_augmented_challenge(ctrl->shash_id,
454 req->sq->dhchap_skey,
455 req->sq->dhchap_skey_len,
456 req->sq->dhchap_c2,
457 challenge, shash_len);
458 if (ret)
459 goto out_free_challenge;
460 }
461
462 shash = kzalloc(sizeof(*shash) + crypto_shash_descsize(shash_tfm),
463 GFP_KERNEL);
464 if (!shash) {
465 ret = -ENOMEM;
466 goto out_free_challenge;
467 }
468 shash->tfm = shash_tfm;
469
470 ret = crypto_shash_init(shash);
471 if (ret)
472 goto out;
473 ret = crypto_shash_update(shash, challenge, shash_len);
474 if (ret)
475 goto out;
476 put_unaligned_le32(req->sq->dhchap_s2, buf);
477 ret = crypto_shash_update(shash, buf, 4);
478 if (ret)
479 goto out;
480 put_unaligned_le16(req->sq->dhchap_tid, buf);
481 ret = crypto_shash_update(shash, buf, 2);
482 if (ret)
483 goto out;
484 memset(buf, 0, 4);
485 ret = crypto_shash_update(shash, buf, 1);
486 if (ret)
487 goto out;
488 ret = crypto_shash_update(shash, "Controller", 10);
489 if (ret)
490 goto out;
491 ret = crypto_shash_update(shash, ctrl->subsysnqn,
492 strlen(ctrl->subsysnqn));
493 if (ret)
494 goto out;
495 ret = crypto_shash_update(shash, buf, 1);
496 if (ret)
497 goto out;
498 ret = crypto_shash_update(shash, ctrl->hostnqn, strlen(ctrl->hostnqn));
499 if (ret)
500 goto out;
501 ret = crypto_shash_final(shash, response);
502 out:
503 kfree(shash);
504 out_free_challenge:
505 if (challenge != req->sq->dhchap_c2)
506 kfree(challenge);
507 out_free_response:
508 nvme_auth_free_key(transformed_key);
509 out_free_tfm:
510 crypto_free_shash(shash_tfm);
511 return ret;
512 }
513
nvmet_auth_ctrl_exponential(struct nvmet_req * req,u8 * buf,int buf_size)514 int nvmet_auth_ctrl_exponential(struct nvmet_req *req,
515 u8 *buf, int buf_size)
516 {
517 struct nvmet_ctrl *ctrl = req->sq->ctrl;
518 int ret = 0;
519
520 if (!ctrl->dh_key) {
521 pr_warn("ctrl %d no DH public key!\n", ctrl->cntlid);
522 return -ENOKEY;
523 }
524 if (buf_size != ctrl->dh_keysize) {
525 pr_warn("ctrl %d DH public key size mismatch, need %zu is %d\n",
526 ctrl->cntlid, ctrl->dh_keysize, buf_size);
527 ret = -EINVAL;
528 } else {
529 memcpy(buf, ctrl->dh_key, buf_size);
530 pr_debug("%s: ctrl %d public key %*ph\n", __func__,
531 ctrl->cntlid, (int)buf_size, buf);
532 }
533
534 return ret;
535 }
536
nvmet_auth_ctrl_sesskey(struct nvmet_req * req,u8 * pkey,int pkey_size)537 int nvmet_auth_ctrl_sesskey(struct nvmet_req *req,
538 u8 *pkey, int pkey_size)
539 {
540 struct nvmet_ctrl *ctrl = req->sq->ctrl;
541 int ret;
542
543 req->sq->dhchap_skey_len = ctrl->dh_keysize;
544 req->sq->dhchap_skey = kzalloc(req->sq->dhchap_skey_len, GFP_KERNEL);
545 if (!req->sq->dhchap_skey)
546 return -ENOMEM;
547 ret = nvme_auth_gen_shared_secret(ctrl->dh_tfm,
548 pkey, pkey_size,
549 req->sq->dhchap_skey,
550 req->sq->dhchap_skey_len);
551 if (ret)
552 pr_debug("failed to compute shared secret, err %d\n", ret);
553 else
554 pr_debug("%s: shared secret %*ph\n", __func__,
555 (int)req->sq->dhchap_skey_len,
556 req->sq->dhchap_skey);
557
558 return ret;
559 }
560
nvmet_auth_insert_psk(struct nvmet_sq * sq)561 void nvmet_auth_insert_psk(struct nvmet_sq *sq)
562 {
563 int hash_len = nvme_auth_hmac_hash_len(sq->ctrl->shash_id);
564 u8 *psk, *digest, *tls_psk;
565 size_t psk_len;
566 int ret;
567 #ifdef CONFIG_NVME_TARGET_TCP_TLS
568 struct key *tls_key = NULL;
569 #endif
570
571 ret = nvme_auth_generate_psk(sq->ctrl->shash_id,
572 sq->dhchap_skey,
573 sq->dhchap_skey_len,
574 sq->dhchap_c1, sq->dhchap_c2,
575 hash_len, &psk, &psk_len);
576 if (ret) {
577 pr_warn("%s: ctrl %d qid %d failed to generate PSK, error %d\n",
578 __func__, sq->ctrl->cntlid, sq->qid, ret);
579 return;
580 }
581 ret = nvme_auth_generate_digest(sq->ctrl->shash_id, psk, psk_len,
582 sq->ctrl->subsysnqn,
583 sq->ctrl->hostnqn, &digest);
584 if (ret) {
585 pr_warn("%s: ctrl %d qid %d failed to generate digest, error %d\n",
586 __func__, sq->ctrl->cntlid, sq->qid, ret);
587 goto out_free_psk;
588 }
589 ret = nvme_auth_derive_tls_psk(sq->ctrl->shash_id, psk, psk_len,
590 digest, &tls_psk);
591 if (ret) {
592 pr_warn("%s: ctrl %d qid %d failed to derive TLS PSK, error %d\n",
593 __func__, sq->ctrl->cntlid, sq->qid, ret);
594 goto out_free_digest;
595 }
596 #ifdef CONFIG_NVME_TARGET_TCP_TLS
597 tls_key = nvme_tls_psk_refresh(NULL, sq->ctrl->hostnqn, sq->ctrl->subsysnqn,
598 sq->ctrl->shash_id, tls_psk, psk_len, digest);
599 if (IS_ERR(tls_key)) {
600 pr_warn("%s: ctrl %d qid %d failed to refresh key, error %ld\n",
601 __func__, sq->ctrl->cntlid, sq->qid, PTR_ERR(tls_key));
602 tls_key = NULL;
603 }
604 if (sq->ctrl->tls_key)
605 key_put(sq->ctrl->tls_key);
606 sq->ctrl->tls_key = tls_key;
607 #endif
608 kfree_sensitive(tls_psk);
609 out_free_digest:
610 kfree_sensitive(digest);
611 out_free_psk:
612 kfree_sensitive(psk);
613 }
614