Lines Matching +full:ctrl +full:- +full:len

1 // SPDX-License-Identifier: GPL-2.0
3 * NVMe over Fabrics DH-HMAC-CHAP authentication.
17 #include <linux/nvme-auth.h>
30 kfree(host->dhchap_ctrl_secret); in nvmet_auth_set_key()
31 host->dhchap_ctrl_secret = NULL; in nvmet_auth_set_key()
32 host->dhchap_ctrl_key_hash = 0; in nvmet_auth_set_key()
34 kfree(host->dhchap_secret); in nvmet_auth_set_key()
35 host->dhchap_secret = NULL; in nvmet_auth_set_key()
36 host->dhchap_key_hash = 0; in nvmet_auth_set_key()
40 if (sscanf(secret, "DHHC-1:%hhd:%*s", &key_hash) != 1) in nvmet_auth_set_key()
41 return -EINVAL; in nvmet_auth_set_key()
43 pr_warn("Invalid DH-HMAC-CHAP hash id %d\n", in nvmet_auth_set_key()
45 return -EINVAL; in nvmet_auth_set_key()
52 pr_err("DH-HMAC-CHAP hash %s unsupported\n", hmac); in nvmet_auth_set_key()
53 return -ENOTSUPP; in nvmet_auth_set_key()
58 return -ENOMEM; in nvmet_auth_set_key()
61 kfree(host->dhchap_ctrl_secret); in nvmet_auth_set_key()
62 host->dhchap_ctrl_secret = strim(dhchap_secret); in nvmet_auth_set_key()
63 host->dhchap_ctrl_key_hash = key_hash; in nvmet_auth_set_key()
65 kfree(host->dhchap_secret); in nvmet_auth_set_key()
66 host->dhchap_secret = strim(dhchap_secret); in nvmet_auth_set_key()
67 host->dhchap_key_hash = key_hash; in nvmet_auth_set_key()
73 int nvmet_setup_dhgroup(struct nvmet_ctrl *ctrl, u8 dhgroup_id) in nvmet_setup_dhgroup() argument
78 pr_debug("%s: ctrl %d selecting dhgroup %d\n", in nvmet_setup_dhgroup()
79 __func__, ctrl->cntlid, dhgroup_id); in nvmet_setup_dhgroup()
81 if (ctrl->dh_tfm) { in nvmet_setup_dhgroup()
82 if (ctrl->dh_gid == dhgroup_id) { in nvmet_setup_dhgroup()
83 pr_debug("%s: ctrl %d reuse existing DH group %d\n", in nvmet_setup_dhgroup()
84 __func__, ctrl->cntlid, dhgroup_id); in nvmet_setup_dhgroup()
87 crypto_free_kpp(ctrl->dh_tfm); in nvmet_setup_dhgroup()
88 ctrl->dh_tfm = NULL; in nvmet_setup_dhgroup()
89 ctrl->dh_gid = 0; in nvmet_setup_dhgroup()
97 pr_debug("%s: ctrl %d invalid DH group %d\n", in nvmet_setup_dhgroup()
98 __func__, ctrl->cntlid, dhgroup_id); in nvmet_setup_dhgroup()
99 return -EINVAL; in nvmet_setup_dhgroup()
101 ctrl->dh_tfm = crypto_alloc_kpp(dhgroup_kpp, 0, 0); in nvmet_setup_dhgroup()
102 if (IS_ERR(ctrl->dh_tfm)) { in nvmet_setup_dhgroup()
103 pr_debug("%s: ctrl %d failed to setup DH group %d, err %ld\n", in nvmet_setup_dhgroup()
104 __func__, ctrl->cntlid, dhgroup_id, in nvmet_setup_dhgroup()
105 PTR_ERR(ctrl->dh_tfm)); in nvmet_setup_dhgroup()
106 ret = PTR_ERR(ctrl->dh_tfm); in nvmet_setup_dhgroup()
107 ctrl->dh_tfm = NULL; in nvmet_setup_dhgroup()
108 ctrl->dh_gid = 0; in nvmet_setup_dhgroup()
110 ctrl->dh_gid = dhgroup_id; in nvmet_setup_dhgroup()
111 pr_debug("%s: ctrl %d setup DH group %d\n", in nvmet_setup_dhgroup()
112 __func__, ctrl->cntlid, ctrl->dh_gid); in nvmet_setup_dhgroup()
113 ret = nvme_auth_gen_privkey(ctrl->dh_tfm, ctrl->dh_gid); in nvmet_setup_dhgroup()
115 pr_debug("%s: ctrl %d failed to generate private key, err %d\n", in nvmet_setup_dhgroup()
116 __func__, ctrl->cntlid, ret); in nvmet_setup_dhgroup()
117 kfree_sensitive(ctrl->dh_key); in nvmet_setup_dhgroup()
118 ctrl->dh_key = NULL; in nvmet_setup_dhgroup()
121 ctrl->dh_keysize = crypto_kpp_maxsize(ctrl->dh_tfm); in nvmet_setup_dhgroup()
122 kfree_sensitive(ctrl->dh_key); in nvmet_setup_dhgroup()
123 ctrl->dh_key = kzalloc(ctrl->dh_keysize, GFP_KERNEL); in nvmet_setup_dhgroup()
124 if (!ctrl->dh_key) { in nvmet_setup_dhgroup()
125 pr_warn("ctrl %d failed to allocate public key\n", in nvmet_setup_dhgroup()
126 ctrl->cntlid); in nvmet_setup_dhgroup()
127 return -ENOMEM; in nvmet_setup_dhgroup()
129 ret = nvme_auth_gen_pubkey(ctrl->dh_tfm, ctrl->dh_key, in nvmet_setup_dhgroup()
130 ctrl->dh_keysize); in nvmet_setup_dhgroup()
132 pr_warn("ctrl %d failed to generate public key\n", in nvmet_setup_dhgroup()
133 ctrl->cntlid); in nvmet_setup_dhgroup()
134 kfree(ctrl->dh_key); in nvmet_setup_dhgroup()
135 ctrl->dh_key = NULL; in nvmet_setup_dhgroup()
142 u8 nvmet_setup_auth(struct nvmet_ctrl *ctrl) in nvmet_setup_auth() argument
149 if (nvmet_is_disc_subsys(ctrl->subsys)) in nvmet_setup_auth()
152 if (ctrl->subsys->allow_any_host) in nvmet_setup_auth()
155 list_for_each_entry(p, &ctrl->subsys->hosts, entry) { in nvmet_setup_auth()
156 pr_debug("check %s\n", nvmet_host_name(p->host)); in nvmet_setup_auth()
157 if (strcmp(nvmet_host_name(p->host), ctrl->hostnqn)) in nvmet_setup_auth()
159 host = p->host; in nvmet_setup_auth()
163 pr_debug("host %s not found\n", ctrl->hostnqn); in nvmet_setup_auth()
168 ret = nvmet_setup_dhgroup(ctrl, host->dhchap_dhgroup_id); in nvmet_setup_auth()
175 if (!host->dhchap_secret) { in nvmet_setup_auth()
180 if (host->dhchap_hash_id == ctrl->shash_id) { in nvmet_setup_auth()
181 pr_debug("Re-use existing hash ID %d\n", in nvmet_setup_auth()
182 ctrl->shash_id); in nvmet_setup_auth()
184 ctrl->shash_id = host->dhchap_hash_id; in nvmet_setup_auth()
187 /* Skip the 'DHHC-1:XX:' prefix */ in nvmet_setup_auth()
188 nvme_auth_free_key(ctrl->host_key); in nvmet_setup_auth()
189 ctrl->host_key = nvme_auth_extract_key(host->dhchap_secret + 10, in nvmet_setup_auth()
190 host->dhchap_key_hash); in nvmet_setup_auth()
191 if (IS_ERR(ctrl->host_key)) { in nvmet_setup_auth()
193 ctrl->host_key = NULL; in nvmet_setup_auth()
197 ctrl->host_key->hash > 0 ? in nvmet_setup_auth()
198 nvme_auth_hmac_name(ctrl->host_key->hash) : "none", in nvmet_setup_auth()
199 (int)ctrl->host_key->len, ctrl->host_key->key); in nvmet_setup_auth()
201 nvme_auth_free_key(ctrl->ctrl_key); in nvmet_setup_auth()
202 if (!host->dhchap_ctrl_secret) { in nvmet_setup_auth()
203 ctrl->ctrl_key = NULL; in nvmet_setup_auth()
207 ctrl->ctrl_key = nvme_auth_extract_key(host->dhchap_ctrl_secret + 10, in nvmet_setup_auth()
208 host->dhchap_ctrl_key_hash); in nvmet_setup_auth()
209 if (IS_ERR(ctrl->ctrl_key)) { in nvmet_setup_auth()
211 ctrl->ctrl_key = NULL; in nvmet_setup_auth()
214 pr_debug("%s: using ctrl hash %s key %*ph\n", __func__, in nvmet_setup_auth()
215 ctrl->ctrl_key->hash > 0 ? in nvmet_setup_auth()
216 nvme_auth_hmac_name(ctrl->ctrl_key->hash) : "none", in nvmet_setup_auth()
217 (int)ctrl->ctrl_key->len, ctrl->ctrl_key->key); in nvmet_setup_auth()
221 if (ctrl->host_key) { in nvmet_setup_auth()
222 nvme_auth_free_key(ctrl->host_key); in nvmet_setup_auth()
223 ctrl->host_key = NULL; in nvmet_setup_auth()
225 ctrl->shash_id = 0; in nvmet_setup_auth()
235 cancel_delayed_work(&sq->auth_expired_work); in nvmet_auth_sq_free()
236 kfree(sq->dhchap_c1); in nvmet_auth_sq_free()
237 sq->dhchap_c1 = NULL; in nvmet_auth_sq_free()
238 kfree(sq->dhchap_c2); in nvmet_auth_sq_free()
239 sq->dhchap_c2 = NULL; in nvmet_auth_sq_free()
240 kfree(sq->dhchap_skey); in nvmet_auth_sq_free()
241 sq->dhchap_skey = NULL; in nvmet_auth_sq_free()
244 void nvmet_destroy_auth(struct nvmet_ctrl *ctrl) in nvmet_destroy_auth() argument
246 ctrl->shash_id = 0; in nvmet_destroy_auth()
248 if (ctrl->dh_tfm) { in nvmet_destroy_auth()
249 crypto_free_kpp(ctrl->dh_tfm); in nvmet_destroy_auth()
250 ctrl->dh_tfm = NULL; in nvmet_destroy_auth()
251 ctrl->dh_gid = 0; in nvmet_destroy_auth()
253 kfree_sensitive(ctrl->dh_key); in nvmet_destroy_auth()
254 ctrl->dh_key = NULL; in nvmet_destroy_auth()
256 if (ctrl->host_key) { in nvmet_destroy_auth()
257 nvme_auth_free_key(ctrl->host_key); in nvmet_destroy_auth()
258 ctrl->host_key = NULL; in nvmet_destroy_auth()
260 if (ctrl->ctrl_key) { in nvmet_destroy_auth()
261 nvme_auth_free_key(ctrl->ctrl_key); in nvmet_destroy_auth()
262 ctrl->ctrl_key = NULL; in nvmet_destroy_auth()
268 if (req->sq->ctrl->host_key && in nvmet_check_auth_status()
269 !req->sq->authenticated) in nvmet_check_auth_status()
279 struct nvmet_ctrl *ctrl = req->sq->ctrl; in nvmet_auth_host_hash() local
281 u8 *challenge = req->sq->dhchap_c1; in nvmet_auth_host_hash()
286 hash_name = nvme_auth_hmac_name(ctrl->shash_id); in nvmet_auth_host_hash()
288 pr_warn("Hash ID %d invalid\n", ctrl->shash_id); in nvmet_auth_host_hash()
289 return -EINVAL; in nvmet_auth_host_hash()
299 pr_err("%s: hash len mismatch (len %d digest %d)\n", in nvmet_auth_host_hash()
302 ret = -EINVAL; in nvmet_auth_host_hash()
306 transformed_key = nvme_auth_transform_key(ctrl->host_key, in nvmet_auth_host_hash()
307 ctrl->hostnqn); in nvmet_auth_host_hash()
313 ret = crypto_shash_setkey(shash_tfm, transformed_key->key, in nvmet_auth_host_hash()
314 transformed_key->len); in nvmet_auth_host_hash()
318 if (ctrl->dh_gid != NVME_AUTH_DHGROUP_NULL) { in nvmet_auth_host_hash()
321 ret = -ENOMEM; in nvmet_auth_host_hash()
324 ret = nvme_auth_augmented_challenge(ctrl->shash_id, in nvmet_auth_host_hash()
325 req->sq->dhchap_skey, in nvmet_auth_host_hash()
326 req->sq->dhchap_skey_len, in nvmet_auth_host_hash()
327 req->sq->dhchap_c1, in nvmet_auth_host_hash()
333 pr_debug("ctrl %d qid %d host response seq %u transaction %d\n", in nvmet_auth_host_hash()
334 ctrl->cntlid, req->sq->qid, req->sq->dhchap_s1, in nvmet_auth_host_hash()
335 req->sq->dhchap_tid); in nvmet_auth_host_hash()
340 ret = -ENOMEM; in nvmet_auth_host_hash()
343 shash->tfm = shash_tfm; in nvmet_auth_host_hash()
350 put_unaligned_le32(req->sq->dhchap_s1, buf); in nvmet_auth_host_hash()
354 put_unaligned_le16(req->sq->dhchap_tid, buf); in nvmet_auth_host_hash()
365 ret = crypto_shash_update(shash, ctrl->hostnqn, strlen(ctrl->hostnqn)); in nvmet_auth_host_hash()
371 ret = crypto_shash_update(shash, ctrl->subsysnqn, in nvmet_auth_host_hash()
372 strlen(ctrl->subsysnqn)); in nvmet_auth_host_hash()
379 if (challenge != req->sq->dhchap_c1) in nvmet_auth_host_hash()
393 struct nvmet_ctrl *ctrl = req->sq->ctrl; in nvmet_auth_ctrl_hash() local
395 u8 *challenge = req->sq->dhchap_c2; in nvmet_auth_ctrl_hash()
400 hash_name = nvme_auth_hmac_name(ctrl->shash_id); in nvmet_auth_ctrl_hash()
402 pr_warn("Hash ID %d invalid\n", ctrl->shash_id); in nvmet_auth_ctrl_hash()
403 return -EINVAL; in nvmet_auth_ctrl_hash()
413 pr_debug("%s: hash len mismatch (len %d digest %d)\n", in nvmet_auth_ctrl_hash()
416 ret = -EINVAL; in nvmet_auth_ctrl_hash()
420 transformed_key = nvme_auth_transform_key(ctrl->ctrl_key, in nvmet_auth_ctrl_hash()
421 ctrl->subsysnqn); in nvmet_auth_ctrl_hash()
427 ret = crypto_shash_setkey(shash_tfm, transformed_key->key, in nvmet_auth_ctrl_hash()
428 transformed_key->len); in nvmet_auth_ctrl_hash()
432 if (ctrl->dh_gid != NVME_AUTH_DHGROUP_NULL) { in nvmet_auth_ctrl_hash()
435 ret = -ENOMEM; in nvmet_auth_ctrl_hash()
438 ret = nvme_auth_augmented_challenge(ctrl->shash_id, in nvmet_auth_ctrl_hash()
439 req->sq->dhchap_skey, in nvmet_auth_ctrl_hash()
440 req->sq->dhchap_skey_len, in nvmet_auth_ctrl_hash()
441 req->sq->dhchap_c2, in nvmet_auth_ctrl_hash()
450 ret = -ENOMEM; in nvmet_auth_ctrl_hash()
453 shash->tfm = shash_tfm; in nvmet_auth_ctrl_hash()
461 put_unaligned_le32(req->sq->dhchap_s2, buf); in nvmet_auth_ctrl_hash()
465 put_unaligned_le16(req->sq->dhchap_tid, buf); in nvmet_auth_ctrl_hash()
476 ret = crypto_shash_update(shash, ctrl->subsysnqn, in nvmet_auth_ctrl_hash()
477 strlen(ctrl->subsysnqn)); in nvmet_auth_ctrl_hash()
483 ret = crypto_shash_update(shash, ctrl->hostnqn, strlen(ctrl->hostnqn)); in nvmet_auth_ctrl_hash()
490 if (challenge != req->sq->dhchap_c2) in nvmet_auth_ctrl_hash()
502 struct nvmet_ctrl *ctrl = req->sq->ctrl; in nvmet_auth_ctrl_exponential() local
505 if (!ctrl->dh_key) { in nvmet_auth_ctrl_exponential()
506 pr_warn("ctrl %d no DH public key!\n", ctrl->cntlid); in nvmet_auth_ctrl_exponential()
507 return -ENOKEY; in nvmet_auth_ctrl_exponential()
509 if (buf_size != ctrl->dh_keysize) { in nvmet_auth_ctrl_exponential()
510 pr_warn("ctrl %d DH public key size mismatch, need %zu is %d\n", in nvmet_auth_ctrl_exponential()
511 ctrl->cntlid, ctrl->dh_keysize, buf_size); in nvmet_auth_ctrl_exponential()
512 ret = -EINVAL; in nvmet_auth_ctrl_exponential()
514 memcpy(buf, ctrl->dh_key, buf_size); in nvmet_auth_ctrl_exponential()
515 pr_debug("%s: ctrl %d public key %*ph\n", __func__, in nvmet_auth_ctrl_exponential()
516 ctrl->cntlid, (int)buf_size, buf); in nvmet_auth_ctrl_exponential()
525 struct nvmet_ctrl *ctrl = req->sq->ctrl; in nvmet_auth_ctrl_sesskey() local
528 req->sq->dhchap_skey_len = ctrl->dh_keysize; in nvmet_auth_ctrl_sesskey()
529 req->sq->dhchap_skey = kzalloc(req->sq->dhchap_skey_len, GFP_KERNEL); in nvmet_auth_ctrl_sesskey()
530 if (!req->sq->dhchap_skey) in nvmet_auth_ctrl_sesskey()
531 return -ENOMEM; in nvmet_auth_ctrl_sesskey()
532 ret = nvme_auth_gen_shared_secret(ctrl->dh_tfm, in nvmet_auth_ctrl_sesskey()
534 req->sq->dhchap_skey, in nvmet_auth_ctrl_sesskey()
535 req->sq->dhchap_skey_len); in nvmet_auth_ctrl_sesskey()
540 (int)req->sq->dhchap_skey_len, in nvmet_auth_ctrl_sesskey()
541 req->sq->dhchap_skey); in nvmet_auth_ctrl_sesskey()