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 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 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 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 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 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 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 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 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 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 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 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