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_destroy_auth(struct nvmet_ctrl *ctrl) 242 { 243 ctrl->shash_id = 0; 244 245 if (ctrl->dh_tfm) { 246 crypto_free_kpp(ctrl->dh_tfm); 247 ctrl->dh_tfm = NULL; 248 ctrl->dh_gid = 0; 249 } 250 kfree_sensitive(ctrl->dh_key); 251 ctrl->dh_key = NULL; 252 253 if (ctrl->host_key) { 254 nvme_auth_free_key(ctrl->host_key); 255 ctrl->host_key = NULL; 256 } 257 if (ctrl->ctrl_key) { 258 nvme_auth_free_key(ctrl->ctrl_key); 259 ctrl->ctrl_key = NULL; 260 } 261 #ifdef CONFIG_NVME_TARGET_TCP_TLS 262 if (ctrl->tls_key) { 263 key_put(ctrl->tls_key); 264 ctrl->tls_key = NULL; 265 } 266 #endif 267 } 268 269 bool nvmet_check_auth_status(struct nvmet_req *req) 270 { 271 if (req->sq->ctrl->host_key) { 272 if (req->sq->qid > 0) 273 return true; 274 if (!req->sq->authenticated) 275 return false; 276 } 277 return true; 278 } 279 280 int nvmet_auth_host_hash(struct nvmet_req *req, u8 *response, 281 unsigned int shash_len) 282 { 283 struct nvme_auth_hmac_ctx hmac; 284 struct nvmet_ctrl *ctrl = req->sq->ctrl; 285 u8 *challenge = req->sq->dhchap_c1; 286 struct nvme_dhchap_key *transformed_key; 287 u8 buf[4]; 288 int ret; 289 290 transformed_key = nvme_auth_transform_key(ctrl->host_key, 291 ctrl->hostnqn); 292 if (IS_ERR(transformed_key)) 293 return PTR_ERR(transformed_key); 294 295 ret = nvme_auth_hmac_init(&hmac, ctrl->shash_id, transformed_key->key, 296 transformed_key->len); 297 if (ret) 298 goto out_free_response; 299 300 if (shash_len != nvme_auth_hmac_hash_len(ctrl->shash_id)) { 301 pr_err("%s: hash len mismatch (len %u digest %zu)\n", __func__, 302 shash_len, nvme_auth_hmac_hash_len(ctrl->shash_id)); 303 ret = -EINVAL; 304 goto out_free_response; 305 } 306 307 if (ctrl->dh_gid != NVME_AUTH_DHGROUP_NULL) { 308 challenge = kmalloc(shash_len, GFP_KERNEL); 309 if (!challenge) { 310 ret = -ENOMEM; 311 goto out_free_response; 312 } 313 ret = nvme_auth_augmented_challenge(ctrl->shash_id, 314 req->sq->dhchap_skey, 315 req->sq->dhchap_skey_len, 316 req->sq->dhchap_c1, 317 challenge, shash_len); 318 if (ret) 319 goto out_free_challenge; 320 } 321 pr_debug("ctrl %d qid %d host response seq %u transaction %d\n", 322 ctrl->cntlid, req->sq->qid, req->sq->dhchap_s1, 323 req->sq->dhchap_tid); 324 325 nvme_auth_hmac_update(&hmac, challenge, shash_len); 326 327 put_unaligned_le32(req->sq->dhchap_s1, buf); 328 nvme_auth_hmac_update(&hmac, buf, 4); 329 330 put_unaligned_le16(req->sq->dhchap_tid, buf); 331 nvme_auth_hmac_update(&hmac, buf, 2); 332 333 *buf = req->sq->sc_c; 334 nvme_auth_hmac_update(&hmac, buf, 1); 335 nvme_auth_hmac_update(&hmac, "HostHost", 8); 336 memset(buf, 0, 4); 337 nvme_auth_hmac_update(&hmac, ctrl->hostnqn, strlen(ctrl->hostnqn)); 338 nvme_auth_hmac_update(&hmac, buf, 1); 339 nvme_auth_hmac_update(&hmac, ctrl->subsys->subsysnqn, 340 strlen(ctrl->subsys->subsysnqn)); 341 nvme_auth_hmac_final(&hmac, response); 342 ret = 0; 343 out_free_challenge: 344 if (challenge != req->sq->dhchap_c1) 345 kfree(challenge); 346 out_free_response: 347 memzero_explicit(&hmac, sizeof(hmac)); 348 nvme_auth_free_key(transformed_key); 349 return ret; 350 } 351 352 int nvmet_auth_ctrl_hash(struct nvmet_req *req, u8 *response, 353 unsigned int shash_len) 354 { 355 struct nvme_auth_hmac_ctx hmac; 356 struct nvmet_ctrl *ctrl = req->sq->ctrl; 357 u8 *challenge = req->sq->dhchap_c2; 358 struct nvme_dhchap_key *transformed_key; 359 u8 buf[4]; 360 int ret; 361 362 transformed_key = nvme_auth_transform_key(ctrl->ctrl_key, 363 ctrl->subsys->subsysnqn); 364 if (IS_ERR(transformed_key)) 365 return PTR_ERR(transformed_key); 366 367 ret = nvme_auth_hmac_init(&hmac, ctrl->shash_id, transformed_key->key, 368 transformed_key->len); 369 if (ret) 370 goto out_free_response; 371 372 if (shash_len != nvme_auth_hmac_hash_len(ctrl->shash_id)) { 373 pr_err("%s: hash len mismatch (len %u digest %zu)\n", __func__, 374 shash_len, nvme_auth_hmac_hash_len(ctrl->shash_id)); 375 ret = -EINVAL; 376 goto out_free_response; 377 } 378 379 if (ctrl->dh_gid != NVME_AUTH_DHGROUP_NULL) { 380 challenge = kmalloc(shash_len, GFP_KERNEL); 381 if (!challenge) { 382 ret = -ENOMEM; 383 goto out_free_response; 384 } 385 ret = nvme_auth_augmented_challenge(ctrl->shash_id, 386 req->sq->dhchap_skey, 387 req->sq->dhchap_skey_len, 388 req->sq->dhchap_c2, 389 challenge, shash_len); 390 if (ret) 391 goto out_free_challenge; 392 } 393 394 nvme_auth_hmac_update(&hmac, challenge, shash_len); 395 396 put_unaligned_le32(req->sq->dhchap_s2, buf); 397 nvme_auth_hmac_update(&hmac, buf, 4); 398 399 put_unaligned_le16(req->sq->dhchap_tid, buf); 400 nvme_auth_hmac_update(&hmac, buf, 2); 401 402 *buf = req->sq->sc_c; 403 nvme_auth_hmac_update(&hmac, buf, 1); 404 nvme_auth_hmac_update(&hmac, "Controller", 10); 405 nvme_auth_hmac_update(&hmac, ctrl->subsys->subsysnqn, 406 strlen(ctrl->subsys->subsysnqn)); 407 memset(buf, 0, 4); 408 nvme_auth_hmac_update(&hmac, buf, 1); 409 nvme_auth_hmac_update(&hmac, ctrl->hostnqn, strlen(ctrl->hostnqn)); 410 nvme_auth_hmac_final(&hmac, response); 411 ret = 0; 412 out_free_challenge: 413 if (challenge != req->sq->dhchap_c2) 414 kfree(challenge); 415 out_free_response: 416 memzero_explicit(&hmac, sizeof(hmac)); 417 nvme_auth_free_key(transformed_key); 418 return ret; 419 } 420 421 int nvmet_auth_ctrl_exponential(struct nvmet_req *req, 422 u8 *buf, int buf_size) 423 { 424 struct nvmet_ctrl *ctrl = req->sq->ctrl; 425 int ret = 0; 426 427 if (!ctrl->dh_key) { 428 pr_warn("ctrl %d no DH public key!\n", ctrl->cntlid); 429 return -ENOKEY; 430 } 431 if (buf_size != ctrl->dh_keysize) { 432 pr_warn("ctrl %d DH public key size mismatch, need %zu is %d\n", 433 ctrl->cntlid, ctrl->dh_keysize, buf_size); 434 ret = -EINVAL; 435 } else { 436 memcpy(buf, ctrl->dh_key, buf_size); 437 #ifdef CONFIG_NVME_TARGET_AUTH_DEBUG 438 pr_debug("%s: ctrl %d public key %*ph\n", __func__, 439 ctrl->cntlid, (int)buf_size, buf); 440 #endif 441 } 442 443 return ret; 444 } 445 446 int nvmet_auth_ctrl_sesskey(struct nvmet_req *req, 447 const u8 *pkey, int pkey_size) 448 { 449 struct nvmet_ctrl *ctrl = req->sq->ctrl; 450 int ret; 451 452 req->sq->dhchap_skey_len = nvme_auth_hmac_hash_len(ctrl->shash_id); 453 req->sq->dhchap_skey = kzalloc(req->sq->dhchap_skey_len, GFP_KERNEL); 454 if (!req->sq->dhchap_skey) 455 return -ENOMEM; 456 ret = nvme_auth_gen_session_key(ctrl->dh_tfm, 457 pkey, pkey_size, 458 req->sq->dhchap_skey, 459 req->sq->dhchap_skey_len, 460 ctrl->shash_id); 461 if (ret) 462 pr_debug("failed to compute session key, err %d\n", ret); 463 #ifdef CONFIG_NVME_TARGET_AUTH_DEBUG 464 else 465 pr_debug("%s: session key %*ph\n", __func__, 466 (int)req->sq->dhchap_skey_len, 467 req->sq->dhchap_skey); 468 #endif 469 return ret; 470 } 471 472 void nvmet_auth_insert_psk(struct nvmet_sq *sq) 473 { 474 int hash_len = nvme_auth_hmac_hash_len(sq->ctrl->shash_id); 475 u8 *psk, *tls_psk; 476 char *digest; 477 size_t psk_len; 478 int ret; 479 #ifdef CONFIG_NVME_TARGET_TCP_TLS 480 struct key *tls_key = NULL; 481 #endif 482 483 ret = nvme_auth_generate_psk(sq->ctrl->shash_id, 484 sq->dhchap_skey, 485 sq->dhchap_skey_len, 486 sq->dhchap_c1, sq->dhchap_c2, 487 hash_len, &psk, &psk_len); 488 if (ret) { 489 pr_warn("%s: ctrl %d qid %d failed to generate PSK, error %d\n", 490 __func__, sq->ctrl->cntlid, sq->qid, ret); 491 return; 492 } 493 ret = nvme_auth_generate_digest(sq->ctrl->shash_id, psk, psk_len, 494 sq->ctrl->subsys->subsysnqn, 495 sq->ctrl->hostnqn, &digest); 496 if (ret) { 497 pr_warn("%s: ctrl %d qid %d failed to generate digest, error %d\n", 498 __func__, sq->ctrl->cntlid, sq->qid, ret); 499 goto out_free_psk; 500 } 501 ret = nvme_auth_derive_tls_psk(sq->ctrl->shash_id, psk, psk_len, 502 digest, &tls_psk); 503 if (ret) { 504 pr_warn("%s: ctrl %d qid %d failed to derive TLS PSK, error %d\n", 505 __func__, sq->ctrl->cntlid, sq->qid, ret); 506 goto out_free_digest; 507 } 508 #ifdef CONFIG_NVME_TARGET_TCP_TLS 509 tls_key = nvme_tls_psk_refresh(NULL, sq->ctrl->hostnqn, 510 sq->ctrl->subsys->subsysnqn, 511 sq->ctrl->shash_id, tls_psk, psk_len, 512 digest); 513 if (IS_ERR(tls_key)) { 514 pr_warn("%s: ctrl %d qid %d failed to refresh key, error %ld\n", 515 __func__, sq->ctrl->cntlid, sq->qid, PTR_ERR(tls_key)); 516 tls_key = NULL; 517 } 518 if (sq->ctrl->tls_key) 519 key_put(sq->ctrl->tls_key); 520 sq->ctrl->tls_key = tls_key; 521 #endif 522 kfree_sensitive(tls_psk); 523 out_free_digest: 524 kfree_sensitive(digest); 525 out_free_psk: 526 kfree_sensitive(psk); 527 } 528