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