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];
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 memset(buf, 0, 4);
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 ret = crypto_shash_update(shash, ctrl->hostnqn, strlen(ctrl->hostnqn));
378 if (ret)
379 goto out;
380 ret = crypto_shash_update(shash, buf, 1);
381 if (ret)
382 goto out;
383 ret = crypto_shash_update(shash, ctrl->subsysnqn,
384 strlen(ctrl->subsysnqn));
385 if (ret)
386 goto out;
387 ret = crypto_shash_final(shash, response);
388 out:
389 if (challenge != req->sq->dhchap_c1)
390 kfree(challenge);
391 out_free_response:
392 nvme_auth_free_key(transformed_key);
393 out_free_tfm:
394 crypto_free_shash(shash_tfm);
395 return ret;
396 }
397
nvmet_auth_ctrl_hash(struct nvmet_req * req,u8 * response,unsigned int shash_len)398 int nvmet_auth_ctrl_hash(struct nvmet_req *req, u8 *response,
399 unsigned int shash_len)
400 {
401 struct crypto_shash *shash_tfm;
402 struct shash_desc *shash;
403 struct nvmet_ctrl *ctrl = req->sq->ctrl;
404 const char *hash_name;
405 u8 *challenge = req->sq->dhchap_c2;
406 struct nvme_dhchap_key *transformed_key;
407 u8 buf[4];
408 int ret;
409
410 hash_name = nvme_auth_hmac_name(ctrl->shash_id);
411 if (!hash_name) {
412 pr_warn("Hash ID %d invalid\n", ctrl->shash_id);
413 return -EINVAL;
414 }
415
416 shash_tfm = crypto_alloc_shash(hash_name, 0, 0);
417 if (IS_ERR(shash_tfm)) {
418 pr_err("failed to allocate shash %s\n", hash_name);
419 return PTR_ERR(shash_tfm);
420 }
421
422 if (shash_len != crypto_shash_digestsize(shash_tfm)) {
423 pr_debug("%s: hash len mismatch (len %d digest %d)\n",
424 __func__, shash_len,
425 crypto_shash_digestsize(shash_tfm));
426 ret = -EINVAL;
427 goto out_free_tfm;
428 }
429
430 transformed_key = nvme_auth_transform_key(ctrl->ctrl_key,
431 ctrl->subsysnqn);
432 if (IS_ERR(transformed_key)) {
433 ret = PTR_ERR(transformed_key);
434 goto out_free_tfm;
435 }
436
437 ret = crypto_shash_setkey(shash_tfm, transformed_key->key,
438 transformed_key->len);
439 if (ret)
440 goto out_free_response;
441
442 if (ctrl->dh_gid != NVME_AUTH_DHGROUP_NULL) {
443 challenge = kmalloc(shash_len, GFP_KERNEL);
444 if (!challenge) {
445 ret = -ENOMEM;
446 goto out_free_response;
447 }
448 ret = nvme_auth_augmented_challenge(ctrl->shash_id,
449 req->sq->dhchap_skey,
450 req->sq->dhchap_skey_len,
451 req->sq->dhchap_c2,
452 challenge, shash_len);
453 if (ret)
454 goto out_free_challenge;
455 }
456
457 shash = kzalloc(sizeof(*shash) + crypto_shash_descsize(shash_tfm),
458 GFP_KERNEL);
459 if (!shash) {
460 ret = -ENOMEM;
461 goto out_free_challenge;
462 }
463 shash->tfm = shash_tfm;
464
465 ret = crypto_shash_init(shash);
466 if (ret)
467 goto out;
468 ret = crypto_shash_update(shash, challenge, shash_len);
469 if (ret)
470 goto out;
471 put_unaligned_le32(req->sq->dhchap_s2, buf);
472 ret = crypto_shash_update(shash, buf, 4);
473 if (ret)
474 goto out;
475 put_unaligned_le16(req->sq->dhchap_tid, buf);
476 ret = crypto_shash_update(shash, buf, 2);
477 if (ret)
478 goto out;
479 memset(buf, 0, 4);
480 ret = crypto_shash_update(shash, buf, 1);
481 if (ret)
482 goto out;
483 ret = crypto_shash_update(shash, "Controller", 10);
484 if (ret)
485 goto out;
486 ret = crypto_shash_update(shash, ctrl->subsysnqn,
487 strlen(ctrl->subsysnqn));
488 if (ret)
489 goto out;
490 ret = crypto_shash_update(shash, buf, 1);
491 if (ret)
492 goto out;
493 ret = crypto_shash_update(shash, ctrl->hostnqn, strlen(ctrl->hostnqn));
494 if (ret)
495 goto out;
496 ret = crypto_shash_final(shash, response);
497 out:
498 kfree(shash);
499 out_free_challenge:
500 if (challenge != req->sq->dhchap_c2)
501 kfree(challenge);
502 out_free_response:
503 nvme_auth_free_key(transformed_key);
504 out_free_tfm:
505 crypto_free_shash(shash_tfm);
506 return ret;
507 }
508
nvmet_auth_ctrl_exponential(struct nvmet_req * req,u8 * buf,int buf_size)509 int nvmet_auth_ctrl_exponential(struct nvmet_req *req,
510 u8 *buf, int buf_size)
511 {
512 struct nvmet_ctrl *ctrl = req->sq->ctrl;
513 int ret = 0;
514
515 if (!ctrl->dh_key) {
516 pr_warn("ctrl %d no DH public key!\n", ctrl->cntlid);
517 return -ENOKEY;
518 }
519 if (buf_size != ctrl->dh_keysize) {
520 pr_warn("ctrl %d DH public key size mismatch, need %zu is %d\n",
521 ctrl->cntlid, ctrl->dh_keysize, buf_size);
522 ret = -EINVAL;
523 } else {
524 memcpy(buf, ctrl->dh_key, buf_size);
525 pr_debug("%s: ctrl %d public key %*ph\n", __func__,
526 ctrl->cntlid, (int)buf_size, buf);
527 }
528
529 return ret;
530 }
531
nvmet_auth_ctrl_sesskey(struct nvmet_req * req,u8 * pkey,int pkey_size)532 int nvmet_auth_ctrl_sesskey(struct nvmet_req *req,
533 u8 *pkey, int pkey_size)
534 {
535 struct nvmet_ctrl *ctrl = req->sq->ctrl;
536 int ret;
537
538 req->sq->dhchap_skey_len = ctrl->dh_keysize;
539 req->sq->dhchap_skey = kzalloc(req->sq->dhchap_skey_len, GFP_KERNEL);
540 if (!req->sq->dhchap_skey)
541 return -ENOMEM;
542 ret = nvme_auth_gen_shared_secret(ctrl->dh_tfm,
543 pkey, pkey_size,
544 req->sq->dhchap_skey,
545 req->sq->dhchap_skey_len);
546 if (ret)
547 pr_debug("failed to compute shared secret, err %d\n", ret);
548 else
549 pr_debug("%s: shared secret %*ph\n", __func__,
550 (int)req->sq->dhchap_skey_len,
551 req->sq->dhchap_skey);
552
553 return ret;
554 }
555
nvmet_auth_insert_psk(struct nvmet_sq * sq)556 void nvmet_auth_insert_psk(struct nvmet_sq *sq)
557 {
558 int hash_len = nvme_auth_hmac_hash_len(sq->ctrl->shash_id);
559 u8 *psk, *digest, *tls_psk;
560 size_t psk_len;
561 int ret;
562 #ifdef CONFIG_NVME_TARGET_TCP_TLS
563 struct key *tls_key = NULL;
564 #endif
565
566 ret = nvme_auth_generate_psk(sq->ctrl->shash_id,
567 sq->dhchap_skey,
568 sq->dhchap_skey_len,
569 sq->dhchap_c1, sq->dhchap_c2,
570 hash_len, &psk, &psk_len);
571 if (ret) {
572 pr_warn("%s: ctrl %d qid %d failed to generate PSK, error %d\n",
573 __func__, sq->ctrl->cntlid, sq->qid, ret);
574 return;
575 }
576 ret = nvme_auth_generate_digest(sq->ctrl->shash_id, psk, psk_len,
577 sq->ctrl->subsysnqn,
578 sq->ctrl->hostnqn, &digest);
579 if (ret) {
580 pr_warn("%s: ctrl %d qid %d failed to generate digest, error %d\n",
581 __func__, sq->ctrl->cntlid, sq->qid, ret);
582 goto out_free_psk;
583 }
584 ret = nvme_auth_derive_tls_psk(sq->ctrl->shash_id, psk, psk_len,
585 digest, &tls_psk);
586 if (ret) {
587 pr_warn("%s: ctrl %d qid %d failed to derive TLS PSK, error %d\n",
588 __func__, sq->ctrl->cntlid, sq->qid, ret);
589 goto out_free_digest;
590 }
591 #ifdef CONFIG_NVME_TARGET_TCP_TLS
592 tls_key = nvme_tls_psk_refresh(NULL, sq->ctrl->hostnqn, sq->ctrl->subsysnqn,
593 sq->ctrl->shash_id, tls_psk, psk_len, digest);
594 if (IS_ERR(tls_key)) {
595 pr_warn("%s: ctrl %d qid %d failed to refresh key, error %ld\n",
596 __func__, sq->ctrl->cntlid, sq->qid, PTR_ERR(tls_key));
597 tls_key = NULL;
598 }
599 if (sq->ctrl->tls_key)
600 key_put(sq->ctrl->tls_key);
601 sq->ctrl->tls_key = tls_key;
602 #endif
603 kfree_sensitive(tls_psk);
604 out_free_digest:
605 kfree_sensitive(digest);
606 out_free_psk:
607 kfree_sensitive(psk);
608 }
609