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