LCOV - code coverage report
Current view: top level - spdk/lib/nvme - nvme_auth.c (source / functions) Hit Total Coverage
Test: Combined Lines: 531 730 72.7 %
Date: 2024-07-12 15:26:30 Functions: 33 33 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 248 406 61.1 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  * Copyright (c) 2024 Intel Corporation.  All rights reserved.
       3                 :            :  */
       4                 :            : 
       5                 :            : #include "spdk/base64.h"
       6                 :            : #include "spdk/crc32.h"
       7                 :            : #include "spdk/endian.h"
       8                 :            : #include "spdk/log.h"
       9                 :            : #include "spdk/string.h"
      10                 :            : #include "spdk/util.h"
      11                 :            : #include "spdk_internal/nvme.h"
      12                 :            : #include "nvme_internal.h"
      13                 :            : 
      14                 :            : #ifdef SPDK_CONFIG_HAVE_EVP_MAC
      15                 :            : #include <openssl/dh.h>
      16                 :            : #include <openssl/evp.h>
      17                 :            : #include <openssl/param_build.h>
      18                 :            : #include <openssl/rand.h>
      19                 :            : #endif
      20                 :            : 
      21                 :            : struct nvme_auth_digest {
      22                 :            :         uint8_t         id;
      23                 :            :         const char      *name;
      24                 :            :         uint8_t         len;
      25                 :            : };
      26                 :            : 
      27                 :            : struct nvme_auth_dhgroup {
      28                 :            :         uint8_t         id;
      29                 :            :         const char      *name;
      30                 :            : };
      31                 :            : 
      32                 :            : #define NVME_AUTH_DATA_SIZE                     4096
      33                 :            : #define NVME_AUTH_DH_KEY_MAX_SIZE               1024
      34                 :            : #define NVME_AUTH_CHAP_KEY_MAX_SIZE             256
      35                 :            : 
      36                 :            : #define AUTH_DEBUGLOG(q, fmt, ...) \
      37                 :            :         SPDK_DEBUGLOG(nvme_auth, "[%s:%s:%u] " fmt, (q)->ctrlr->trid.subnqn, \
      38                 :            :                       (q)->ctrlr->opts.hostnqn, (q)->id, ## __VA_ARGS__)
      39                 :            : #define AUTH_ERRLOG(q, fmt, ...) \
      40                 :            :         SPDK_ERRLOG("[%s:%s:%u] " fmt, (q)->ctrlr->trid.subnqn, (q)->ctrlr->opts.hostnqn, \
      41                 :            :                     (q)->id, ## __VA_ARGS__)
      42                 :            : #define AUTH_LOGDUMP(msg, buf, len) \
      43                 :            :         SPDK_LOGDUMP(nvme_auth, msg, buf, len)
      44                 :            : 
      45                 :            : static const struct nvme_auth_digest g_digests[] = {
      46                 :            :         { SPDK_NVMF_DHCHAP_HASH_SHA256, "sha256", 32 },
      47                 :            :         { SPDK_NVMF_DHCHAP_HASH_SHA384, "sha384", 48 },
      48                 :            :         { SPDK_NVMF_DHCHAP_HASH_SHA512, "sha512", 64 },
      49                 :            : };
      50                 :            : 
      51                 :            : static const struct nvme_auth_dhgroup g_dhgroups[] = {
      52                 :            :         { SPDK_NVMF_DHCHAP_DHGROUP_NULL, "null" },
      53                 :            :         { SPDK_NVMF_DHCHAP_DHGROUP_2048, "ffdhe2048" },
      54                 :            :         { SPDK_NVMF_DHCHAP_DHGROUP_3072, "ffdhe3072" },
      55                 :            :         { SPDK_NVMF_DHCHAP_DHGROUP_4096, "ffdhe4096" },
      56                 :            :         { SPDK_NVMF_DHCHAP_DHGROUP_6144, "ffdhe6144" },
      57                 :            :         { SPDK_NVMF_DHCHAP_DHGROUP_8192, "ffdhe8192" },
      58                 :            : };
      59                 :            : 
      60                 :            : static const struct nvme_auth_digest *
      61                 :      22999 : nvme_auth_get_digest(int id)
      62                 :            : {
      63                 :            :         size_t i;
      64                 :            : 
      65         [ +  - ]:      52698 :         for (i = 0; i < SPDK_COUNTOF(g_digests); ++i) {
      66         [ +  + ]:      52698 :                 if (g_digests[i].id == id) {
      67                 :      22999 :                         return &g_digests[i];
      68                 :            :                 }
      69                 :            :         }
      70                 :            : 
      71                 :          0 :         return NULL;
      72                 :            : }
      73                 :            : 
      74                 :            : int
      75                 :       1408 : spdk_nvme_dhchap_get_digest_id(const char *digest)
      76                 :            : {
      77                 :            :         size_t i;
      78                 :            : 
      79         [ +  - ]:       2812 :         for (i = 0; i < SPDK_COUNTOF(g_digests); ++i) {
      80   [ +  +  -  +  :       2812 :                 if (strcmp(g_digests[i].name, digest) == 0) {
                   +  + ]
      81                 :       1408 :                         return g_digests[i].id;
      82                 :            :                 }
      83                 :            :         }
      84                 :            : 
      85                 :          0 :         return -EINVAL;
      86                 :            : }
      87                 :            : 
      88                 :            : const char *
      89                 :      14535 : spdk_nvme_dhchap_get_digest_name(int id)
      90                 :            : {
      91                 :      14535 :         const struct nvme_auth_digest *digest = nvme_auth_get_digest(id);
      92                 :            : 
      93         [ +  - ]:      14535 :         return digest != NULL ? digest->name : NULL;
      94                 :            : }
      95                 :            : 
      96                 :            : int
      97                 :       2184 : spdk_nvme_dhchap_get_dhgroup_id(const char *dhgroup)
      98                 :            : {
      99                 :            :         size_t i;
     100                 :            : 
     101         [ +  - ]:       7808 :         for (i = 0; i < SPDK_COUNTOF(g_dhgroups); ++i) {
     102   [ +  +  -  +  :       7808 :                 if (strcmp(g_dhgroups[i].name, dhgroup) == 0) {
                   +  + ]
     103                 :       2184 :                         return g_dhgroups[i].id;
     104                 :            :                 }
     105                 :            :         }
     106                 :            : 
     107                 :          0 :         return -EINVAL;
     108                 :            : }
     109                 :            : 
     110                 :            : const char *
     111                 :       5046 : spdk_nvme_dhchap_get_dhgroup_name(int id)
     112                 :            : {
     113                 :            :         size_t i;
     114                 :            : 
     115         [ +  - ]:      21609 :         for (i = 0; i < SPDK_COUNTOF(g_dhgroups); ++i) {
     116         [ +  + ]:      21609 :                 if (g_dhgroups[i].id == id) {
     117                 :       5046 :                         return g_dhgroups[i].name;
     118                 :            :                 }
     119                 :            :         }
     120                 :            : 
     121                 :          0 :         return NULL;
     122                 :            : }
     123                 :            : 
     124                 :            : uint8_t
     125                 :       8464 : spdk_nvme_dhchap_get_digest_length(int id)
     126                 :            : {
     127                 :       8464 :         const struct nvme_auth_digest *digest = nvme_auth_get_digest(id);
     128                 :            : 
     129         [ +  - ]:       8464 :         return digest != NULL ? digest->len : 0;
     130                 :            : }
     131                 :            : 
     132                 :            : #ifdef SPDK_CONFIG_HAVE_EVP_MAC
     133                 :            : static bool
     134                 :       3732 : nvme_auth_digest_allowed(struct spdk_nvme_qpair *qpair, uint8_t digest)
     135                 :            : {
     136                 :       3732 :         struct spdk_nvme_ctrlr *ctrlr = qpair->ctrlr;
     137                 :            : 
     138         [ -  + ]:       3732 :         return ctrlr->opts.dhchap_digests & SPDK_BIT(digest);
     139                 :            : }
     140                 :            : 
     141                 :            : static bool
     142                 :       6540 : nvme_auth_dhgroup_allowed(struct spdk_nvme_qpair *qpair, uint8_t dhgroup)
     143                 :            : {
     144                 :       6540 :         struct spdk_nvme_ctrlr *ctrlr = qpair->ctrlr;
     145                 :            : 
     146         [ -  + ]:       6540 :         return ctrlr->opts.dhchap_dhgroups & SPDK_BIT(dhgroup);
     147                 :            : }
     148                 :            : 
     149                 :            : static void
     150                 :       6304 : nvme_auth_set_state(struct spdk_nvme_qpair *qpair, enum nvme_qpair_auth_state state)
     151                 :            : {
     152                 :            :         static const char *state_names[] __attribute__((unused)) = {
     153                 :            :                 [NVME_QPAIR_AUTH_STATE_NEGOTIATE] = "negotiate",
     154                 :            :                 [NVME_QPAIR_AUTH_STATE_AWAIT_NEGOTIATE] = "await-negotiate",
     155                 :            :                 [NVME_QPAIR_AUTH_STATE_AWAIT_CHALLENGE] = "await-challenge",
     156                 :            :                 [NVME_QPAIR_AUTH_STATE_AWAIT_REPLY] = "await-reply",
     157                 :            :                 [NVME_QPAIR_AUTH_STATE_AWAIT_SUCCESS1] = "await-success1",
     158                 :            :                 [NVME_QPAIR_AUTH_STATE_AWAIT_SUCCESS2] = "await-success2",
     159                 :            :                 [NVME_QPAIR_AUTH_STATE_AWAIT_FAILURE2] = "await-failure2",
     160                 :            :                 [NVME_QPAIR_AUTH_STATE_DONE] = "done",
     161                 :            :         };
     162                 :            : 
     163   [ -  +  +  - ]:       6304 :         AUTH_DEBUGLOG(qpair, "auth state: %s\n", state_names[state]);
     164                 :       6304 :         qpair->auth.state = state;
     165                 :       6304 : }
     166                 :            : 
     167                 :            : static void
     168                 :         32 : nvme_auth_set_failure(struct spdk_nvme_qpair *qpair, int status, bool failure2)
     169                 :            : {
     170         [ +  - ]:         32 :         if (qpair->auth.status == 0) {
     171                 :         32 :                 qpair->auth.status = status;
     172                 :            :         }
     173                 :            : 
     174         [ +  + ]:         32 :         nvme_auth_set_state(qpair, failure2 ?
     175                 :            :                             NVME_QPAIR_AUTH_STATE_AWAIT_FAILURE2 :
     176                 :            :                             NVME_QPAIR_AUTH_STATE_DONE);
     177                 :         32 : }
     178                 :            : 
     179                 :            : static void
     180                 :          8 : nvme_auth_print_cpl(struct spdk_nvme_qpair *qpair, const char *msg)
     181                 :            : {
     182                 :          8 :         struct nvme_completion_poll_status *status = qpair->poll_status;
     183                 :            : 
     184   [ -  +  +  + ]:          8 :         AUTH_ERRLOG(qpair, "%s failed: sc=%d, sct=%d (timed out: %s)\n", msg, status->cpl.status.sc,
     185                 :            :                     status->cpl.status.sct, status->timed_out ? "true" : "false");
     186                 :          8 : }
     187                 :            : 
     188                 :            : static uint32_t
     189                 :        720 : nvme_auth_get_seqnum(struct spdk_nvme_qpair *qpair)
     190                 :            : {
     191                 :        720 :         struct spdk_nvme_ctrlr *ctrlr = qpair->ctrlr;
     192                 :            :         uint32_t seqnum;
     193                 :            :         int rc;
     194                 :            : 
     195                 :        720 :         nvme_ctrlr_lock(ctrlr);
     196         [ +  + ]:        720 :         if (ctrlr->auth_seqnum == 0) {
     197                 :        476 :                 rc = RAND_bytes((void *)&ctrlr->auth_seqnum, sizeof(ctrlr->auth_seqnum));
     198         [ -  + ]:        476 :                 if (rc != 1) {
     199                 :          0 :                         nvme_ctrlr_unlock(ctrlr);
     200                 :          0 :                         return 0;
     201                 :            :                 }
     202                 :            :         }
     203         [ -  + ]:        720 :         if (++ctrlr->auth_seqnum == 0) {
     204                 :          0 :                 ctrlr->auth_seqnum = 1;
     205                 :            :         }
     206                 :        720 :         seqnum = ctrlr->auth_seqnum;
     207                 :        720 :         nvme_ctrlr_unlock(ctrlr);
     208                 :            : 
     209                 :        720 :         return seqnum;
     210                 :            : }
     211                 :            : 
     212                 :            : static int
     213                 :       3208 : nvme_auth_transform_key(struct spdk_key *key, int hash, const char *nqn,
     214                 :            :                         const void *keyin, size_t keylen, void *out, size_t outlen)
     215                 :            : {
     216                 :       3208 :         EVP_MAC *hmac = NULL;
     217                 :       3208 :         EVP_MAC_CTX *ctx = NULL;
     218                 :          0 :         OSSL_PARAM params[2];
     219                 :            :         int rc;
     220                 :            : 
     221      [ +  +  - ]:       3208 :         switch (hash) {
     222                 :        676 :         case SPDK_NVMF_DHCHAP_HASH_NONE:
     223         [ -  + ]:        676 :                 if (keylen > outlen) {
     224                 :          0 :                         SPDK_ERRLOG("Key buffer too small: %zu < %zu (key=%s)\n", outlen, keylen,
     225                 :            :                                     spdk_key_get_name(key));
     226                 :          0 :                         return -ENOBUFS;
     227                 :            :                 }
     228   [ -  +  -  + ]:        676 :                 memcpy(out, keyin, keylen);
     229                 :        676 :                 return keylen;
     230                 :       2532 :         case SPDK_NVMF_DHCHAP_HASH_SHA256:
     231                 :            :         case SPDK_NVMF_DHCHAP_HASH_SHA384:
     232                 :            :         case SPDK_NVMF_DHCHAP_HASH_SHA512:
     233                 :       2532 :                 break;
     234                 :          0 :         default:
     235                 :          0 :                 SPDK_ERRLOG("Unsupported key hash: 0x%x (key=%s)\n", hash, spdk_key_get_name(key));
     236                 :          0 :                 return -EINVAL;
     237                 :            :         }
     238                 :            : 
     239                 :       2532 :         hmac = EVP_MAC_fetch(NULL, "hmac", NULL);
     240         [ -  + ]:       2532 :         if (hmac == NULL) {
     241                 :          0 :                 return -EIO;
     242                 :            :         }
     243                 :       2532 :         ctx = EVP_MAC_CTX_new(hmac);
     244         [ -  + ]:       2532 :         if (ctx == NULL) {
     245                 :          0 :                 rc = -EIO;
     246                 :          0 :                 goto out;
     247                 :            :         }
     248                 :       2532 :         params[0] = OSSL_PARAM_construct_utf8_string("digest",
     249                 :       2532 :                         (char *)spdk_nvme_dhchap_get_digest_name(hash), 0);
     250                 :       2532 :         params[1] = OSSL_PARAM_construct_end();
     251                 :            : 
     252         [ -  + ]:       2532 :         if (EVP_MAC_init(ctx, keyin, keylen, params) != 1) {
     253                 :          0 :                 rc = -EIO;
     254                 :          0 :                 goto out;
     255                 :            :         }
     256   [ -  +  -  + ]:       2532 :         if (EVP_MAC_update(ctx, nqn, strlen(nqn)) != 1) {
     257                 :          0 :                 rc = -EIO;
     258                 :          0 :                 goto out;
     259                 :            :         }
     260         [ -  + ]:       2532 :         if (EVP_MAC_update(ctx, "NVMe-over-Fabrics", strlen("NVMe-over-Fabrics")) != 1) {
     261                 :          0 :                 rc = -EIO;
     262                 :          0 :                 goto out;
     263                 :            :         }
     264         [ -  + ]:       2532 :         if (EVP_MAC_final(ctx, out, &outlen, outlen) != 1) {
     265                 :          0 :                 rc = -EIO;
     266                 :          0 :                 goto out;
     267                 :            :         }
     268                 :       2532 :         rc = (int)outlen;
     269                 :       2532 : out:
     270                 :       2532 :         EVP_MAC_CTX_free(ctx);
     271                 :       2532 :         EVP_MAC_free(hmac);
     272                 :            : 
     273                 :       2532 :         return rc;
     274                 :            : }
     275                 :            : 
     276                 :            : static int
     277                 :       3208 : nvme_auth_get_key(struct spdk_key *key, const char *nqn, void *buf, size_t buflen)
     278                 :            : {
     279                 :       3208 :         char keystr[NVME_AUTH_CHAP_KEY_MAX_SIZE + 1] = {};
     280                 :       3208 :         char keyb64[NVME_AUTH_CHAP_KEY_MAX_SIZE] = {};
     281                 :            :         char *tmp, *secret;
     282                 :          0 :         int rc, hash;
     283                 :          0 :         size_t keylen;
     284                 :            : 
     285                 :       3208 :         rc = spdk_key_get_key(key, keystr, NVME_AUTH_CHAP_KEY_MAX_SIZE);
     286         [ -  + ]:       3208 :         if (rc < 0) {
     287                 :          0 :                 SPDK_ERRLOG("Failed to load key=%s: %s\n", spdk_key_get_name(key),
     288                 :            :                             spdk_strerror(-rc));
     289                 :          0 :                 goto out;
     290                 :            :         }
     291                 :            : 
     292                 :       3208 :         rc = sscanf(keystr, "DHHC-1:%02x:", &hash);
     293         [ -  + ]:       3208 :         if (rc != 1) {
     294                 :          0 :                 SPDK_ERRLOG("Invalid key format (key=%s)\n", spdk_key_get_name(key));
     295                 :          0 :                 rc = -EINVAL;
     296                 :          0 :                 goto out;
     297                 :            : 
     298                 :            :         }
     299                 :            :         /* Start at the first character after second ":" and remove the trailing ":" */
     300                 :       3208 :         secret = &keystr[10];
     301         [ -  + ]:       3208 :         tmp = strstr(secret, ":");
     302         [ -  + ]:       3208 :         if (!tmp) {
     303                 :          0 :                 SPDK_ERRLOG("Invalid key format (key=%s)\n", spdk_key_get_name(key));
     304                 :          0 :                 rc = -EINVAL;
     305                 :          0 :                 goto out;
     306                 :            :         }
     307                 :            : 
     308                 :       3208 :         *tmp = '\0';
     309                 :       3208 :         keylen = sizeof(keyb64);
     310                 :       3208 :         rc = spdk_base64_decode(keyb64, &keylen, secret);
     311         [ -  + ]:       3208 :         if (rc != 0) {
     312                 :          0 :                 SPDK_ERRLOG("Invalid key format (key=%s)\n", spdk_key_get_name(key));
     313                 :          0 :                 rc = -EINVAL;
     314                 :          0 :                 goto out;
     315                 :            :         }
     316                 :            :         /* Only 32B, 48B, and 64B keys are supported (+ 4B, as they're followed by a crc32) */
     317   [ +  +  +  +  :       3208 :         if (keylen != 36 && keylen != 52 && keylen != 68) {
                   -  + ]
     318                 :          0 :                 SPDK_ERRLOG("Invalid key size=%zu (key=%s)\n", keylen, spdk_key_get_name(key));
     319                 :          0 :                 rc = -EINVAL;
     320                 :          0 :                 goto out;
     321                 :            :         }
     322                 :            : 
     323                 :       3208 :         keylen -= 4;
     324         [ -  + ]:       3208 :         if (~spdk_crc32_ieee_update(keyb64, keylen, ~0) != from_le32(&keyb64[keylen])) {
     325                 :          0 :                 SPDK_ERRLOG("Invalid key checksum (key=%s)\n", spdk_key_get_name(key));
     326                 :          0 :                 rc = -EINVAL;
     327                 :          0 :                 goto out;
     328                 :            :         }
     329                 :            : 
     330                 :       3208 :         rc = nvme_auth_transform_key(key, hash, nqn, keyb64, keylen, buf, buflen);
     331                 :       3208 : out:
     332                 :       3208 :         spdk_memset_s(keystr, sizeof(keystr), 0, sizeof(keystr));
     333                 :       3208 :         spdk_memset_s(keyb64, sizeof(keyb64), 0, sizeof(keyb64));
     334                 :            : 
     335                 :       3208 :         return rc;
     336                 :            : }
     337                 :            : 
     338                 :            : static int
     339                 :       3208 : nvme_auth_augment_challenge(const void *cval, size_t clen, const void *key, size_t keylen,
     340                 :            :                             void *caval, size_t *calen, enum spdk_nvmf_dhchap_hash hash)
     341                 :            : {
     342                 :       3208 :         EVP_MAC *hmac = NULL;
     343                 :       3208 :         EVP_MAC_CTX *ctx = NULL;
     344                 :       3208 :         EVP_MD *md = NULL;
     345                 :          0 :         OSSL_PARAM params[2];
     346                 :          0 :         uint8_t keydgst[NVME_AUTH_DIGEST_MAX_SIZE];
     347                 :       3208 :         unsigned int dgstlen = sizeof(keydgst);
     348                 :       3208 :         int rc = 0;
     349                 :            : 
     350                 :            :         /* If there's no key, there's nothing to augment, cval == caval */
     351         [ +  + ]:       3208 :         if (key == NULL) {
     352         [ -  + ]:        168 :                 assert(clen <= *calen);
     353   [ -  +  -  + ]:        168 :                 memcpy(caval, cval, clen);
     354                 :        168 :                 *calen = clen;
     355                 :        168 :                 return 0;
     356                 :            :         }
     357                 :            : 
     358                 :       3040 :         md = EVP_MD_fetch(NULL, spdk_nvme_dhchap_get_digest_name(hash), NULL);
     359         [ -  + ]:       3040 :         if (!md) {
     360                 :          0 :                 SPDK_ERRLOG("Failed to fetch digest function: %d\n", hash);
     361                 :          0 :                 return -EINVAL;
     362                 :            :         }
     363         [ -  + ]:       3040 :         if (EVP_Digest(key, keylen, keydgst, &dgstlen, md, NULL) != 1) {
     364                 :          0 :                 rc = -EIO;
     365                 :          0 :                 goto out;
     366                 :            :         }
     367                 :            : 
     368                 :       3040 :         hmac = EVP_MAC_fetch(NULL, "hmac", NULL);
     369         [ -  + ]:       3040 :         if (hmac == NULL) {
     370                 :          0 :                 rc = -EIO;
     371                 :          0 :                 goto out;
     372                 :            :         }
     373                 :       3040 :         ctx = EVP_MAC_CTX_new(hmac);
     374         [ -  + ]:       3040 :         if (ctx == NULL) {
     375                 :          0 :                 rc = -EIO;
     376                 :          0 :                 goto out;
     377                 :            :         }
     378                 :       3040 :         params[0] = OSSL_PARAM_construct_utf8_string("digest",
     379                 :       3040 :                         (char *)spdk_nvme_dhchap_get_digest_name(hash), 0);
     380                 :       3040 :         params[1] = OSSL_PARAM_construct_end();
     381                 :            : 
     382         [ -  + ]:       3040 :         if (EVP_MAC_init(ctx, keydgst, dgstlen, params) != 1) {
     383                 :          0 :                 rc = -EIO;
     384                 :          0 :                 goto out;
     385                 :            :         }
     386         [ -  + ]:       3040 :         if (EVP_MAC_update(ctx, cval, clen) != 1) {
     387                 :          0 :                 rc = -EIO;
     388                 :          0 :                 goto out;
     389                 :            :         }
     390         [ +  - ]:       3040 :         if (EVP_MAC_final(ctx, caval, calen, *calen) != 1) {
     391                 :          0 :                 rc = -EIO;
     392                 :          0 :                 goto out;
     393                 :            :         }
     394                 :       3040 : out:
     395                 :       3040 :         EVP_MD_free(md);
     396                 :       3040 :         EVP_MAC_CTX_free(ctx);
     397                 :       3040 :         EVP_MAC_free(hmac);
     398                 :            : 
     399                 :       3040 :         return rc;
     400                 :            : }
     401                 :            : 
     402                 :            : int
     403                 :       3208 : spdk_nvme_dhchap_calculate(struct spdk_key *key, enum spdk_nvmf_dhchap_hash hash,
     404                 :            :                            const char *type, uint32_t seq, uint16_t tid, uint8_t scc,
     405                 :            :                            const char *nqn1, const char *nqn2, const void *dhkey, size_t dhlen,
     406                 :            :                            const void *cval, void *rval)
     407                 :            : {
     408                 :            :         EVP_MAC *hmac;
     409                 :            :         EVP_MAC_CTX *ctx;
     410                 :          0 :         OSSL_PARAM params[2];
     411                 :       3208 :         uint8_t keybuf[NVME_AUTH_CHAP_KEY_MAX_SIZE], term = 0;
     412                 :          0 :         uint8_t caval[NVME_AUTH_DATA_SIZE];
     413                 :       3208 :         size_t hlen, calen = sizeof(caval);
     414                 :            :         int rc, keylen;
     415                 :            : 
     416                 :       3208 :         hlen = spdk_nvme_dhchap_get_digest_length(hash);
     417                 :       3208 :         rc = nvme_auth_augment_challenge(cval, hlen, dhkey, dhlen, caval, &calen, hash);
     418         [ -  + ]:       3208 :         if (rc != 0) {
     419                 :          0 :                 return rc;
     420                 :            :         }
     421                 :            : 
     422                 :       3208 :         hmac = EVP_MAC_fetch(NULL, "hmac", NULL);
     423         [ -  + ]:       3208 :         if (hmac == NULL) {
     424                 :          0 :                 return -EIO;
     425                 :            :         }
     426                 :            : 
     427                 :       3208 :         ctx = EVP_MAC_CTX_new(hmac);
     428         [ -  + ]:       3208 :         if (ctx == NULL) {
     429                 :          0 :                 rc = -EIO;
     430                 :          0 :                 goto out;
     431                 :            :         }
     432                 :            : 
     433                 :       3208 :         keylen = nvme_auth_get_key(key, nqn1, keybuf, sizeof(keybuf));
     434         [ -  + ]:       3208 :         if (keylen < 0) {
     435                 :          0 :                 rc = keylen;
     436                 :          0 :                 goto out;
     437                 :            :         }
     438                 :            : 
     439                 :       3208 :         params[0] = OSSL_PARAM_construct_utf8_string("digest",
     440                 :       3208 :                         (char *)spdk_nvme_dhchap_get_digest_name(hash), 0);
     441                 :       3208 :         params[1] = OSSL_PARAM_construct_end();
     442                 :            : 
     443                 :       3208 :         rc = -EIO;
     444         [ -  + ]:       3208 :         if (EVP_MAC_init(ctx, keybuf, (size_t)keylen, params) != 1) {
     445                 :          0 :                 goto out;
     446                 :            :         }
     447         [ -  + ]:       3208 :         if (EVP_MAC_update(ctx, caval, calen) != 1) {
     448                 :          0 :                 goto out;
     449                 :            :         }
     450         [ -  + ]:       3208 :         if (EVP_MAC_update(ctx, (void *)&seq, sizeof(seq)) != 1) {
     451                 :          0 :                 goto out;
     452                 :            :         }
     453         [ -  + ]:       3208 :         if (EVP_MAC_update(ctx, (void *)&tid, sizeof(tid)) != 1) {
     454                 :          0 :                 goto out;
     455                 :            :         }
     456         [ -  + ]:       3208 :         if (EVP_MAC_update(ctx, (void *)&scc, sizeof(scc)) != 1) {
     457                 :          0 :                 goto out;
     458                 :            :         }
     459   [ -  +  -  + ]:       3208 :         if (EVP_MAC_update(ctx, (void *)type, strlen(type)) != 1) {
     460                 :          0 :                 goto out;
     461                 :            :         }
     462   [ -  +  -  + ]:       3208 :         if (EVP_MAC_update(ctx, (void *)nqn1, strlen(nqn1)) != 1) {
     463                 :          0 :                 goto out;
     464                 :            :         }
     465         [ -  + ]:       3208 :         if (EVP_MAC_update(ctx, (void *)&term, sizeof(term)) != 1) {
     466                 :          0 :                 goto out;
     467                 :            :         }
     468   [ -  +  -  + ]:       3208 :         if (EVP_MAC_update(ctx, (void *)nqn2, strlen(nqn2)) != 1) {
     469                 :          0 :                 goto out;
     470                 :            :         }
     471         [ -  + ]:       3208 :         if (EVP_MAC_final(ctx, rval, &hlen, hlen) != 1) {
     472                 :          0 :                 goto out;
     473                 :            :         }
     474                 :       3208 :         rc = 0;
     475                 :       3208 : out:
     476                 :       3208 :         spdk_memset_s(keybuf, sizeof(keybuf), 0, sizeof(keybuf));
     477                 :       3208 :         EVP_MAC_CTX_free(ctx);
     478                 :       3208 :         EVP_MAC_free(hmac);
     479                 :            : 
     480                 :       3208 :         return rc;
     481                 :            : }
     482                 :            : 
     483                 :            : struct spdk_nvme_dhchap_dhkey *
     484                 :       1728 : spdk_nvme_dhchap_generate_dhkey(enum spdk_nvmf_dhchap_dhgroup dhgroup)
     485                 :            : {
     486                 :       1728 :         EVP_PKEY_CTX *ctx = NULL;
     487                 :       1728 :         EVP_PKEY *key = NULL;
     488                 :          0 :         OSSL_PARAM params[2];
     489                 :            : 
     490                 :       1728 :         ctx = EVP_PKEY_CTX_new_from_name(NULL, "DHX", NULL);
     491         [ -  + ]:       1728 :         if (ctx == NULL) {
     492                 :          0 :                 goto error;
     493                 :            :         }
     494         [ -  + ]:       1728 :         if (EVP_PKEY_keygen_init(ctx) != 1) {
     495                 :          0 :                 goto error;
     496                 :            :         }
     497                 :            : 
     498                 :       1728 :         params[0] = OSSL_PARAM_construct_utf8_string("group",
     499                 :       1728 :                         (char *)spdk_nvme_dhchap_get_dhgroup_name(dhgroup), 0);
     500                 :       1728 :         params[1] = OSSL_PARAM_construct_end();
     501         [ -  + ]:       1728 :         if (EVP_PKEY_CTX_set_params(ctx, params) != 1) {
     502                 :          0 :                 SPDK_ERRLOG("Failed to set dhkey's dhgroup: %s\n",
     503                 :            :                             spdk_nvme_dhchap_get_dhgroup_name(dhgroup));
     504                 :          0 :                 goto error;
     505                 :            :         }
     506         [ +  - ]:       1728 :         if (EVP_PKEY_generate(ctx, &key) != 1) {
     507                 :          0 :                 goto error;
     508                 :            :         }
     509                 :       1728 : error:
     510                 :       1728 :         EVP_PKEY_CTX_free(ctx);
     511                 :       1728 :         return (void *)key;
     512                 :            : }
     513                 :            : 
     514                 :            : void
     515                 :       2672 : spdk_nvme_dhchap_dhkey_free(struct spdk_nvme_dhchap_dhkey **key)
     516                 :            : {
     517         [ -  + ]:       2672 :         if (key == NULL) {
     518                 :          0 :                 return;
     519                 :            :         }
     520                 :            : 
     521                 :       2672 :         EVP_PKEY_free(*(EVP_PKEY **)key);
     522                 :       2672 :         *key = NULL;
     523                 :            : }
     524                 :            : 
     525                 :            : int
     526                 :       1728 : spdk_nvme_dhchap_dhkey_get_pubkey(struct spdk_nvme_dhchap_dhkey *dhkey, void *pub, size_t *len)
     527                 :            : {
     528                 :       1728 :         EVP_PKEY *key = (EVP_PKEY *)dhkey;
     529                 :       1728 :         BIGNUM *bn = NULL;
     530                 :            :         int rc;
     531                 :       1728 :         const size_t num_bytes = (size_t)spdk_divide_round_up(EVP_PKEY_get_bits(key), 8);
     532                 :            : 
     533         [ -  + ]:       1728 :         if (num_bytes == 0) {
     534                 :          0 :                 SPDK_ERRLOG("Failed to get key size\n");
     535                 :          0 :                 return -EIO;
     536                 :            :         }
     537                 :            : 
     538         [ -  + ]:       1728 :         if (num_bytes > *len) {
     539                 :          0 :                 SPDK_ERRLOG("Insufficient key buffer size=%zu (needed=%zu)",
     540                 :            :                             *len, num_bytes);
     541                 :          0 :                 return -EINVAL;
     542                 :            :         }
     543                 :       1728 :         *len = num_bytes;
     544                 :            : 
     545         [ -  + ]:       1728 :         if (EVP_PKEY_get_bn_param(key, "pub", &bn) != 1) {
     546                 :          0 :                 rc = -EIO;
     547                 :          0 :                 goto error;
     548                 :            :         }
     549                 :            : 
     550                 :       1728 :         rc = BN_bn2binpad(bn, pub, *len);
     551         [ -  + ]:       1728 :         if (rc <= 0) {
     552                 :          0 :                 rc = -EIO;
     553                 :          0 :                 goto error;
     554                 :            :         }
     555                 :       1728 :         rc = 0;
     556                 :       1728 : error:
     557                 :       1728 :         BN_free(bn);
     558                 :       1728 :         return rc;
     559                 :            : }
     560                 :            : 
     561                 :            : static EVP_PKEY *
     562                 :       1728 : nvme_auth_get_peerkey(const void *peerkey, size_t len, const char *dhgroup)
     563                 :            : {
     564                 :       1728 :         EVP_PKEY_CTX *ctx = NULL;
     565                 :       1728 :         EVP_PKEY *result = NULL, *key = NULL;
     566                 :       1728 :         OSSL_PARAM_BLD *bld = NULL;
     567                 :       1728 :         OSSL_PARAM *params = NULL;
     568                 :       1728 :         BIGNUM *bn = NULL;
     569                 :            : 
     570                 :       1728 :         ctx = EVP_PKEY_CTX_new_from_name(NULL, "DHX", NULL);
     571         [ -  + ]:       1728 :         if (ctx == NULL) {
     572                 :          0 :                 goto error;
     573                 :            :         }
     574         [ -  + ]:       1728 :         if (EVP_PKEY_fromdata_init(ctx) != 1) {
     575                 :          0 :                 goto error;
     576                 :            :         }
     577                 :            : 
     578                 :       1728 :         bn = BN_bin2bn(peerkey, len, NULL);
     579         [ -  + ]:       1728 :         if (bn == NULL) {
     580                 :          0 :                 goto error;
     581                 :            :         }
     582                 :            : 
     583                 :       1728 :         bld = OSSL_PARAM_BLD_new();
     584         [ -  + ]:       1728 :         if (bld == NULL) {
     585                 :          0 :                 goto error;
     586                 :            :         }
     587         [ -  + ]:       1728 :         if (OSSL_PARAM_BLD_push_BN(bld, "pub", bn) != 1) {
     588                 :          0 :                 goto error;
     589                 :            :         }
     590         [ -  + ]:       1728 :         if (OSSL_PARAM_BLD_push_utf8_string(bld, "group", dhgroup, 0) != 1) {
     591                 :          0 :                 goto error;
     592                 :            :         }
     593                 :            : 
     594                 :       1728 :         params = OSSL_PARAM_BLD_to_param(bld);
     595         [ -  + ]:       1728 :         if (params == NULL) {
     596                 :          0 :                 goto error;
     597                 :            :         }
     598         [ -  + ]:       1728 :         if (EVP_PKEY_fromdata(ctx, &key, EVP_PKEY_PUBLIC_KEY, params) != 1) {
     599                 :          0 :                 SPDK_ERRLOG("Failed to create dhkey peer key\n");
     600                 :          0 :                 goto error;
     601                 :            :         }
     602                 :            : 
     603                 :       1728 :         result = EVP_PKEY_dup(key);
     604                 :       1728 : error:
     605                 :       1728 :         EVP_PKEY_free(key);
     606                 :       1728 :         EVP_PKEY_CTX_free(ctx);
     607                 :       1728 :         OSSL_PARAM_BLD_free(bld);
     608                 :       1728 :         OSSL_PARAM_free(params);
     609                 :       1728 :         BN_free(bn);
     610                 :            : 
     611                 :       1728 :         return result;
     612                 :            : }
     613                 :            : 
     614                 :            : int
     615                 :       1728 : spdk_nvme_dhchap_dhkey_derive_secret(struct spdk_nvme_dhchap_dhkey *dhkey,
     616                 :            :                                      const void *peer, size_t peerlen, void *secret, size_t *seclen)
     617                 :            : {
     618                 :       1728 :         EVP_PKEY *key = (EVP_PKEY *)dhkey;
     619                 :       1728 :         EVP_PKEY_CTX *ctx = NULL;
     620                 :       1728 :         EVP_PKEY *peerkey = NULL;
     621                 :       1728 :         char dhgroup[64] = {};
     622                 :       1728 :         int rc = 0;
     623                 :            : 
     624         [ -  + ]:       1728 :         if (EVP_PKEY_get_utf8_string_param(key, "group", dhgroup,
     625                 :            :                                            sizeof(dhgroup), NULL) != 1) {
     626                 :          0 :                 return -EIO;
     627                 :            :         }
     628                 :       1728 :         peerkey = nvme_auth_get_peerkey(peer, peerlen, dhgroup);
     629         [ -  + ]:       1728 :         if (peerkey == NULL) {
     630                 :          0 :                 return -EINVAL;
     631                 :            :         }
     632                 :       1728 :         ctx = EVP_PKEY_CTX_new(key, NULL);
     633         [ -  + ]:       1728 :         if (ctx == NULL) {
     634                 :          0 :                 rc = -ENOMEM;
     635                 :          0 :                 goto out;
     636                 :            :         }
     637         [ -  + ]:       1728 :         if (EVP_PKEY_derive_init(ctx) != 1) {
     638                 :          0 :                 rc = -EIO;
     639                 :          0 :                 goto out;
     640                 :            :         }
     641         [ -  + ]:       1728 :         if (EVP_PKEY_CTX_set_dh_pad(ctx, 1) <= 0) {
     642                 :          0 :                 rc = -EIO;
     643                 :          0 :                 goto out;
     644                 :            :         }
     645         [ -  + ]:       1728 :         if (EVP_PKEY_derive_set_peer(ctx, peerkey) != 1) {
     646                 :          0 :                 SPDK_ERRLOG("Failed to set dhsecret's peer key\n");
     647                 :          0 :                 rc = -EINVAL;
     648                 :          0 :                 goto out;
     649                 :            :         }
     650         [ +  - ]:       1728 :         if (EVP_PKEY_derive(ctx, secret, seclen) != 1) {
     651                 :          0 :                 SPDK_ERRLOG("Failed to derive dhsecret\n");
     652                 :          0 :                 rc = -ENOBUFS;
     653                 :          0 :                 goto out;
     654                 :            :         }
     655                 :       1728 : out:
     656                 :       1728 :         EVP_PKEY_free(peerkey);
     657                 :       1728 :         EVP_PKEY_CTX_free(ctx);
     658                 :            : 
     659                 :       1728 :         return rc;
     660                 :            : }
     661                 :            : 
     662                 :            : static int
     663                 :       4432 : nvme_auth_submit_request(struct spdk_nvme_qpair *qpair,
     664                 :            :                          enum spdk_nvmf_fabric_cmd_types type, uint32_t len)
     665                 :            : {
     666                 :       4432 :         struct spdk_nvme_ctrlr *ctrlr = qpair->ctrlr;
     667                 :       4432 :         struct nvme_request *req = qpair->reserved_req;
     668                 :       4432 :         struct nvme_completion_poll_status *status = qpair->poll_status;
     669                 :       4432 :         struct spdk_nvmf_fabric_auth_recv_cmd rcmd = {};
     670                 :       4432 :         struct spdk_nvmf_fabric_auth_send_cmd scmd = {};
     671                 :            : 
     672         [ -  + ]:       4432 :         assert(len <= NVME_AUTH_DATA_SIZE);
     673         [ -  + ]:       4432 :         memset(&status->cpl, 0, sizeof(status->cpl));
     674                 :       8864 :         status->timeout_tsc = ctrlr->opts.admin_timeout_ms * spdk_get_ticks_hz() / 1000 +
     675                 :       4432 :                               spdk_get_ticks();
     676                 :       4432 :         status->done = false;
     677                 :       4432 :         NVME_INIT_REQUEST(req, nvme_completion_poll_cb, status,
     678                 :            :                           NVME_PAYLOAD_CONTIG(status->dma_data, NULL), len, 0);
     679      [ +  +  - ]:       4432 :         switch (type) {
     680                 :       2576 :         case SPDK_NVMF_FABRIC_COMMAND_AUTHENTICATION_SEND:
     681                 :       2576 :                 scmd.opcode = SPDK_NVME_OPC_FABRIC;
     682                 :       2576 :                 scmd.fctype = type;
     683                 :       2576 :                 scmd.spsp0 = 1;
     684                 :       2576 :                 scmd.spsp1 = 1;
     685                 :       2576 :                 scmd.secp = SPDK_NVMF_AUTH_SECP_NVME;
     686                 :       2576 :                 scmd.tl = len;
     687                 :       2576 :                 memcpy(&req->cmd, &scmd, sizeof(scmd));
     688                 :       2576 :                 break;
     689                 :       1856 :         case SPDK_NVMF_FABRIC_COMMAND_AUTHENTICATION_RECV:
     690                 :       1856 :                 rcmd.opcode = SPDK_NVME_OPC_FABRIC;
     691                 :       1856 :                 rcmd.fctype = type;
     692                 :       1856 :                 rcmd.spsp0 = 1;
     693                 :       1856 :                 rcmd.spsp1 = 1;
     694                 :       1856 :                 rcmd.secp = SPDK_NVMF_AUTH_SECP_NVME;
     695                 :       1856 :                 rcmd.al = len;
     696                 :       1856 :                 memcpy(&req->cmd, &rcmd, sizeof(rcmd));
     697                 :       1856 :                 break;
     698                 :          0 :         default:
     699                 :          0 :                 assert(0 && "invalid command");
     700                 :            :                 return -EINVAL;
     701                 :            :         }
     702                 :            : 
     703                 :       4432 :         return nvme_qpair_submit_request(qpair, req);
     704                 :            : }
     705                 :            : 
     706                 :            : static int
     707                 :       1856 : nvme_auth_recv_message(struct spdk_nvme_qpair *qpair)
     708                 :            : {
     709         [ -  + ]:       1856 :         memset(qpair->poll_status->dma_data, 0, NVME_AUTH_DATA_SIZE);
     710                 :       1856 :         return nvme_auth_submit_request(qpair, SPDK_NVMF_FABRIC_COMMAND_AUTHENTICATION_RECV,
     711                 :            :                                         NVME_AUTH_DATA_SIZE);
     712                 :            : }
     713                 :            : 
     714                 :            : static bool
     715                 :          8 : nvme_auth_send_failure2(struct spdk_nvme_qpair *qpair, enum spdk_nvmf_auth_failure_reason reason)
     716                 :            : {
     717                 :          8 :         struct spdk_nvmf_auth_failure *msg = qpair->poll_status->dma_data;
     718                 :          8 :         struct nvme_auth *auth = &qpair->auth;
     719                 :            : 
     720         [ -  + ]:          8 :         memset(qpair->poll_status->dma_data, 0, NVME_AUTH_DATA_SIZE);
     721                 :          8 :         msg->auth_type = SPDK_NVMF_AUTH_TYPE_COMMON_MESSAGE;
     722                 :          8 :         msg->auth_id = SPDK_NVMF_AUTH_ID_FAILURE2;
     723                 :          8 :         msg->t_id = auth->tid;
     724                 :          8 :         msg->rc = SPDK_NVMF_AUTH_FAILURE;
     725                 :          8 :         msg->rce = reason;
     726                 :            : 
     727                 :          8 :         return nvme_auth_submit_request(qpair, SPDK_NVMF_FABRIC_COMMAND_AUTHENTICATION_SEND,
     728                 :          8 :                                         sizeof(*msg)) == 0;
     729                 :            : }
     730                 :            : 
     731                 :            : static int
     732                 :       1852 : nvme_auth_check_message(struct spdk_nvme_qpair *qpair, enum spdk_nvmf_auth_id auth_id)
     733                 :            : {
     734                 :       1852 :         struct spdk_nvmf_auth_failure *msg = qpair->poll_status->dma_data;
     735                 :       1852 :         const char *reason = NULL;
     736                 :       1852 :         const char *reasons[] = {
     737                 :            :                 [SPDK_NVMF_AUTH_FAILED] = "authentication failed",
     738                 :            :                 [SPDK_NVMF_AUTH_PROTOCOL_UNUSABLE] = "protocol not usable",
     739                 :            :                 [SPDK_NVMF_AUTH_SCC_MISMATCH] = "secure channel concatenation mismatch",
     740                 :            :                 [SPDK_NVMF_AUTH_HASH_UNUSABLE] = "hash not usable",
     741                 :            :                 [SPDK_NVMF_AUTH_DHGROUP_UNUSABLE] = "dhgroup not usable",
     742                 :            :                 [SPDK_NVMF_AUTH_INCORRECT_PAYLOAD] = "incorrect payload",
     743                 :            :                 [SPDK_NVMF_AUTH_INCORRECT_PROTOCOL_MESSAGE] = "incorrect protocol message",
     744                 :            :         };
     745                 :            : 
     746      [ +  +  - ]:       1852 :         switch (msg->auth_type) {
     747                 :       1836 :         case SPDK_NVMF_AUTH_TYPE_DHCHAP:
     748         [ +  - ]:       1836 :                 if (msg->auth_id == auth_id) {
     749                 :       1836 :                         return 0;
     750                 :            :                 }
     751                 :          0 :                 AUTH_ERRLOG(qpair, "received unexpected DH-HMAC-CHAP message id: %u (expected: %u)\n",
     752                 :            :                             msg->auth_id, auth_id);
     753                 :          0 :                 break;
     754                 :         16 :         case SPDK_NVMF_AUTH_TYPE_COMMON_MESSAGE:
     755                 :            :                 /* The only common message that we can expect to receive is AUTH_failure1 */
     756         [ -  + ]:         16 :                 if (msg->auth_id != SPDK_NVMF_AUTH_ID_FAILURE1) {
     757                 :          0 :                         AUTH_ERRLOG(qpair, "received unexpected common message id: %u\n",
     758                 :            :                                     msg->auth_id);
     759                 :          0 :                         break;
     760                 :            :                 }
     761   [ +  -  +  - ]:         16 :                 if (msg->rc == SPDK_NVMF_AUTH_FAILURE && msg->rce < SPDK_COUNTOF(reasons)) {
     762                 :         16 :                         reason = reasons[msg->rce];
     763                 :            :                 }
     764                 :         16 :                 AUTH_ERRLOG(qpair, "received AUTH_failure1: rc=%d, rce=%d (%s)\n",
     765                 :            :                             msg->rc, msg->rce, reason);
     766                 :         16 :                 nvme_auth_set_failure(qpair, -EACCES, false);
     767                 :         16 :                 return -EACCES;
     768                 :          0 :         default:
     769                 :          0 :                 AUTH_ERRLOG(qpair, "received unknown message type: %u\n", msg->auth_type);
     770                 :          0 :                 break;
     771                 :            :         }
     772                 :            : 
     773                 :          0 :         nvme_auth_set_failure(qpair, -EACCES,
     774                 :          0 :                               nvme_auth_send_failure2(qpair,
     775                 :            :                                               SPDK_NVMF_AUTH_INCORRECT_PROTOCOL_MESSAGE));
     776                 :          0 :         return -EACCES;
     777                 :            : }
     778                 :            : 
     779                 :            : static int
     780                 :        936 : nvme_auth_send_negotiate(struct spdk_nvme_qpair *qpair)
     781                 :            : {
     782                 :        936 :         struct nvme_auth *auth = &qpair->auth;
     783                 :        936 :         struct spdk_nvmf_auth_negotiate *msg = qpair->poll_status->dma_data;
     784                 :        936 :         struct spdk_nvmf_auth_descriptor *desc = msg->descriptors;
     785                 :            :         size_t i;
     786                 :            : 
     787         [ -  + ]:        936 :         memset(qpair->poll_status->dma_data, 0, NVME_AUTH_DATA_SIZE);
     788                 :        936 :         desc->auth_id = SPDK_NVMF_AUTH_TYPE_DHCHAP;
     789                 :            :         assert(SPDK_COUNTOF(g_digests) <= sizeof(desc->hash_id_list));
     790                 :            :         assert(SPDK_COUNTOF(g_dhgroups) <= sizeof(desc->dhg_id_list));
     791                 :            : 
     792         [ +  + ]:       3744 :         for (i = 0; i < SPDK_COUNTOF(g_digests); ++i) {
     793         [ +  + ]:       2808 :                 if (!nvme_auth_digest_allowed(qpair, g_digests[i].id)) {
     794                 :       1800 :                         continue;
     795                 :            :                 }
     796   [ -  +  +  - ]:       1008 :                 AUTH_DEBUGLOG(qpair, "digest: %u (%s)\n", g_digests[i].id,
     797                 :            :                               spdk_nvme_dhchap_get_digest_name(g_digests[i].id));
     798                 :       1008 :                 desc->hash_id_list[desc->halen++] = g_digests[i].id;
     799                 :            :         }
     800         [ +  + ]:       6552 :         for (i = 0; i < SPDK_COUNTOF(g_dhgroups); ++i) {
     801         [ +  + ]:       5616 :                 if (!nvme_auth_dhgroup_allowed(qpair, g_dhgroups[i].id)) {
     802                 :       4508 :                         continue;
     803                 :            :                 }
     804   [ -  +  +  - ]:       1108 :                 AUTH_DEBUGLOG(qpair, "dhgroup: %u (%s)\n", g_dhgroups[i].id,
     805                 :            :                               spdk_nvme_dhchap_get_dhgroup_name(g_dhgroups[i].id));
     806                 :       1108 :                 desc->dhg_id_list[desc->dhlen++] = g_dhgroups[i].id;
     807                 :            :         }
     808                 :            : 
     809                 :        936 :         msg->auth_type = SPDK_NVMF_AUTH_TYPE_COMMON_MESSAGE;
     810                 :        936 :         msg->auth_id = SPDK_NVMF_AUTH_ID_NEGOTIATE;
     811                 :        936 :         msg->t_id = auth->tid;
     812                 :        936 :         msg->sc_c = SPDK_NVMF_AUTH_SCC_DISABLED;
     813                 :        936 :         msg->napd = 1;
     814                 :            : 
     815                 :       1872 :         return nvme_auth_submit_request(qpair, SPDK_NVMF_FABRIC_COMMAND_AUTHENTICATION_SEND,
     816                 :        936 :                                         sizeof(*msg) + msg->napd * sizeof(*desc));
     817                 :            : }
     818                 :            : 
     819                 :            : static int
     820                 :        930 : nvme_auth_check_challenge(struct spdk_nvme_qpair *qpair)
     821                 :            : {
     822                 :        930 :         struct spdk_nvmf_dhchap_challenge *challenge = qpair->poll_status->dma_data;
     823                 :        930 :         struct nvme_auth *auth = &qpair->auth;
     824                 :            :         uint8_t hl;
     825                 :            :         int rc;
     826                 :            : 
     827                 :        930 :         rc = nvme_auth_check_message(qpair, SPDK_NVMF_AUTH_ID_DHCHAP_CHALLENGE);
     828         [ +  + ]:        930 :         if (rc != 0) {
     829                 :          6 :                 return rc;
     830                 :            :         }
     831                 :            : 
     832         [ -  + ]:        924 :         if (challenge->t_id != auth->tid) {
     833                 :          0 :                 AUTH_ERRLOG(qpair, "unexpected tid: received=%u, expected=%u\n",
     834                 :            :                             challenge->t_id, auth->tid);
     835                 :          0 :                 goto error;
     836                 :            :         }
     837                 :            : 
     838         [ -  + ]:        924 :         if (challenge->seqnum == 0) {
     839                 :          0 :                 AUTH_ERRLOG(qpair, "received challenge with seqnum=0\n");
     840                 :          0 :                 goto error;
     841                 :            :         }
     842                 :            : 
     843                 :        924 :         hl = spdk_nvme_dhchap_get_digest_length(challenge->hash_id);
     844         [ -  + ]:        924 :         if (hl == 0) {
     845                 :          0 :                 AUTH_ERRLOG(qpair, "unsupported hash function: 0x%x\n", challenge->hash_id);
     846                 :          0 :                 goto error;
     847                 :            :         }
     848                 :            : 
     849         [ -  + ]:        924 :         if (challenge->hl != hl) {
     850                 :          0 :                 AUTH_ERRLOG(qpair, "unexpected hash length: received=%u, expected=%u\n",
     851                 :            :                             challenge->hl, hl);
     852                 :          0 :                 goto error;
     853                 :            :         }
     854                 :            : 
     855      [ +  +  - ]:        924 :         switch (challenge->dhg_id) {
     856                 :         48 :         case SPDK_NVMF_DHCHAP_DHGROUP_NULL:
     857         [ -  + ]:         48 :                 if (challenge->dhvlen != 0) {
     858                 :          0 :                         AUTH_ERRLOG(qpair, "unexpected dhvlen=%u for dhgroup 0\n",
     859                 :            :                                     challenge->dhvlen);
     860                 :          0 :                         goto error;
     861                 :            :                 }
     862                 :         48 :                 break;
     863                 :        876 :         case SPDK_NVMF_DHCHAP_DHGROUP_2048:
     864                 :            :         case SPDK_NVMF_DHCHAP_DHGROUP_3072:
     865                 :            :         case SPDK_NVMF_DHCHAP_DHGROUP_4096:
     866                 :            :         case SPDK_NVMF_DHCHAP_DHGROUP_6144:
     867                 :            :         case SPDK_NVMF_DHCHAP_DHGROUP_8192:
     868         [ +  - ]:        876 :                 if (sizeof(*challenge) + hl + challenge->dhvlen > NVME_AUTH_DATA_SIZE ||
     869         [ -  + ]:        876 :                     challenge->dhvlen == 0) {
     870                 :          0 :                         AUTH_ERRLOG(qpair, "invalid dhvlen=%u for dhgroup %u\n",
     871                 :            :                                     challenge->dhvlen, challenge->dhg_id);
     872                 :          0 :                         goto error;
     873                 :            :                 }
     874                 :        876 :                 break;
     875                 :          0 :         default:
     876                 :          0 :                 AUTH_ERRLOG(qpair, "unsupported dhgroup: 0x%x\n", challenge->dhg_id);
     877                 :          0 :                 goto error;
     878                 :            :         }
     879                 :            : 
     880         [ -  + ]:        924 :         if (!nvme_auth_digest_allowed(qpair, challenge->hash_id)) {
     881                 :          0 :                 AUTH_ERRLOG(qpair, "received disallowed digest: %u (%s)\n", challenge->hash_id,
     882                 :            :                             spdk_nvme_dhchap_get_digest_name(challenge->hash_id));
     883                 :          0 :                 goto error;
     884                 :            :         }
     885                 :            : 
     886         [ -  + ]:        924 :         if (!nvme_auth_dhgroup_allowed(qpair, challenge->dhg_id)) {
     887                 :          0 :                 AUTH_ERRLOG(qpair, "received disallowed dhgroup: %u (%s)\n", challenge->dhg_id,
     888                 :            :                             spdk_nvme_dhchap_get_dhgroup_name(challenge->dhg_id));
     889                 :          0 :                 goto error;
     890                 :            :         }
     891                 :            : 
     892                 :        924 :         return 0;
     893                 :          0 : error:
     894                 :          0 :         nvme_auth_set_failure(qpair, -EACCES,
     895                 :          0 :                               nvme_auth_send_failure2(qpair, SPDK_NVMF_AUTH_INCORRECT_PAYLOAD));
     896                 :          0 :         return -EACCES;
     897                 :            : }
     898                 :            : 
     899                 :            : static int
     900                 :        924 : nvme_auth_send_reply(struct spdk_nvme_qpair *qpair)
     901                 :            : {
     902                 :        924 :         struct nvme_completion_poll_status *status = qpair->poll_status;
     903                 :        924 :         struct spdk_nvme_ctrlr *ctrlr = qpair->ctrlr;
     904                 :        924 :         struct spdk_nvmf_dhchap_challenge *challenge = status->dma_data;
     905                 :        924 :         struct spdk_nvmf_dhchap_reply *reply = status->dma_data;
     906                 :        924 :         struct nvme_auth *auth = &qpair->auth;
     907                 :          0 :         struct spdk_nvme_dhchap_dhkey *dhkey;
     908                 :          0 :         uint8_t hl, response[NVME_AUTH_DATA_SIZE];
     909                 :          0 :         uint8_t pubkey[NVME_AUTH_DH_KEY_MAX_SIZE];
     910                 :          0 :         uint8_t dhsec[NVME_AUTH_DH_KEY_MAX_SIZE];
     911                 :        924 :         uint8_t ctrlr_challenge[NVME_AUTH_DIGEST_MAX_SIZE] = {};
     912                 :        924 :         size_t dhseclen = 0, publen = 0;
     913                 :        924 :         uint32_t seqnum = 0;
     914                 :            :         int rc;
     915                 :            : 
     916                 :        924 :         auth->hash = challenge->hash_id;
     917                 :        924 :         hl = spdk_nvme_dhchap_get_digest_length(challenge->hash_id);
     918         [ +  + ]:        924 :         if (challenge->dhg_id != SPDK_NVMF_DHCHAP_DHGROUP_NULL) {
     919                 :        876 :                 dhseclen = sizeof(dhsec);
     920                 :        876 :                 publen = sizeof(pubkey);
     921   [ -  +  +  - ]:        876 :                 AUTH_LOGDUMP("ctrlr pubkey:", &challenge->cval[hl], challenge->dhvlen);
     922                 :       1752 :                 dhkey = spdk_nvme_dhchap_generate_dhkey(
     923                 :        876 :                                 (enum spdk_nvmf_dhchap_dhgroup)challenge->dhg_id);
     924         [ -  + ]:        876 :                 if (dhkey == NULL) {
     925                 :          0 :                         return -EINVAL;
     926                 :            :                 }
     927                 :        876 :                 rc = spdk_nvme_dhchap_dhkey_get_pubkey(dhkey, pubkey, &publen);
     928         [ -  + ]:        876 :                 if (rc != 0) {
     929                 :          0 :                         spdk_nvme_dhchap_dhkey_free(&dhkey);
     930                 :          0 :                         return rc;
     931                 :            :                 }
     932   [ -  +  +  - ]:        876 :                 AUTH_LOGDUMP("host pubkey:", pubkey, publen);
     933                 :       1752 :                 rc = spdk_nvme_dhchap_dhkey_derive_secret(dhkey,
     934                 :        876 :                                 &challenge->cval[hl], challenge->dhvlen, dhsec, &dhseclen);
     935                 :        876 :                 spdk_nvme_dhchap_dhkey_free(&dhkey);
     936         [ -  + ]:        876 :                 if (rc != 0) {
     937                 :          0 :                         return rc;
     938                 :            :                 }
     939                 :            : 
     940   [ -  +  +  - ]:        876 :                 AUTH_LOGDUMP("dh secret:", dhsec, dhseclen);
     941                 :            :         }
     942                 :            : 
     943   [ -  +  +  - ]:        924 :         AUTH_DEBUGLOG(qpair, "key=%s, hash=%u, dhgroup=%u, seq=%u, tid=%u, subnqn=%s, hostnqn=%s, "
     944                 :            :                       "len=%u\n", spdk_key_get_name(ctrlr->opts.dhchap_key),
     945                 :            :                       challenge->hash_id, challenge->dhg_id, challenge->seqnum, auth->tid,
     946                 :            :                       ctrlr->trid.subnqn, ctrlr->opts.hostnqn, hl);
     947                 :       2772 :         rc = spdk_nvme_dhchap_calculate(ctrlr->opts.dhchap_key,
     948                 :        924 :                                         (enum spdk_nvmf_dhchap_hash)challenge->hash_id,
     949                 :        924 :                                         "HostHost", challenge->seqnum, auth->tid, 0,
     950                 :        924 :                                         ctrlr->opts.hostnqn, ctrlr->trid.subnqn,
     951                 :        924 :                                         dhseclen > 0 ? dhsec : NULL, dhseclen,
     952         [ +  + ]:        924 :                                         challenge->cval, response);
     953         [ -  + ]:        924 :         if (rc != 0) {
     954                 :          0 :                 AUTH_ERRLOG(qpair, "failed to calculate response: %s\n", spdk_strerror(-rc));
     955                 :          0 :                 return rc;
     956                 :            :         }
     957                 :            : 
     958         [ +  + ]:        924 :         if (ctrlr->opts.dhchap_ctrlr_key != NULL) {
     959                 :        720 :                 seqnum = nvme_auth_get_seqnum(qpair);
     960         [ -  + ]:        720 :                 if (seqnum == 0) {
     961                 :          0 :                         return -EIO;
     962                 :            :                 }
     963                 :            : 
     964         [ -  + ]:        720 :                 assert(sizeof(ctrlr_challenge) >= hl);
     965                 :        720 :                 rc = RAND_bytes(ctrlr_challenge, hl);
     966         [ -  + ]:        720 :                 if (rc != 1) {
     967                 :          0 :                         return -EIO;
     968                 :            :                 }
     969                 :            : 
     970                 :       1440 :                 rc = spdk_nvme_dhchap_calculate(ctrlr->opts.dhchap_ctrlr_key,
     971                 :        720 :                                                 (enum spdk_nvmf_dhchap_hash)challenge->hash_id,
     972                 :        720 :                                                 "Controller", seqnum, auth->tid, 0,
     973                 :        720 :                                                 ctrlr->trid.subnqn, ctrlr->opts.hostnqn,
     974                 :        720 :                                                 dhseclen > 0 ? dhsec : NULL, dhseclen,
     975         [ +  + ]:        720 :                                                 ctrlr_challenge, auth->challenge);
     976         [ -  + ]:        720 :                 if (rc != 0) {
     977                 :          0 :                         AUTH_ERRLOG(qpair, "failed to calculate controller's response: %s\n",
     978                 :            :                                     spdk_strerror(-rc));
     979                 :          0 :                         return rc;
     980                 :            :                 }
     981                 :            :         }
     982                 :            : 
     983                 :            :         /* Now that the response has been calculated, send the reply */
     984         [ -  + ]:        924 :         memset(qpair->poll_status->dma_data, 0, NVME_AUTH_DATA_SIZE);
     985         [ -  + ]:        924 :         assert(sizeof(*reply) + 2 * hl + publen <= NVME_AUTH_DATA_SIZE);
     986   [ -  +  -  + ]:        924 :         memcpy(reply->rval, response, hl);
     987   [ -  +  -  + ]:        924 :         memcpy(&reply->rval[1 * hl], ctrlr_challenge, hl);
     988   [ -  +  -  + ]:        924 :         memcpy(&reply->rval[2 * hl], pubkey, publen);
     989                 :            : 
     990                 :        924 :         reply->auth_type = SPDK_NVMF_AUTH_TYPE_DHCHAP;
     991                 :        924 :         reply->auth_id = SPDK_NVMF_AUTH_ID_DHCHAP_REPLY;
     992                 :        924 :         reply->t_id = auth->tid;
     993                 :        924 :         reply->hl = hl;
     994                 :        924 :         reply->cvalid = ctrlr->opts.dhchap_ctrlr_key != NULL;
     995                 :        924 :         reply->dhvlen = publen;
     996                 :        924 :         reply->seqnum = seqnum;
     997                 :            : 
     998                 :            :         /* The 2 * reply->hl below is because the spec says that both rval[hl] and cval[hl] must
     999                 :            :          * always be part of the reply message, even cvalid is zero.
    1000                 :            :          */
    1001                 :        924 :         return nvme_auth_submit_request(qpair, SPDK_NVMF_FABRIC_COMMAND_AUTHENTICATION_SEND,
    1002                 :        924 :                                         sizeof(*reply) + 2 * reply->hl + publen);
    1003                 :            : }
    1004                 :            : 
    1005                 :            : static int
    1006                 :        922 : nvme_auth_check_success1(struct spdk_nvme_qpair *qpair)
    1007                 :            : {
    1008                 :        922 :         struct spdk_nvmf_dhchap_success1 *msg = qpair->poll_status->dma_data;
    1009                 :        922 :         struct spdk_nvme_ctrlr *ctrlr = qpair->ctrlr;
    1010                 :        922 :         struct nvme_auth *auth = &qpair->auth;
    1011                 :            :         uint8_t hl;
    1012                 :            :         int rc, status;
    1013                 :            : 
    1014                 :        922 :         rc = nvme_auth_check_message(qpair, SPDK_NVMF_AUTH_ID_DHCHAP_SUCCESS1);
    1015         [ +  + ]:        922 :         if (rc != 0) {
    1016                 :         10 :                 return rc;
    1017                 :            :         }
    1018                 :            : 
    1019         [ -  + ]:        912 :         if (msg->t_id != auth->tid) {
    1020                 :          0 :                 AUTH_ERRLOG(qpair, "unexpected tid: received=%u, expected=%u\n",
    1021                 :            :                             msg->t_id, auth->tid);
    1022                 :          0 :                 status = SPDK_NVMF_AUTH_INCORRECT_PAYLOAD;
    1023                 :          0 :                 goto error;
    1024                 :            :         }
    1025                 :            : 
    1026         [ +  + ]:        912 :         if (ctrlr->opts.dhchap_ctrlr_key != NULL) {
    1027         [ -  + ]:        716 :                 if (!msg->rvalid) {
    1028                 :          0 :                         AUTH_ERRLOG(qpair, "received rvalid=0, expected response\n");
    1029                 :          0 :                         status = SPDK_NVMF_AUTH_INCORRECT_PAYLOAD;
    1030                 :          0 :                         goto error;
    1031                 :            :                 }
    1032                 :            : 
    1033                 :        716 :                 hl = spdk_nvme_dhchap_get_digest_length(auth->hash);
    1034         [ -  + ]:        716 :                 if (msg->hl != hl) {
    1035                 :          0 :                         AUTH_ERRLOG(qpair, "received invalid hl=%u, expected=%u\n", msg->hl, hl);
    1036                 :          0 :                         status = SPDK_NVMF_AUTH_INCORRECT_PAYLOAD;
    1037                 :          0 :                         goto error;
    1038                 :            :                 }
    1039                 :            : 
    1040   [ -  +  -  +  :        716 :                 if (memcmp(msg->rval, auth->challenge, hl) != 0) {
                   +  + ]
    1041                 :          8 :                         AUTH_ERRLOG(qpair, "controller challenge mismatch\n");
    1042   [ -  +  +  - ]:          8 :                         AUTH_LOGDUMP("received:", msg->rval, hl);
    1043   [ -  +  +  - ]:          8 :                         AUTH_LOGDUMP("expected:", auth->challenge, hl);
    1044                 :          8 :                         status = SPDK_NVMF_AUTH_FAILED;
    1045                 :          8 :                         goto error;
    1046                 :            :                 }
    1047                 :            :         }
    1048                 :            : 
    1049                 :        904 :         return 0;
    1050                 :          8 : error:
    1051                 :          8 :         nvme_auth_set_failure(qpair, -EACCES, nvme_auth_send_failure2(qpair, status));
    1052                 :            : 
    1053                 :          8 :         return -EACCES;
    1054                 :            : }
    1055                 :            : 
    1056                 :            : static int
    1057                 :        708 : nvme_auth_send_success2(struct spdk_nvme_qpair *qpair)
    1058                 :            : {
    1059                 :        708 :         struct spdk_nvmf_dhchap_success2 *msg = qpair->poll_status->dma_data;
    1060                 :        708 :         struct nvme_auth *auth = &qpair->auth;
    1061                 :            : 
    1062         [ -  + ]:        708 :         memset(qpair->poll_status->dma_data, 0, NVME_AUTH_DATA_SIZE);
    1063                 :        708 :         msg->auth_type = SPDK_NVMF_AUTH_TYPE_DHCHAP;
    1064                 :        708 :         msg->auth_id = SPDK_NVMF_AUTH_ID_DHCHAP_SUCCESS2;
    1065                 :        708 :         msg->t_id = auth->tid;
    1066                 :            : 
    1067                 :        708 :         return nvme_auth_submit_request(qpair, SPDK_NVMF_FABRIC_COMMAND_AUTHENTICATION_SEND,
    1068                 :            :                                         sizeof(*msg));
    1069                 :            : }
    1070                 :            : 
    1071                 :            : int
    1072                 :     945594 : nvme_fabric_qpair_authenticate_poll(struct spdk_nvme_qpair *qpair)
    1073                 :            : {
    1074                 :     945594 :         struct spdk_nvme_ctrlr *ctrlr = qpair->ctrlr;
    1075                 :     945594 :         struct nvme_auth *auth = &qpair->auth;
    1076                 :     945594 :         struct nvme_completion_poll_status *status = qpair->poll_status;
    1077                 :            :         enum nvme_qpair_auth_state prev_state;
    1078                 :            :         int rc;
    1079                 :            : 
    1080                 :            :         do {
    1081                 :     950962 :                 prev_state = auth->state;
    1082                 :            : 
    1083   [ +  +  +  +  :     950962 :                 switch (auth->state) {
             +  +  +  - ]
    1084                 :        936 :                 case NVME_QPAIR_AUTH_STATE_NEGOTIATE:
    1085                 :        936 :                         rc = nvme_auth_send_negotiate(qpair);
    1086         [ -  + ]:        936 :                         if (rc != 0) {
    1087                 :          0 :                                 nvme_auth_set_failure(qpair, rc, false);
    1088                 :          0 :                                 AUTH_ERRLOG(qpair, "failed to send AUTH_negotiate: %s\n",
    1089                 :            :                                             spdk_strerror(-rc));
    1090                 :          0 :                                 break;
    1091                 :            :                         }
    1092                 :        936 :                         nvme_auth_set_state(qpair, NVME_QPAIR_AUTH_STATE_AWAIT_NEGOTIATE);
    1093                 :        936 :                         break;
    1094                 :       4196 :                 case NVME_QPAIR_AUTH_STATE_AWAIT_NEGOTIATE:
    1095                 :       4196 :                         rc = nvme_wait_for_completion_robust_lock_timeout_poll(qpair, status, NULL);
    1096         [ +  + ]:       4196 :                         if (rc != 0) {
    1097         [ +  + ]:       3264 :                                 if (rc != -EAGAIN) {
    1098                 :          4 :                                         nvme_auth_print_cpl(qpair, "AUTH_negotiate");
    1099                 :          4 :                                         nvme_auth_set_failure(qpair, rc, false);
    1100                 :            :                                 }
    1101                 :       3264 :                                 break;
    1102                 :            :                         }
    1103                 :            :                         /* Negotiate has been sent, try to receive the challenge */
    1104                 :        932 :                         rc = nvme_auth_recv_message(qpair);
    1105         [ -  + ]:        932 :                         if (rc != 0) {
    1106                 :          0 :                                 nvme_auth_set_failure(qpair, rc, false);
    1107                 :          0 :                                 AUTH_ERRLOG(qpair, "failed to recv DH-HMAC-CHAP_challenge: %s\n",
    1108                 :            :                                             spdk_strerror(-rc));
    1109                 :          0 :                                 break;
    1110                 :            :                         }
    1111                 :        932 :                         nvme_auth_set_state(qpair, NVME_QPAIR_AUTH_STATE_AWAIT_CHALLENGE);
    1112                 :        932 :                         break;
    1113                 :      63669 :                 case NVME_QPAIR_AUTH_STATE_AWAIT_CHALLENGE:
    1114                 :      63669 :                         rc = nvme_wait_for_completion_robust_lock_timeout_poll(qpair, status, NULL);
    1115         [ +  + ]:      63669 :                         if (rc != 0) {
    1116         [ +  + ]:      62739 :                                 if (rc != -EAGAIN) {
    1117                 :          2 :                                         nvme_auth_print_cpl(qpair, "DH-HMAC-CHAP_challenge");
    1118                 :          2 :                                         nvme_auth_set_failure(qpair, rc, false);
    1119                 :            :                                 }
    1120                 :      62739 :                                 break;
    1121                 :            :                         }
    1122                 :        930 :                         rc = nvme_auth_check_challenge(qpair);
    1123         [ +  + ]:        930 :                         if (rc != 0) {
    1124                 :          6 :                                 break;
    1125                 :            :                         }
    1126                 :        924 :                         rc = nvme_auth_send_reply(qpair);
    1127         [ -  + ]:        924 :                         if (rc != 0) {
    1128                 :          0 :                                 nvme_auth_set_failure(qpair, rc, false);
    1129                 :          0 :                                 AUTH_ERRLOG(qpair, "failed to send DH-HMAC-CHAP_reply: %s\n",
    1130                 :            :                                             spdk_strerror(-rc));
    1131                 :          0 :                                 break;
    1132                 :            :                         }
    1133                 :        924 :                         nvme_auth_set_state(qpair, NVME_QPAIR_AUTH_STATE_AWAIT_REPLY);
    1134                 :        924 :                         break;
    1135                 :     815491 :                 case NVME_QPAIR_AUTH_STATE_AWAIT_REPLY:
    1136                 :     815491 :                         rc = nvme_wait_for_completion_robust_lock_timeout_poll(qpair, status, NULL);
    1137         [ +  + ]:     815491 :                         if (rc != 0) {
    1138         [ -  + ]:     814567 :                                 if (rc != -EAGAIN) {
    1139                 :          0 :                                         nvme_auth_print_cpl(qpair, "DH-HMAC-CHAP_reply");
    1140                 :          0 :                                         nvme_auth_set_failure(qpair, rc, false);
    1141                 :            :                                 }
    1142                 :     814567 :                                 break;
    1143                 :            :                         }
    1144                 :            :                         /* Reply has been sent, try to receive response */
    1145                 :        924 :                         rc = nvme_auth_recv_message(qpair);
    1146         [ -  + ]:        924 :                         if (rc != 0) {
    1147                 :          0 :                                 nvme_auth_set_failure(qpair, rc, false);
    1148                 :          0 :                                 AUTH_ERRLOG(qpair, "failed to recv DH-HMAC-CHAP_success1: %s\n",
    1149                 :            :                                             spdk_strerror(-rc));
    1150                 :          0 :                                 break;
    1151                 :            :                         }
    1152                 :        924 :                         nvme_auth_set_state(qpair, NVME_QPAIR_AUTH_STATE_AWAIT_SUCCESS1);
    1153                 :        924 :                         break;
    1154                 :      63285 :                 case NVME_QPAIR_AUTH_STATE_AWAIT_SUCCESS1:
    1155                 :      63285 :                         rc = nvme_wait_for_completion_robust_lock_timeout_poll(qpair, status, NULL);
    1156         [ +  + ]:      63285 :                         if (rc != 0) {
    1157         [ +  + ]:      62363 :                                 if (rc != -EAGAIN) {
    1158                 :          2 :                                         nvme_auth_print_cpl(qpair, "DH-HMAC-CHAP_success1");
    1159                 :          2 :                                         nvme_auth_set_failure(qpair, rc, false);
    1160                 :            :                                 }
    1161                 :      62363 :                                 break;
    1162                 :            :                         }
    1163                 :        922 :                         rc = nvme_auth_check_success1(qpair);
    1164         [ +  + ]:        922 :                         if (rc != 0) {
    1165                 :         18 :                                 break;
    1166                 :            :                         }
    1167   [ -  +  +  - ]:        904 :                         AUTH_DEBUGLOG(qpair, "authentication completed successfully\n");
    1168         [ +  + ]:        904 :                         if (ctrlr->opts.dhchap_ctrlr_key != NULL) {
    1169                 :        708 :                                 rc = nvme_auth_send_success2(qpair);
    1170         [ -  + ]:        708 :                                 if (rc != 0) {
    1171                 :          0 :                                         AUTH_ERRLOG(qpair, "failed to send DH-HMAC-CHAP_success2: "
    1172                 :            :                                                     "%s\n", spdk_strerror(rc));
    1173                 :          0 :                                         nvme_auth_set_failure(qpair, rc, false);
    1174                 :          0 :                                         break;
    1175                 :            :                                 }
    1176                 :        708 :                                 nvme_auth_set_state(qpair, NVME_QPAIR_AUTH_STATE_AWAIT_SUCCESS2);
    1177                 :        708 :                                 break;
    1178                 :            :                         }
    1179                 :        196 :                         nvme_auth_set_state(qpair, NVME_QPAIR_AUTH_STATE_DONE);
    1180                 :        196 :                         break;
    1181                 :       2314 :                 case NVME_QPAIR_AUTH_STATE_AWAIT_SUCCESS2:
    1182                 :            :                 case NVME_QPAIR_AUTH_STATE_AWAIT_FAILURE2:
    1183                 :       2314 :                         rc = nvme_wait_for_completion_robust_lock_timeout_poll(qpair, status, NULL);
    1184         [ +  + ]:       2314 :                         if (rc == -EAGAIN) {
    1185                 :       1598 :                                 break;
    1186                 :            :                         }
    1187                 :        716 :                         nvme_auth_set_state(qpair, NVME_QPAIR_AUTH_STATE_DONE);
    1188                 :        716 :                         break;
    1189                 :       1071 :                 case NVME_QPAIR_AUTH_STATE_DONE:
    1190   [ +  +  -  +  :       1071 :                         if (qpair->poll_status != NULL && !status->timed_out) {
                   +  + ]
    1191                 :        932 :                                 qpair->poll_status = NULL;
    1192                 :        932 :                                 spdk_free(status->dma_data);
    1193                 :        932 :                                 free(status);
    1194                 :            :                         }
    1195                 :       1071 :                         return auth->status;
    1196                 :          0 :                 default:
    1197                 :          0 :                         assert(0 && "invalid state");
    1198                 :            :                         return -EINVAL;
    1199                 :            :                 }
    1200         [ +  + ]:     949891 :         } while (auth->state != prev_state);
    1201                 :            : 
    1202                 :     944523 :         return -EAGAIN;
    1203                 :            : }
    1204                 :            : 
    1205                 :            : int
    1206                 :        940 : nvme_fabric_qpair_authenticate_async(struct spdk_nvme_qpair *qpair)
    1207                 :            : {
    1208                 :        940 :         struct spdk_nvme_ctrlr *ctrlr = qpair->ctrlr;
    1209                 :            :         struct nvme_completion_poll_status *status;
    1210                 :        940 :         struct nvme_auth *auth = &qpair->auth;
    1211                 :            :         int rc;
    1212                 :            : 
    1213         [ +  + ]:        940 :         if (ctrlr->opts.dhchap_key == NULL) {
    1214                 :          4 :                 AUTH_ERRLOG(qpair, "missing DH-HMAC-CHAP key\n");
    1215                 :          4 :                 return -ENOKEY;
    1216                 :            :         }
    1217                 :            : 
    1218         [ -  + ]:        936 :         if (qpair->auth.flags & NVME_QPAIR_AUTH_FLAG_ASCR) {
    1219                 :          0 :                 AUTH_ERRLOG(qpair, "secure channel concatentation is not supported\n");
    1220                 :          0 :                 return -EINVAL;
    1221                 :            :         }
    1222                 :            : 
    1223                 :        936 :         status = calloc(1, sizeof(*qpair->poll_status));
    1224         [ -  + ]:        936 :         if (!status) {
    1225                 :          0 :                 AUTH_ERRLOG(qpair, "failed to allocate poll status\n");
    1226                 :          0 :                 return -ENOMEM;
    1227                 :            :         }
    1228                 :            : 
    1229                 :        936 :         status->dma_data = spdk_zmalloc(NVME_AUTH_DATA_SIZE, 0, NULL, SPDK_ENV_LCORE_ID_ANY,
    1230                 :            :                                         SPDK_MALLOC_DMA);
    1231         [ -  + ]:        936 :         if (!status->dma_data) {
    1232                 :          0 :                 AUTH_ERRLOG(qpair, "failed to allocate poll status\n");
    1233                 :          0 :                 free(status);
    1234                 :          0 :                 return -ENOMEM;
    1235                 :            :         }
    1236                 :            : 
    1237         [ -  + ]:        936 :         assert(qpair->poll_status == NULL);
    1238                 :        936 :         qpair->poll_status = status;
    1239                 :            : 
    1240                 :        936 :         nvme_ctrlr_lock(ctrlr);
    1241                 :        936 :         auth->tid = ctrlr->auth_tid++;
    1242                 :        936 :         nvme_ctrlr_unlock(ctrlr);
    1243                 :            : 
    1244                 :        936 :         nvme_auth_set_state(qpair, NVME_QPAIR_AUTH_STATE_NEGOTIATE);
    1245                 :            : 
    1246                 :            :         /* Do the initial poll to kick-start the state machine */
    1247                 :        936 :         rc = nvme_fabric_qpair_authenticate_poll(qpair);
    1248         [ +  + ]:        936 :         return rc != -EAGAIN ? rc : 0;
    1249                 :            : }
    1250                 :            : #endif /* SPDK_CONFIG_EVP_MAC */
    1251                 :            : 
    1252                 :       2692 : SPDK_LOG_REGISTER_COMPONENT(nvme_auth)

Generated by: LCOV version 1.14