1*db1312ddSHannes Reinecke // SPDX-License-Identifier: GPL-2.0 2*db1312ddSHannes Reinecke /* 3*db1312ddSHannes Reinecke * NVMe over Fabrics DH-HMAC-CHAP authentication command handling. 4*db1312ddSHannes Reinecke * Copyright (c) 2020 Hannes Reinecke, SUSE Software Solutions. 5*db1312ddSHannes Reinecke * All rights reserved. 6*db1312ddSHannes Reinecke */ 7*db1312ddSHannes Reinecke #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 8*db1312ddSHannes Reinecke #include <linux/blkdev.h> 9*db1312ddSHannes Reinecke #include <linux/random.h> 10*db1312ddSHannes Reinecke #include <linux/nvme-auth.h> 11*db1312ddSHannes Reinecke #include <crypto/hash.h> 12*db1312ddSHannes Reinecke #include <crypto/kpp.h> 13*db1312ddSHannes Reinecke #include "nvmet.h" 14*db1312ddSHannes Reinecke 15*db1312ddSHannes Reinecke void nvmet_init_auth(struct nvmet_ctrl *ctrl, struct nvmet_req *req) 16*db1312ddSHannes Reinecke { 17*db1312ddSHannes Reinecke u32 result = le32_to_cpu(req->cqe->result.u32); 18*db1312ddSHannes Reinecke 19*db1312ddSHannes Reinecke /* Initialize in-band authentication */ 20*db1312ddSHannes Reinecke req->sq->authenticated = false; 21*db1312ddSHannes Reinecke req->sq->dhchap_step = NVME_AUTH_DHCHAP_MESSAGE_NEGOTIATE; 22*db1312ddSHannes Reinecke result |= (u32)NVME_CONNECT_AUTHREQ_ATR << 16; 23*db1312ddSHannes Reinecke req->cqe->result.u32 = cpu_to_le32(result); 24*db1312ddSHannes Reinecke } 25*db1312ddSHannes Reinecke 26*db1312ddSHannes Reinecke static u16 nvmet_auth_negotiate(struct nvmet_req *req, void *d) 27*db1312ddSHannes Reinecke { 28*db1312ddSHannes Reinecke struct nvmet_ctrl *ctrl = req->sq->ctrl; 29*db1312ddSHannes Reinecke struct nvmf_auth_dhchap_negotiate_data *data = d; 30*db1312ddSHannes Reinecke int i, hash_id = 0, fallback_hash_id = 0, dhgid; 31*db1312ddSHannes Reinecke 32*db1312ddSHannes Reinecke pr_debug("%s: ctrl %d qid %d: data sc_d %d napd %d authid %d halen %d dhlen %d\n", 33*db1312ddSHannes Reinecke __func__, ctrl->cntlid, req->sq->qid, 34*db1312ddSHannes Reinecke data->sc_c, data->napd, data->auth_protocol[0].dhchap.authid, 35*db1312ddSHannes Reinecke data->auth_protocol[0].dhchap.halen, 36*db1312ddSHannes Reinecke data->auth_protocol[0].dhchap.dhlen); 37*db1312ddSHannes Reinecke req->sq->dhchap_tid = le16_to_cpu(data->t_id); 38*db1312ddSHannes Reinecke if (data->sc_c) 39*db1312ddSHannes Reinecke return NVME_AUTH_DHCHAP_FAILURE_CONCAT_MISMATCH; 40*db1312ddSHannes Reinecke 41*db1312ddSHannes Reinecke if (data->napd != 1) 42*db1312ddSHannes Reinecke return NVME_AUTH_DHCHAP_FAILURE_HASH_UNUSABLE; 43*db1312ddSHannes Reinecke 44*db1312ddSHannes Reinecke if (data->auth_protocol[0].dhchap.authid != 45*db1312ddSHannes Reinecke NVME_AUTH_DHCHAP_AUTH_ID) 46*db1312ddSHannes Reinecke return NVME_AUTH_DHCHAP_FAILURE_INCORRECT_PAYLOAD; 47*db1312ddSHannes Reinecke 48*db1312ddSHannes Reinecke for (i = 0; i < data->auth_protocol[0].dhchap.halen; i++) { 49*db1312ddSHannes Reinecke u8 host_hmac_id = data->auth_protocol[0].dhchap.idlist[i]; 50*db1312ddSHannes Reinecke 51*db1312ddSHannes Reinecke if (!fallback_hash_id && 52*db1312ddSHannes Reinecke crypto_has_shash(nvme_auth_hmac_name(host_hmac_id), 0, 0)) 53*db1312ddSHannes Reinecke fallback_hash_id = host_hmac_id; 54*db1312ddSHannes Reinecke if (ctrl->shash_id != host_hmac_id) 55*db1312ddSHannes Reinecke continue; 56*db1312ddSHannes Reinecke hash_id = ctrl->shash_id; 57*db1312ddSHannes Reinecke break; 58*db1312ddSHannes Reinecke } 59*db1312ddSHannes Reinecke if (hash_id == 0) { 60*db1312ddSHannes Reinecke if (fallback_hash_id == 0) { 61*db1312ddSHannes Reinecke pr_debug("%s: ctrl %d qid %d: no usable hash found\n", 62*db1312ddSHannes Reinecke __func__, ctrl->cntlid, req->sq->qid); 63*db1312ddSHannes Reinecke return NVME_AUTH_DHCHAP_FAILURE_HASH_UNUSABLE; 64*db1312ddSHannes Reinecke } 65*db1312ddSHannes Reinecke pr_debug("%s: ctrl %d qid %d: no usable hash found, falling back to %s\n", 66*db1312ddSHannes Reinecke __func__, ctrl->cntlid, req->sq->qid, 67*db1312ddSHannes Reinecke nvme_auth_hmac_name(fallback_hash_id)); 68*db1312ddSHannes Reinecke ctrl->shash_id = fallback_hash_id; 69*db1312ddSHannes Reinecke } 70*db1312ddSHannes Reinecke 71*db1312ddSHannes Reinecke dhgid = -1; 72*db1312ddSHannes Reinecke for (i = 0; i < data->auth_protocol[0].dhchap.dhlen; i++) { 73*db1312ddSHannes Reinecke int tmp_dhgid = data->auth_protocol[0].dhchap.idlist[i + 30]; 74*db1312ddSHannes Reinecke 75*db1312ddSHannes Reinecke if (tmp_dhgid == NVME_AUTH_DHGROUP_NULL) { 76*db1312ddSHannes Reinecke dhgid = tmp_dhgid; 77*db1312ddSHannes Reinecke break; 78*db1312ddSHannes Reinecke } 79*db1312ddSHannes Reinecke } 80*db1312ddSHannes Reinecke if (dhgid < 0) { 81*db1312ddSHannes Reinecke pr_debug("%s: ctrl %d qid %d: no usable DH group found\n", 82*db1312ddSHannes Reinecke __func__, ctrl->cntlid, req->sq->qid); 83*db1312ddSHannes Reinecke return NVME_AUTH_DHCHAP_FAILURE_DHGROUP_UNUSABLE; 84*db1312ddSHannes Reinecke } 85*db1312ddSHannes Reinecke pr_debug("%s: ctrl %d qid %d: selected DH group %s (%d)\n", 86*db1312ddSHannes Reinecke __func__, ctrl->cntlid, req->sq->qid, 87*db1312ddSHannes Reinecke nvme_auth_dhgroup_name(dhgid), dhgid); 88*db1312ddSHannes Reinecke return 0; 89*db1312ddSHannes Reinecke } 90*db1312ddSHannes Reinecke 91*db1312ddSHannes Reinecke static u16 nvmet_auth_reply(struct nvmet_req *req, void *d) 92*db1312ddSHannes Reinecke { 93*db1312ddSHannes Reinecke struct nvmet_ctrl *ctrl = req->sq->ctrl; 94*db1312ddSHannes Reinecke struct nvmf_auth_dhchap_reply_data *data = d; 95*db1312ddSHannes Reinecke u16 dhvlen = le16_to_cpu(data->dhvlen); 96*db1312ddSHannes Reinecke u8 *response; 97*db1312ddSHannes Reinecke 98*db1312ddSHannes Reinecke pr_debug("%s: ctrl %d qid %d: data hl %d cvalid %d dhvlen %u\n", 99*db1312ddSHannes Reinecke __func__, ctrl->cntlid, req->sq->qid, 100*db1312ddSHannes Reinecke data->hl, data->cvalid, dhvlen); 101*db1312ddSHannes Reinecke 102*db1312ddSHannes Reinecke if (dhvlen) { 103*db1312ddSHannes Reinecke return NVME_AUTH_DHCHAP_FAILURE_INCORRECT_PAYLOAD; 104*db1312ddSHannes Reinecke } 105*db1312ddSHannes Reinecke 106*db1312ddSHannes Reinecke response = kmalloc(data->hl, GFP_KERNEL); 107*db1312ddSHannes Reinecke if (!response) 108*db1312ddSHannes Reinecke return NVME_AUTH_DHCHAP_FAILURE_FAILED; 109*db1312ddSHannes Reinecke 110*db1312ddSHannes Reinecke if (!ctrl->host_key) { 111*db1312ddSHannes Reinecke pr_warn("ctrl %d qid %d no host key\n", 112*db1312ddSHannes Reinecke ctrl->cntlid, req->sq->qid); 113*db1312ddSHannes Reinecke kfree(response); 114*db1312ddSHannes Reinecke return NVME_AUTH_DHCHAP_FAILURE_FAILED; 115*db1312ddSHannes Reinecke } 116*db1312ddSHannes Reinecke if (nvmet_auth_host_hash(req, response, data->hl) < 0) { 117*db1312ddSHannes Reinecke pr_debug("ctrl %d qid %d host hash failed\n", 118*db1312ddSHannes Reinecke ctrl->cntlid, req->sq->qid); 119*db1312ddSHannes Reinecke kfree(response); 120*db1312ddSHannes Reinecke return NVME_AUTH_DHCHAP_FAILURE_FAILED; 121*db1312ddSHannes Reinecke } 122*db1312ddSHannes Reinecke 123*db1312ddSHannes Reinecke if (memcmp(data->rval, response, data->hl)) { 124*db1312ddSHannes Reinecke pr_info("ctrl %d qid %d host response mismatch\n", 125*db1312ddSHannes Reinecke ctrl->cntlid, req->sq->qid); 126*db1312ddSHannes Reinecke kfree(response); 127*db1312ddSHannes Reinecke return NVME_AUTH_DHCHAP_FAILURE_FAILED; 128*db1312ddSHannes Reinecke } 129*db1312ddSHannes Reinecke kfree(response); 130*db1312ddSHannes Reinecke pr_debug("%s: ctrl %d qid %d host authenticated\n", 131*db1312ddSHannes Reinecke __func__, ctrl->cntlid, req->sq->qid); 132*db1312ddSHannes Reinecke if (data->cvalid) { 133*db1312ddSHannes Reinecke req->sq->dhchap_c2 = kmalloc(data->hl, GFP_KERNEL); 134*db1312ddSHannes Reinecke if (!req->sq->dhchap_c2) 135*db1312ddSHannes Reinecke return NVME_AUTH_DHCHAP_FAILURE_FAILED; 136*db1312ddSHannes Reinecke memcpy(req->sq->dhchap_c2, data->rval + data->hl, data->hl); 137*db1312ddSHannes Reinecke 138*db1312ddSHannes Reinecke pr_debug("%s: ctrl %d qid %d challenge %*ph\n", 139*db1312ddSHannes Reinecke __func__, ctrl->cntlid, req->sq->qid, data->hl, 140*db1312ddSHannes Reinecke req->sq->dhchap_c2); 141*db1312ddSHannes Reinecke req->sq->dhchap_s2 = le32_to_cpu(data->seqnum); 142*db1312ddSHannes Reinecke } else { 143*db1312ddSHannes Reinecke req->sq->authenticated = true; 144*db1312ddSHannes Reinecke req->sq->dhchap_c2 = NULL; 145*db1312ddSHannes Reinecke } 146*db1312ddSHannes Reinecke 147*db1312ddSHannes Reinecke return 0; 148*db1312ddSHannes Reinecke } 149*db1312ddSHannes Reinecke 150*db1312ddSHannes Reinecke static u16 nvmet_auth_failure2(struct nvmet_req *req, void *d) 151*db1312ddSHannes Reinecke { 152*db1312ddSHannes Reinecke struct nvmf_auth_dhchap_failure_data *data = d; 153*db1312ddSHannes Reinecke 154*db1312ddSHannes Reinecke return data->rescode_exp; 155*db1312ddSHannes Reinecke } 156*db1312ddSHannes Reinecke 157*db1312ddSHannes Reinecke void nvmet_execute_auth_send(struct nvmet_req *req) 158*db1312ddSHannes Reinecke { 159*db1312ddSHannes Reinecke struct nvmet_ctrl *ctrl = req->sq->ctrl; 160*db1312ddSHannes Reinecke struct nvmf_auth_dhchap_success2_data *data; 161*db1312ddSHannes Reinecke void *d; 162*db1312ddSHannes Reinecke u32 tl; 163*db1312ddSHannes Reinecke u16 status = 0; 164*db1312ddSHannes Reinecke 165*db1312ddSHannes Reinecke if (req->cmd->auth_send.secp != NVME_AUTH_DHCHAP_PROTOCOL_IDENTIFIER) { 166*db1312ddSHannes Reinecke status = NVME_SC_INVALID_FIELD | NVME_SC_DNR; 167*db1312ddSHannes Reinecke req->error_loc = 168*db1312ddSHannes Reinecke offsetof(struct nvmf_auth_send_command, secp); 169*db1312ddSHannes Reinecke goto done; 170*db1312ddSHannes Reinecke } 171*db1312ddSHannes Reinecke if (req->cmd->auth_send.spsp0 != 0x01) { 172*db1312ddSHannes Reinecke status = NVME_SC_INVALID_FIELD | NVME_SC_DNR; 173*db1312ddSHannes Reinecke req->error_loc = 174*db1312ddSHannes Reinecke offsetof(struct nvmf_auth_send_command, spsp0); 175*db1312ddSHannes Reinecke goto done; 176*db1312ddSHannes Reinecke } 177*db1312ddSHannes Reinecke if (req->cmd->auth_send.spsp1 != 0x01) { 178*db1312ddSHannes Reinecke status = NVME_SC_INVALID_FIELD | NVME_SC_DNR; 179*db1312ddSHannes Reinecke req->error_loc = 180*db1312ddSHannes Reinecke offsetof(struct nvmf_auth_send_command, spsp1); 181*db1312ddSHannes Reinecke goto done; 182*db1312ddSHannes Reinecke } 183*db1312ddSHannes Reinecke tl = le32_to_cpu(req->cmd->auth_send.tl); 184*db1312ddSHannes Reinecke if (!tl) { 185*db1312ddSHannes Reinecke status = NVME_SC_INVALID_FIELD | NVME_SC_DNR; 186*db1312ddSHannes Reinecke req->error_loc = 187*db1312ddSHannes Reinecke offsetof(struct nvmf_auth_send_command, tl); 188*db1312ddSHannes Reinecke goto done; 189*db1312ddSHannes Reinecke } 190*db1312ddSHannes Reinecke if (!nvmet_check_transfer_len(req, tl)) { 191*db1312ddSHannes Reinecke pr_debug("%s: transfer length mismatch (%u)\n", __func__, tl); 192*db1312ddSHannes Reinecke return; 193*db1312ddSHannes Reinecke } 194*db1312ddSHannes Reinecke 195*db1312ddSHannes Reinecke d = kmalloc(tl, GFP_KERNEL); 196*db1312ddSHannes Reinecke if (!d) { 197*db1312ddSHannes Reinecke status = NVME_SC_INTERNAL; 198*db1312ddSHannes Reinecke goto done; 199*db1312ddSHannes Reinecke } 200*db1312ddSHannes Reinecke 201*db1312ddSHannes Reinecke status = nvmet_copy_from_sgl(req, 0, d, tl); 202*db1312ddSHannes Reinecke if (status) { 203*db1312ddSHannes Reinecke kfree(d); 204*db1312ddSHannes Reinecke goto done; 205*db1312ddSHannes Reinecke } 206*db1312ddSHannes Reinecke 207*db1312ddSHannes Reinecke data = d; 208*db1312ddSHannes Reinecke pr_debug("%s: ctrl %d qid %d type %d id %d step %x\n", __func__, 209*db1312ddSHannes Reinecke ctrl->cntlid, req->sq->qid, data->auth_type, data->auth_id, 210*db1312ddSHannes Reinecke req->sq->dhchap_step); 211*db1312ddSHannes Reinecke if (data->auth_type != NVME_AUTH_COMMON_MESSAGES && 212*db1312ddSHannes Reinecke data->auth_type != NVME_AUTH_DHCHAP_MESSAGES) 213*db1312ddSHannes Reinecke goto done_failure1; 214*db1312ddSHannes Reinecke if (data->auth_type == NVME_AUTH_COMMON_MESSAGES) { 215*db1312ddSHannes Reinecke if (data->auth_id == NVME_AUTH_DHCHAP_MESSAGE_NEGOTIATE) { 216*db1312ddSHannes Reinecke /* Restart negotiation */ 217*db1312ddSHannes Reinecke pr_debug("%s: ctrl %d qid %d reset negotiation\n", __func__, 218*db1312ddSHannes Reinecke ctrl->cntlid, req->sq->qid); 219*db1312ddSHannes Reinecke if (!req->sq->qid) { 220*db1312ddSHannes Reinecke status = nvmet_setup_auth(ctrl); 221*db1312ddSHannes Reinecke if (status < 0) { 222*db1312ddSHannes Reinecke pr_err("ctrl %d qid 0 failed to setup" 223*db1312ddSHannes Reinecke "re-authentication", 224*db1312ddSHannes Reinecke ctrl->cntlid); 225*db1312ddSHannes Reinecke goto done_failure1; 226*db1312ddSHannes Reinecke } 227*db1312ddSHannes Reinecke } 228*db1312ddSHannes Reinecke req->sq->dhchap_step = NVME_AUTH_DHCHAP_MESSAGE_NEGOTIATE; 229*db1312ddSHannes Reinecke } else if (data->auth_id != req->sq->dhchap_step) 230*db1312ddSHannes Reinecke goto done_failure1; 231*db1312ddSHannes Reinecke /* Validate negotiation parameters */ 232*db1312ddSHannes Reinecke status = nvmet_auth_negotiate(req, d); 233*db1312ddSHannes Reinecke if (status == 0) 234*db1312ddSHannes Reinecke req->sq->dhchap_step = 235*db1312ddSHannes Reinecke NVME_AUTH_DHCHAP_MESSAGE_CHALLENGE; 236*db1312ddSHannes Reinecke else { 237*db1312ddSHannes Reinecke req->sq->dhchap_step = 238*db1312ddSHannes Reinecke NVME_AUTH_DHCHAP_MESSAGE_FAILURE1; 239*db1312ddSHannes Reinecke req->sq->dhchap_status = status; 240*db1312ddSHannes Reinecke status = 0; 241*db1312ddSHannes Reinecke } 242*db1312ddSHannes Reinecke goto done_kfree; 243*db1312ddSHannes Reinecke } 244*db1312ddSHannes Reinecke if (data->auth_id != req->sq->dhchap_step) { 245*db1312ddSHannes Reinecke pr_debug("%s: ctrl %d qid %d step mismatch (%d != %d)\n", 246*db1312ddSHannes Reinecke __func__, ctrl->cntlid, req->sq->qid, 247*db1312ddSHannes Reinecke data->auth_id, req->sq->dhchap_step); 248*db1312ddSHannes Reinecke goto done_failure1; 249*db1312ddSHannes Reinecke } 250*db1312ddSHannes Reinecke if (le16_to_cpu(data->t_id) != req->sq->dhchap_tid) { 251*db1312ddSHannes Reinecke pr_debug("%s: ctrl %d qid %d invalid transaction %d (expected %d)\n", 252*db1312ddSHannes Reinecke __func__, ctrl->cntlid, req->sq->qid, 253*db1312ddSHannes Reinecke le16_to_cpu(data->t_id), 254*db1312ddSHannes Reinecke req->sq->dhchap_tid); 255*db1312ddSHannes Reinecke req->sq->dhchap_step = 256*db1312ddSHannes Reinecke NVME_AUTH_DHCHAP_MESSAGE_FAILURE1; 257*db1312ddSHannes Reinecke req->sq->dhchap_status = 258*db1312ddSHannes Reinecke NVME_AUTH_DHCHAP_FAILURE_INCORRECT_PAYLOAD; 259*db1312ddSHannes Reinecke goto done_kfree; 260*db1312ddSHannes Reinecke } 261*db1312ddSHannes Reinecke 262*db1312ddSHannes Reinecke switch (data->auth_id) { 263*db1312ddSHannes Reinecke case NVME_AUTH_DHCHAP_MESSAGE_REPLY: 264*db1312ddSHannes Reinecke status = nvmet_auth_reply(req, d); 265*db1312ddSHannes Reinecke if (status == 0) 266*db1312ddSHannes Reinecke req->sq->dhchap_step = 267*db1312ddSHannes Reinecke NVME_AUTH_DHCHAP_MESSAGE_SUCCESS1; 268*db1312ddSHannes Reinecke else { 269*db1312ddSHannes Reinecke req->sq->dhchap_step = 270*db1312ddSHannes Reinecke NVME_AUTH_DHCHAP_MESSAGE_FAILURE1; 271*db1312ddSHannes Reinecke req->sq->dhchap_status = status; 272*db1312ddSHannes Reinecke status = 0; 273*db1312ddSHannes Reinecke } 274*db1312ddSHannes Reinecke goto done_kfree; 275*db1312ddSHannes Reinecke break; 276*db1312ddSHannes Reinecke case NVME_AUTH_DHCHAP_MESSAGE_SUCCESS2: 277*db1312ddSHannes Reinecke req->sq->authenticated = true; 278*db1312ddSHannes Reinecke pr_debug("%s: ctrl %d qid %d ctrl authenticated\n", 279*db1312ddSHannes Reinecke __func__, ctrl->cntlid, req->sq->qid); 280*db1312ddSHannes Reinecke goto done_kfree; 281*db1312ddSHannes Reinecke break; 282*db1312ddSHannes Reinecke case NVME_AUTH_DHCHAP_MESSAGE_FAILURE2: 283*db1312ddSHannes Reinecke status = nvmet_auth_failure2(req, d); 284*db1312ddSHannes Reinecke if (status) { 285*db1312ddSHannes Reinecke pr_warn("ctrl %d qid %d: authentication failed (%d)\n", 286*db1312ddSHannes Reinecke ctrl->cntlid, req->sq->qid, status); 287*db1312ddSHannes Reinecke req->sq->dhchap_status = status; 288*db1312ddSHannes Reinecke req->sq->authenticated = false; 289*db1312ddSHannes Reinecke status = 0; 290*db1312ddSHannes Reinecke } 291*db1312ddSHannes Reinecke goto done_kfree; 292*db1312ddSHannes Reinecke break; 293*db1312ddSHannes Reinecke default: 294*db1312ddSHannes Reinecke req->sq->dhchap_status = 295*db1312ddSHannes Reinecke NVME_AUTH_DHCHAP_FAILURE_INCORRECT_MESSAGE; 296*db1312ddSHannes Reinecke req->sq->dhchap_step = 297*db1312ddSHannes Reinecke NVME_AUTH_DHCHAP_MESSAGE_FAILURE2; 298*db1312ddSHannes Reinecke req->sq->authenticated = false; 299*db1312ddSHannes Reinecke goto done_kfree; 300*db1312ddSHannes Reinecke break; 301*db1312ddSHannes Reinecke } 302*db1312ddSHannes Reinecke done_failure1: 303*db1312ddSHannes Reinecke req->sq->dhchap_status = NVME_AUTH_DHCHAP_FAILURE_INCORRECT_MESSAGE; 304*db1312ddSHannes Reinecke req->sq->dhchap_step = NVME_AUTH_DHCHAP_MESSAGE_FAILURE2; 305*db1312ddSHannes Reinecke 306*db1312ddSHannes Reinecke done_kfree: 307*db1312ddSHannes Reinecke kfree(d); 308*db1312ddSHannes Reinecke done: 309*db1312ddSHannes Reinecke pr_debug("%s: ctrl %d qid %d dhchap status %x step %x\n", __func__, 310*db1312ddSHannes Reinecke ctrl->cntlid, req->sq->qid, 311*db1312ddSHannes Reinecke req->sq->dhchap_status, req->sq->dhchap_step); 312*db1312ddSHannes Reinecke if (status) 313*db1312ddSHannes Reinecke pr_debug("%s: ctrl %d qid %d nvme status %x error loc %d\n", 314*db1312ddSHannes Reinecke __func__, ctrl->cntlid, req->sq->qid, 315*db1312ddSHannes Reinecke status, req->error_loc); 316*db1312ddSHannes Reinecke req->cqe->result.u64 = 0; 317*db1312ddSHannes Reinecke nvmet_req_complete(req, status); 318*db1312ddSHannes Reinecke if (req->sq->dhchap_step != NVME_AUTH_DHCHAP_MESSAGE_SUCCESS2 && 319*db1312ddSHannes Reinecke req->sq->dhchap_step != NVME_AUTH_DHCHAP_MESSAGE_FAILURE2) 320*db1312ddSHannes Reinecke return; 321*db1312ddSHannes Reinecke /* Final states, clear up variables */ 322*db1312ddSHannes Reinecke nvmet_auth_sq_free(req->sq); 323*db1312ddSHannes Reinecke if (req->sq->dhchap_step == NVME_AUTH_DHCHAP_MESSAGE_FAILURE2) 324*db1312ddSHannes Reinecke nvmet_ctrl_fatal_error(ctrl); 325*db1312ddSHannes Reinecke } 326*db1312ddSHannes Reinecke 327*db1312ddSHannes Reinecke static int nvmet_auth_challenge(struct nvmet_req *req, void *d, int al) 328*db1312ddSHannes Reinecke { 329*db1312ddSHannes Reinecke struct nvmf_auth_dhchap_challenge_data *data = d; 330*db1312ddSHannes Reinecke struct nvmet_ctrl *ctrl = req->sq->ctrl; 331*db1312ddSHannes Reinecke int ret = 0; 332*db1312ddSHannes Reinecke int hash_len = nvme_auth_hmac_hash_len(ctrl->shash_id); 333*db1312ddSHannes Reinecke int data_size = sizeof(*d) + hash_len; 334*db1312ddSHannes Reinecke 335*db1312ddSHannes Reinecke if (al < data_size) { 336*db1312ddSHannes Reinecke pr_debug("%s: buffer too small (al %d need %d)\n", __func__, 337*db1312ddSHannes Reinecke al, data_size); 338*db1312ddSHannes Reinecke return -EINVAL; 339*db1312ddSHannes Reinecke } 340*db1312ddSHannes Reinecke memset(data, 0, data_size); 341*db1312ddSHannes Reinecke req->sq->dhchap_s1 = nvme_auth_get_seqnum(); 342*db1312ddSHannes Reinecke data->auth_type = NVME_AUTH_DHCHAP_MESSAGES; 343*db1312ddSHannes Reinecke data->auth_id = NVME_AUTH_DHCHAP_MESSAGE_CHALLENGE; 344*db1312ddSHannes Reinecke data->t_id = cpu_to_le16(req->sq->dhchap_tid); 345*db1312ddSHannes Reinecke data->hashid = ctrl->shash_id; 346*db1312ddSHannes Reinecke data->hl = hash_len; 347*db1312ddSHannes Reinecke data->seqnum = cpu_to_le32(req->sq->dhchap_s1); 348*db1312ddSHannes Reinecke req->sq->dhchap_c1 = kmalloc(data->hl, GFP_KERNEL); 349*db1312ddSHannes Reinecke if (!req->sq->dhchap_c1) 350*db1312ddSHannes Reinecke return -ENOMEM; 351*db1312ddSHannes Reinecke get_random_bytes(req->sq->dhchap_c1, data->hl); 352*db1312ddSHannes Reinecke memcpy(data->cval, req->sq->dhchap_c1, data->hl); 353*db1312ddSHannes Reinecke pr_debug("%s: ctrl %d qid %d seq %u transaction %d hl %d dhvlen %u\n", 354*db1312ddSHannes Reinecke __func__, ctrl->cntlid, req->sq->qid, req->sq->dhchap_s1, 355*db1312ddSHannes Reinecke req->sq->dhchap_tid, data->hl, 0); 356*db1312ddSHannes Reinecke return ret; 357*db1312ddSHannes Reinecke } 358*db1312ddSHannes Reinecke 359*db1312ddSHannes Reinecke static int nvmet_auth_success1(struct nvmet_req *req, void *d, int al) 360*db1312ddSHannes Reinecke { 361*db1312ddSHannes Reinecke struct nvmf_auth_dhchap_success1_data *data = d; 362*db1312ddSHannes Reinecke struct nvmet_ctrl *ctrl = req->sq->ctrl; 363*db1312ddSHannes Reinecke int hash_len = nvme_auth_hmac_hash_len(ctrl->shash_id); 364*db1312ddSHannes Reinecke 365*db1312ddSHannes Reinecke WARN_ON(al < sizeof(*data)); 366*db1312ddSHannes Reinecke memset(data, 0, sizeof(*data)); 367*db1312ddSHannes Reinecke data->auth_type = NVME_AUTH_DHCHAP_MESSAGES; 368*db1312ddSHannes Reinecke data->auth_id = NVME_AUTH_DHCHAP_MESSAGE_SUCCESS1; 369*db1312ddSHannes Reinecke data->t_id = cpu_to_le16(req->sq->dhchap_tid); 370*db1312ddSHannes Reinecke data->hl = hash_len; 371*db1312ddSHannes Reinecke if (req->sq->dhchap_c2) { 372*db1312ddSHannes Reinecke if (!ctrl->ctrl_key) { 373*db1312ddSHannes Reinecke pr_warn("ctrl %d qid %d no ctrl key\n", 374*db1312ddSHannes Reinecke ctrl->cntlid, req->sq->qid); 375*db1312ddSHannes Reinecke return NVME_AUTH_DHCHAP_FAILURE_FAILED; 376*db1312ddSHannes Reinecke } 377*db1312ddSHannes Reinecke if (nvmet_auth_ctrl_hash(req, data->rval, data->hl)) 378*db1312ddSHannes Reinecke return NVME_AUTH_DHCHAP_FAILURE_HASH_UNUSABLE; 379*db1312ddSHannes Reinecke data->rvalid = 1; 380*db1312ddSHannes Reinecke pr_debug("ctrl %d qid %d response %*ph\n", 381*db1312ddSHannes Reinecke ctrl->cntlid, req->sq->qid, data->hl, data->rval); 382*db1312ddSHannes Reinecke } 383*db1312ddSHannes Reinecke return 0; 384*db1312ddSHannes Reinecke } 385*db1312ddSHannes Reinecke 386*db1312ddSHannes Reinecke static void nvmet_auth_failure1(struct nvmet_req *req, void *d, int al) 387*db1312ddSHannes Reinecke { 388*db1312ddSHannes Reinecke struct nvmf_auth_dhchap_failure_data *data = d; 389*db1312ddSHannes Reinecke 390*db1312ddSHannes Reinecke WARN_ON(al < sizeof(*data)); 391*db1312ddSHannes Reinecke data->auth_type = NVME_AUTH_COMMON_MESSAGES; 392*db1312ddSHannes Reinecke data->auth_id = NVME_AUTH_DHCHAP_MESSAGE_FAILURE1; 393*db1312ddSHannes Reinecke data->t_id = cpu_to_le16(req->sq->dhchap_tid); 394*db1312ddSHannes Reinecke data->rescode = NVME_AUTH_DHCHAP_FAILURE_REASON_FAILED; 395*db1312ddSHannes Reinecke data->rescode_exp = req->sq->dhchap_status; 396*db1312ddSHannes Reinecke } 397*db1312ddSHannes Reinecke 398*db1312ddSHannes Reinecke void nvmet_execute_auth_receive(struct nvmet_req *req) 399*db1312ddSHannes Reinecke { 400*db1312ddSHannes Reinecke struct nvmet_ctrl *ctrl = req->sq->ctrl; 401*db1312ddSHannes Reinecke void *d; 402*db1312ddSHannes Reinecke u32 al; 403*db1312ddSHannes Reinecke u16 status = 0; 404*db1312ddSHannes Reinecke 405*db1312ddSHannes Reinecke if (req->cmd->auth_receive.secp != NVME_AUTH_DHCHAP_PROTOCOL_IDENTIFIER) { 406*db1312ddSHannes Reinecke status = NVME_SC_INVALID_FIELD | NVME_SC_DNR; 407*db1312ddSHannes Reinecke req->error_loc = 408*db1312ddSHannes Reinecke offsetof(struct nvmf_auth_receive_command, secp); 409*db1312ddSHannes Reinecke goto done; 410*db1312ddSHannes Reinecke } 411*db1312ddSHannes Reinecke if (req->cmd->auth_receive.spsp0 != 0x01) { 412*db1312ddSHannes Reinecke status = NVME_SC_INVALID_FIELD | NVME_SC_DNR; 413*db1312ddSHannes Reinecke req->error_loc = 414*db1312ddSHannes Reinecke offsetof(struct nvmf_auth_receive_command, spsp0); 415*db1312ddSHannes Reinecke goto done; 416*db1312ddSHannes Reinecke } 417*db1312ddSHannes Reinecke if (req->cmd->auth_receive.spsp1 != 0x01) { 418*db1312ddSHannes Reinecke status = NVME_SC_INVALID_FIELD | NVME_SC_DNR; 419*db1312ddSHannes Reinecke req->error_loc = 420*db1312ddSHannes Reinecke offsetof(struct nvmf_auth_receive_command, spsp1); 421*db1312ddSHannes Reinecke goto done; 422*db1312ddSHannes Reinecke } 423*db1312ddSHannes Reinecke al = le32_to_cpu(req->cmd->auth_receive.al); 424*db1312ddSHannes Reinecke if (!al) { 425*db1312ddSHannes Reinecke status = NVME_SC_INVALID_FIELD | NVME_SC_DNR; 426*db1312ddSHannes Reinecke req->error_loc = 427*db1312ddSHannes Reinecke offsetof(struct nvmf_auth_receive_command, al); 428*db1312ddSHannes Reinecke goto done; 429*db1312ddSHannes Reinecke } 430*db1312ddSHannes Reinecke if (!nvmet_check_transfer_len(req, al)) { 431*db1312ddSHannes Reinecke pr_debug("%s: transfer length mismatch (%u)\n", __func__, al); 432*db1312ddSHannes Reinecke return; 433*db1312ddSHannes Reinecke } 434*db1312ddSHannes Reinecke 435*db1312ddSHannes Reinecke d = kmalloc(al, GFP_KERNEL); 436*db1312ddSHannes Reinecke if (!d) { 437*db1312ddSHannes Reinecke status = NVME_SC_INTERNAL; 438*db1312ddSHannes Reinecke goto done; 439*db1312ddSHannes Reinecke } 440*db1312ddSHannes Reinecke pr_debug("%s: ctrl %d qid %d step %x\n", __func__, 441*db1312ddSHannes Reinecke ctrl->cntlid, req->sq->qid, req->sq->dhchap_step); 442*db1312ddSHannes Reinecke switch (req->sq->dhchap_step) { 443*db1312ddSHannes Reinecke case NVME_AUTH_DHCHAP_MESSAGE_CHALLENGE: 444*db1312ddSHannes Reinecke status = nvmet_auth_challenge(req, d, al); 445*db1312ddSHannes Reinecke if (status < 0) { 446*db1312ddSHannes Reinecke pr_warn("ctrl %d qid %d: challenge error (%d)\n", 447*db1312ddSHannes Reinecke ctrl->cntlid, req->sq->qid, status); 448*db1312ddSHannes Reinecke status = NVME_SC_INTERNAL; 449*db1312ddSHannes Reinecke break; 450*db1312ddSHannes Reinecke } 451*db1312ddSHannes Reinecke if (status) { 452*db1312ddSHannes Reinecke req->sq->dhchap_status = status; 453*db1312ddSHannes Reinecke nvmet_auth_failure1(req, d, al); 454*db1312ddSHannes Reinecke pr_warn("ctrl %d qid %d: challenge status (%x)\n", 455*db1312ddSHannes Reinecke ctrl->cntlid, req->sq->qid, 456*db1312ddSHannes Reinecke req->sq->dhchap_status); 457*db1312ddSHannes Reinecke status = 0; 458*db1312ddSHannes Reinecke break; 459*db1312ddSHannes Reinecke } 460*db1312ddSHannes Reinecke req->sq->dhchap_step = NVME_AUTH_DHCHAP_MESSAGE_REPLY; 461*db1312ddSHannes Reinecke break; 462*db1312ddSHannes Reinecke case NVME_AUTH_DHCHAP_MESSAGE_SUCCESS1: 463*db1312ddSHannes Reinecke status = nvmet_auth_success1(req, d, al); 464*db1312ddSHannes Reinecke if (status) { 465*db1312ddSHannes Reinecke req->sq->dhchap_status = status; 466*db1312ddSHannes Reinecke req->sq->authenticated = false; 467*db1312ddSHannes Reinecke nvmet_auth_failure1(req, d, al); 468*db1312ddSHannes Reinecke pr_warn("ctrl %d qid %d: success1 status (%x)\n", 469*db1312ddSHannes Reinecke ctrl->cntlid, req->sq->qid, 470*db1312ddSHannes Reinecke req->sq->dhchap_status); 471*db1312ddSHannes Reinecke break; 472*db1312ddSHannes Reinecke } 473*db1312ddSHannes Reinecke req->sq->dhchap_step = NVME_AUTH_DHCHAP_MESSAGE_SUCCESS2; 474*db1312ddSHannes Reinecke break; 475*db1312ddSHannes Reinecke case NVME_AUTH_DHCHAP_MESSAGE_FAILURE1: 476*db1312ddSHannes Reinecke req->sq->authenticated = false; 477*db1312ddSHannes Reinecke nvmet_auth_failure1(req, d, al); 478*db1312ddSHannes Reinecke pr_warn("ctrl %d qid %d failure1 (%x)\n", 479*db1312ddSHannes Reinecke ctrl->cntlid, req->sq->qid, req->sq->dhchap_status); 480*db1312ddSHannes Reinecke break; 481*db1312ddSHannes Reinecke default: 482*db1312ddSHannes Reinecke pr_warn("ctrl %d qid %d unhandled step (%d)\n", 483*db1312ddSHannes Reinecke ctrl->cntlid, req->sq->qid, req->sq->dhchap_step); 484*db1312ddSHannes Reinecke req->sq->dhchap_step = NVME_AUTH_DHCHAP_MESSAGE_FAILURE1; 485*db1312ddSHannes Reinecke req->sq->dhchap_status = NVME_AUTH_DHCHAP_FAILURE_FAILED; 486*db1312ddSHannes Reinecke nvmet_auth_failure1(req, d, al); 487*db1312ddSHannes Reinecke status = 0; 488*db1312ddSHannes Reinecke break; 489*db1312ddSHannes Reinecke } 490*db1312ddSHannes Reinecke 491*db1312ddSHannes Reinecke status = nvmet_copy_to_sgl(req, 0, d, al); 492*db1312ddSHannes Reinecke kfree(d); 493*db1312ddSHannes Reinecke done: 494*db1312ddSHannes Reinecke req->cqe->result.u64 = 0; 495*db1312ddSHannes Reinecke nvmet_req_complete(req, status); 496*db1312ddSHannes Reinecke if (req->sq->dhchap_step == NVME_AUTH_DHCHAP_MESSAGE_SUCCESS2) 497*db1312ddSHannes Reinecke nvmet_auth_sq_free(req->sq); 498*db1312ddSHannes Reinecke else if (req->sq->dhchap_step == NVME_AUTH_DHCHAP_MESSAGE_FAILURE1) { 499*db1312ddSHannes Reinecke nvmet_auth_sq_free(req->sq); 500*db1312ddSHannes Reinecke nvmet_ctrl_fatal_error(ctrl); 501*db1312ddSHannes Reinecke } 502*db1312ddSHannes Reinecke } 503