Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'nvme-7.1-2026-03-27' of git://git.infradead.org/nvme into for-7.1/block

Pull NVMe updates from Keith:

"- Fabrics authentication updates (Eric, Alistar)
- Enanced block queue limits support (Caleb)
- Workqueue usage updates (Marco)
- A new write zeroes device quirk (Robert)
- Tagset cleanup fix for loop device (Nilay)"

* tag 'nvme-7.1-2026-03-27' of git://git.infradead.org/nvme: (41 commits)
nvme-loop: do not cancel I/O and admin tagset during ctrl reset/shutdown
nvme: add WQ_PERCPU to alloc_workqueue users
nvmet-fc: add WQ_PERCPU to alloc_workqueue users
nvmet: replace use of system_wq with system_percpu_wq
nvme-auth: Don't propose NVME_AUTH_DHGROUP_NULL with SC_C
nvme: Add the DHCHAP maximum HD IDs
nvme-pci: add NVME_QUIRK_DISABLE_WRITE_ZEROES for Kingston OM3SGP4
nvme: respect NVME_QUIRK_DISABLE_WRITE_ZEROES when wzsl is set
nvmet: report NPDGL and NPDAL
nvmet: use NVME_NS_FEAT_OPTPERF_SHIFT
nvme: set discard_granularity from NPDG/NPDA
nvme: add from0based() helper
nvme: always issue I/O Command Set specific Identify Namespace
nvme: update nvme_id_ns OPTPERF constants
nvme: fold nvme_config_discard() into nvme_update_disk_info()
nvme: add preferred I/O size fields to struct nvme_id_ns_nvm
nvme: Allow reauth from sysfs
nvme: Expose the tls_configured sysfs for secure concat connections
nvmet-tcp: Don't free SQ on authentication success
nvmet-tcp: Don't error if TLS is enabed on a reset
...

+768 -1302
+13
Documentation/ABI/testing/sysfs-nvme
··· 1 + What: /sys/devices/virtual/nvme-fabrics/ctl/.../tls_configured_key 2 + Date: November 2025 3 + KernelVersion: 6.19 4 + Contact: Linux NVMe mailing list <linux-nvme@lists.infradead.org> 5 + Description: 6 + The file is avaliable when using a secure concatanation 7 + connection to a NVMe target. Reading the file will return 8 + the serial of the currently negotiated key. 9 + 10 + Writing 0 to the file will trigger a PSK reauthentication 11 + (REPLACETLSPSK) with the target. After a reauthentication 12 + the value returned by tls_configured_key will be the new 13 + serial.
-6
crypto/Kconfig
··· 141 141 select CRYPTO_ALGAPI 142 142 select CRYPTO_ACOMP2 143 143 144 - config CRYPTO_HKDF 145 - tristate 146 - select CRYPTO_SHA256 if CRYPTO_SELFTESTS 147 - select CRYPTO_SHA512 if CRYPTO_SELFTESTS 148 - select CRYPTO_HASH2 149 - 150 144 config CRYPTO_MANAGER 151 145 tristate 152 146 default CRYPTO_ALGAPI if CRYPTO_SELFTESTS
-1
crypto/Makefile
··· 36 36 obj-$(CONFIG_CRYPTO_AKCIPHER2) += akcipher.o 37 37 obj-$(CONFIG_CRYPTO_SIG2) += sig.o 38 38 obj-$(CONFIG_CRYPTO_KPP2) += kpp.o 39 - obj-$(CONFIG_CRYPTO_HKDF) += hkdf.o 40 39 41 40 dh_generic-y := dh.o 42 41 dh_generic-y += dh_helper.o
-573
crypto/hkdf.c
··· 1 - // SPDX-License-Identifier: GPL-2.0 2 - /* 3 - * Implementation of HKDF ("HMAC-based Extract-and-Expand Key Derivation 4 - * Function"), aka RFC 5869. See also the original paper (Krawczyk 2010): 5 - * "Cryptographic Extraction and Key Derivation: The HKDF Scheme". 6 - * 7 - * Copyright 2019 Google LLC 8 - */ 9 - 10 - #include <crypto/internal/hash.h> 11 - #include <crypto/sha2.h> 12 - #include <crypto/hkdf.h> 13 - #include <linux/module.h> 14 - 15 - /* 16 - * HKDF consists of two steps: 17 - * 18 - * 1. HKDF-Extract: extract a pseudorandom key from the input keying material 19 - * and optional salt. 20 - * 2. HKDF-Expand: expand the pseudorandom key into output keying material of 21 - * any length, parameterized by an application-specific info string. 22 - * 23 - */ 24 - 25 - /** 26 - * hkdf_extract - HKDF-Extract (RFC 5869 section 2.2) 27 - * @hmac_tfm: an HMAC transform using the hash function desired for HKDF. The 28 - * caller is responsible for setting the @prk afterwards. 29 - * @ikm: input keying material 30 - * @ikmlen: length of @ikm 31 - * @salt: input salt value 32 - * @saltlen: length of @salt 33 - * @prk: resulting pseudorandom key 34 - * 35 - * Extracts a pseudorandom key @prk from the input keying material 36 - * @ikm with length @ikmlen and salt @salt with length @saltlen. 37 - * The length of @prk is given by the digest size of @hmac_tfm. 38 - * For an 'unsalted' version of HKDF-Extract @salt must be set 39 - * to all zeroes and @saltlen must be set to the length of @prk. 40 - * 41 - * Returns 0 on success with the pseudorandom key stored in @prk, 42 - * or a negative errno value otherwise. 43 - */ 44 - int hkdf_extract(struct crypto_shash *hmac_tfm, const u8 *ikm, 45 - unsigned int ikmlen, const u8 *salt, unsigned int saltlen, 46 - u8 *prk) 47 - { 48 - int err; 49 - 50 - err = crypto_shash_setkey(hmac_tfm, salt, saltlen); 51 - if (!err) 52 - err = crypto_shash_tfm_digest(hmac_tfm, ikm, ikmlen, prk); 53 - 54 - return err; 55 - } 56 - EXPORT_SYMBOL_GPL(hkdf_extract); 57 - 58 - /** 59 - * hkdf_expand - HKDF-Expand (RFC 5869 section 2.3) 60 - * @hmac_tfm: hash context keyed with pseudorandom key 61 - * @info: application-specific information 62 - * @infolen: length of @info 63 - * @okm: output keying material 64 - * @okmlen: length of @okm 65 - * 66 - * This expands the pseudorandom key, which was already keyed into @hmac_tfm, 67 - * into @okmlen bytes of output keying material parameterized by the 68 - * application-specific @info of length @infolen bytes. 69 - * This is thread-safe and may be called by multiple threads in parallel. 70 - * 71 - * Returns 0 on success with output keying material stored in @okm, 72 - * or a negative errno value otherwise. 73 - */ 74 - int hkdf_expand(struct crypto_shash *hmac_tfm, 75 - const u8 *info, unsigned int infolen, 76 - u8 *okm, unsigned int okmlen) 77 - { 78 - SHASH_DESC_ON_STACK(desc, hmac_tfm); 79 - unsigned int i, hashlen = crypto_shash_digestsize(hmac_tfm); 80 - int err; 81 - const u8 *prev = NULL; 82 - u8 counter = 1; 83 - u8 tmp[HASH_MAX_DIGESTSIZE] = {}; 84 - 85 - if (WARN_ON(okmlen > 255 * hashlen)) 86 - return -EINVAL; 87 - 88 - desc->tfm = hmac_tfm; 89 - 90 - for (i = 0; i < okmlen; i += hashlen) { 91 - err = crypto_shash_init(desc); 92 - if (err) 93 - goto out; 94 - 95 - if (prev) { 96 - err = crypto_shash_update(desc, prev, hashlen); 97 - if (err) 98 - goto out; 99 - } 100 - 101 - if (infolen) { 102 - err = crypto_shash_update(desc, info, infolen); 103 - if (err) 104 - goto out; 105 - } 106 - 107 - BUILD_BUG_ON(sizeof(counter) != 1); 108 - if (okmlen - i < hashlen) { 109 - err = crypto_shash_finup(desc, &counter, 1, tmp); 110 - if (err) 111 - goto out; 112 - memcpy(&okm[i], tmp, okmlen - i); 113 - memzero_explicit(tmp, sizeof(tmp)); 114 - } else { 115 - err = crypto_shash_finup(desc, &counter, 1, &okm[i]); 116 - if (err) 117 - goto out; 118 - } 119 - counter++; 120 - prev = &okm[i]; 121 - } 122 - err = 0; 123 - out: 124 - if (unlikely(err)) 125 - memzero_explicit(okm, okmlen); /* so caller doesn't need to */ 126 - shash_desc_zero(desc); 127 - memzero_explicit(tmp, HASH_MAX_DIGESTSIZE); 128 - return err; 129 - } 130 - EXPORT_SYMBOL_GPL(hkdf_expand); 131 - 132 - struct hkdf_testvec { 133 - const char *test; 134 - const u8 *ikm; 135 - const u8 *salt; 136 - const u8 *info; 137 - const u8 *prk; 138 - const u8 *okm; 139 - u16 ikm_size; 140 - u16 salt_size; 141 - u16 info_size; 142 - u16 prk_size; 143 - u16 okm_size; 144 - }; 145 - 146 - /* 147 - * HKDF test vectors from RFC5869 148 - * 149 - * Additional HKDF test vectors from 150 - * https://github.com/brycx/Test-Vector-Generation/blob/master/HKDF/hkdf-hmac-sha2-test-vectors.md 151 - */ 152 - static const struct hkdf_testvec hkdf_sha256_tv[] = { 153 - { 154 - .test = "basic hdkf test", 155 - .ikm = "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" 156 - "\x0b\x0b\x0b\x0b\x0b\x0b", 157 - .ikm_size = 22, 158 - .salt = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c", 159 - .salt_size = 13, 160 - .info = "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9", 161 - .info_size = 10, 162 - .prk = "\x07\x77\x09\x36\x2c\x2e\x32\xdf\x0d\xdc\x3f\x0d\xc4\x7b\xba\x63" 163 - "\x90\xb6\xc7\x3b\xb5\x0f\x9c\x31\x22\xec\x84\x4a\xd7\xc2\xb3\xe5", 164 - .prk_size = 32, 165 - .okm = "\x3c\xb2\x5f\x25\xfa\xac\xd5\x7a\x90\x43\x4f\x64\xd0\x36\x2f\x2a" 166 - "\x2d\x2d\x0a\x90\xcf\x1a\x5a\x4c\x5d\xb0\x2d\x56\xec\xc4\xc5\xbf" 167 - "\x34\x00\x72\x08\xd5\xb8\x87\x18\x58\x65", 168 - .okm_size = 42, 169 - }, { 170 - .test = "hkdf test with long input", 171 - .ikm = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" 172 - "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" 173 - "\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f" 174 - "\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f" 175 - "\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f", 176 - .ikm_size = 80, 177 - .salt = "\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f" 178 - "\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f" 179 - "\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f" 180 - "\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f" 181 - "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf", 182 - .salt_size = 80, 183 - .info = "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf" 184 - "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf" 185 - "\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf" 186 - "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef" 187 - "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff", 188 - .info_size = 80, 189 - .prk = "\x06\xa6\xb8\x8c\x58\x53\x36\x1a\x06\x10\x4c\x9c\xeb\x35\xb4\x5c" 190 - "\xef\x76\x00\x14\x90\x46\x71\x01\x4a\x19\x3f\x40\xc1\x5f\xc2\x44", 191 - .prk_size = 32, 192 - .okm = "\xb1\x1e\x39\x8d\xc8\x03\x27\xa1\xc8\xe7\xf7\x8c\x59\x6a\x49\x34" 193 - "\x4f\x01\x2e\xda\x2d\x4e\xfa\xd8\xa0\x50\xcc\x4c\x19\xaf\xa9\x7c" 194 - "\x59\x04\x5a\x99\xca\xc7\x82\x72\x71\xcb\x41\xc6\x5e\x59\x0e\x09" 195 - "\xda\x32\x75\x60\x0c\x2f\x09\xb8\x36\x77\x93\xa9\xac\xa3\xdb\x71" 196 - "\xcc\x30\xc5\x81\x79\xec\x3e\x87\xc1\x4c\x01\xd5\xc1\xf3\x43\x4f" 197 - "\x1d\x87", 198 - .okm_size = 82, 199 - }, { 200 - .test = "hkdf test with zero salt and info", 201 - .ikm = "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" 202 - "\x0b\x0b\x0b\x0b\x0b\x0b", 203 - .ikm_size = 22, 204 - .salt = NULL, 205 - .salt_size = 0, 206 - .info = NULL, 207 - .info_size = 0, 208 - .prk = "\x19\xef\x24\xa3\x2c\x71\x7b\x16\x7f\x33\xa9\x1d\x6f\x64\x8b\xdf" 209 - "\x96\x59\x67\x76\xaf\xdb\x63\x77\xac\x43\x4c\x1c\x29\x3c\xcb\x04", 210 - .prk_size = 32, 211 - .okm = "\x8d\xa4\xe7\x75\xa5\x63\xc1\x8f\x71\x5f\x80\x2a\x06\x3c\x5a\x31" 212 - "\xb8\xa1\x1f\x5c\x5e\xe1\x87\x9e\xc3\x45\x4e\x5f\x3c\x73\x8d\x2d" 213 - "\x9d\x20\x13\x95\xfa\xa4\xb6\x1a\x96\xc8", 214 - .okm_size = 42, 215 - }, { 216 - .test = "hkdf test with short input", 217 - .ikm = "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b", 218 - .ikm_size = 11, 219 - .salt = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c", 220 - .salt_size = 13, 221 - .info = "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9", 222 - .info_size = 10, 223 - .prk = "\x82\x65\xf6\x9d\x7f\xf7\xe5\x01\x37\x93\x01\x5c\xa0\xef\x92\x0c" 224 - "\xb1\x68\x21\x99\xc8\xbc\x3a\x00\xda\x0c\xab\x47\xb7\xb0\x0f\xdf", 225 - .prk_size = 32, 226 - .okm = "\x58\xdc\xe1\x0d\x58\x01\xcd\xfd\xa8\x31\x72\x6b\xfe\xbc\xb7\x43" 227 - "\xd1\x4a\x7e\xe8\x3a\xa0\x57\xa9\x3d\x59\xb0\xa1\x31\x7f\xf0\x9d" 228 - "\x10\x5c\xce\xcf\x53\x56\x92\xb1\x4d\xd5", 229 - .okm_size = 42, 230 - }, { 231 - .test = "unsalted hkdf test with zero info", 232 - .ikm = "\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c" 233 - "\x0c\x0c\x0c\x0c\x0c\x0c", 234 - .ikm_size = 22, 235 - .salt = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" 236 - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 237 - .salt_size = 32, 238 - .info = NULL, 239 - .info_size = 0, 240 - .prk = "\xaa\x84\x1e\x1f\x35\x74\xf3\x2d\x13\xfb\xa8\x00\x5f\xcd\x9b\x8d" 241 - "\x77\x67\x82\xa5\xdf\xa1\x92\x38\x92\xfd\x8b\x63\x5d\x3a\x89\xdf", 242 - .prk_size = 32, 243 - .okm = "\x59\x68\x99\x17\x9a\xb1\xbc\x00\xa7\xc0\x37\x86\xff\x43\xee\x53" 244 - "\x50\x04\xbe\x2b\xb9\xbe\x68\xbc\x14\x06\x63\x6f\x54\xbd\x33\x8a" 245 - "\x66\xa2\x37\xba\x2a\xcb\xce\xe3\xc9\xa7", 246 - .okm_size = 42, 247 - } 248 - }; 249 - 250 - static const struct hkdf_testvec hkdf_sha384_tv[] = { 251 - { 252 - .test = "basic hkdf test", 253 - .ikm = "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" 254 - "\x0b\x0b\x0b\x0b\x0b\x0b", 255 - .ikm_size = 22, 256 - .salt = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c", 257 - .salt_size = 13, 258 - .info = "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9", 259 - .info_size = 10, 260 - .prk = "\x70\x4b\x39\x99\x07\x79\xce\x1d\xc5\x48\x05\x2c\x7d\xc3\x9f\x30" 261 - "\x35\x70\xdd\x13\xfb\x39\xf7\xac\xc5\x64\x68\x0b\xef\x80\xe8\xde" 262 - "\xc7\x0e\xe9\xa7\xe1\xf3\xe2\x93\xef\x68\xec\xeb\x07\x2a\x5a\xde", 263 - .prk_size = 48, 264 - .okm = "\x9b\x50\x97\xa8\x60\x38\xb8\x05\x30\x90\x76\xa4\x4b\x3a\x9f\x38" 265 - "\x06\x3e\x25\xb5\x16\xdc\xbf\x36\x9f\x39\x4c\xfa\xb4\x36\x85\xf7" 266 - "\x48\xb6\x45\x77\x63\xe4\xf0\x20\x4f\xc5", 267 - .okm_size = 42, 268 - }, { 269 - .test = "hkdf test with long input", 270 - .ikm = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" 271 - "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" 272 - "\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f" 273 - "\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f" 274 - "\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f", 275 - .ikm_size = 80, 276 - .salt = "\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f" 277 - "\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f" 278 - "\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f" 279 - "\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f" 280 - "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf", 281 - .salt_size = 80, 282 - .info = "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf" 283 - "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf" 284 - "\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf" 285 - "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef" 286 - "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff", 287 - .info_size = 80, 288 - .prk = "\xb3\x19\xf6\x83\x1d\xff\x93\x14\xef\xb6\x43\xba\xa2\x92\x63\xb3" 289 - "\x0e\x4a\x8d\x77\x9f\xe3\x1e\x9c\x90\x1e\xfd\x7d\xe7\x37\xc8\x5b" 290 - "\x62\xe6\x76\xd4\xdc\x87\xb0\x89\x5c\x6a\x7d\xc9\x7b\x52\xce\xbb", 291 - .prk_size = 48, 292 - .okm = "\x48\x4c\xa0\x52\xb8\xcc\x72\x4f\xd1\xc4\xec\x64\xd5\x7b\x4e\x81" 293 - "\x8c\x7e\x25\xa8\xe0\xf4\x56\x9e\xd7\x2a\x6a\x05\xfe\x06\x49\xee" 294 - "\xbf\x69\xf8\xd5\xc8\x32\x85\x6b\xf4\xe4\xfb\xc1\x79\x67\xd5\x49" 295 - "\x75\x32\x4a\x94\x98\x7f\x7f\x41\x83\x58\x17\xd8\x99\x4f\xdb\xd6" 296 - "\xf4\xc0\x9c\x55\x00\xdc\xa2\x4a\x56\x22\x2f\xea\x53\xd8\x96\x7a" 297 - "\x8b\x2e", 298 - .okm_size = 82, 299 - }, { 300 - .test = "hkdf test with zero salt and info", 301 - .ikm = "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" 302 - "\x0b\x0b\x0b\x0b\x0b\x0b", 303 - .ikm_size = 22, 304 - .salt = NULL, 305 - .salt_size = 0, 306 - .info = NULL, 307 - .info_size = 0, 308 - .prk = "\x10\xe4\x0c\xf0\x72\xa4\xc5\x62\x6e\x43\xdd\x22\xc1\xcf\x72\x7d" 309 - "\x4b\xb1\x40\x97\x5c\x9a\xd0\xcb\xc8\xe4\x5b\x40\x06\x8f\x8f\x0b" 310 - "\xa5\x7c\xdb\x59\x8a\xf9\xdf\xa6\x96\x3a\x96\x89\x9a\xf0\x47\xe5", 311 - .prk_size = 48, 312 - .okm = "\xc8\xc9\x6e\x71\x0f\x89\xb0\xd7\x99\x0b\xca\x68\xbc\xde\xc8\xcf" 313 - "\x85\x40\x62\xe5\x4c\x73\xa7\xab\xc7\x43\xfa\xde\x9b\x24\x2d\xaa" 314 - "\xcc\x1c\xea\x56\x70\x41\x5b\x52\x84\x9c", 315 - .okm_size = 42, 316 - }, { 317 - .test = "hkdf test with short input", 318 - .ikm = "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b", 319 - .ikm_size = 11, 320 - .salt = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c", 321 - .salt_size = 13, 322 - .info = "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9", 323 - .info_size = 10, 324 - .prk = "\x6d\x31\x69\x98\x28\x79\x80\x88\xb3\x59\xda\xd5\x0b\x8f\x01\xb0" 325 - "\x15\xf1\x7a\xa3\xbd\x4e\x27\xa6\xe9\xf8\x73\xb7\x15\x85\xca\x6a" 326 - "\x00\xd1\xf0\x82\x12\x8a\xdb\x3c\xf0\x53\x0b\x57\xc0\xf9\xac\x72", 327 - .prk_size = 48, 328 - .okm = "\xfb\x7e\x67\x43\xeb\x42\xcd\xe9\x6f\x1b\x70\x77\x89\x52\xab\x75" 329 - "\x48\xca\xfe\x53\x24\x9f\x7f\xfe\x14\x97\xa1\x63\x5b\x20\x1f\xf1" 330 - "\x85\xb9\x3e\x95\x19\x92\xd8\x58\xf1\x1a", 331 - .okm_size = 42, 332 - }, { 333 - .test = "unsalted hkdf test with zero info", 334 - .ikm = "\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c" 335 - "\x0c\x0c\x0c\x0c\x0c\x0c", 336 - .ikm_size = 22, 337 - .salt = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" 338 - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" 339 - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 340 - .salt_size = 48, 341 - .info = NULL, 342 - .info_size = 0, 343 - .prk = "\x9d\x2d\xa5\x06\x6f\x05\xd1\x6c\x59\xfe\xdf\x6c\x5f\x32\xc7\x5e" 344 - "\xda\x9a\x47\xa7\x9c\x93\x6a\xa4\x4c\xb7\x63\xa8\xe2\x2f\xfb\xfc" 345 - "\xd8\xfe\x55\x43\x58\x53\x47\x21\x90\x39\xd1\x68\x28\x36\x33\xf5", 346 - .prk_size = 48, 347 - .okm = "\x6a\xd7\xc7\x26\xc8\x40\x09\x54\x6a\x76\xe0\x54\x5d\xf2\x66\x78" 348 - "\x7e\x2b\x2c\xd6\xca\x43\x73\xa1\xf3\x14\x50\xa7\xbd\xf9\x48\x2b" 349 - "\xfa\xb8\x11\xf5\x54\x20\x0e\xad\x8f\x53", 350 - .okm_size = 42, 351 - } 352 - }; 353 - 354 - static const struct hkdf_testvec hkdf_sha512_tv[] = { 355 - { 356 - .test = "basic hkdf test", 357 - .ikm = "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" 358 - "\x0b\x0b\x0b\x0b\x0b\x0b", 359 - .ikm_size = 22, 360 - .salt = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c", 361 - .salt_size = 13, 362 - .info = "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9", 363 - .info_size = 10, 364 - .prk = "\x66\x57\x99\x82\x37\x37\xde\xd0\x4a\x88\xe4\x7e\x54\xa5\x89\x0b" 365 - "\xb2\xc3\xd2\x47\xc7\xa4\x25\x4a\x8e\x61\x35\x07\x23\x59\x0a\x26" 366 - "\xc3\x62\x38\x12\x7d\x86\x61\xb8\x8c\xf8\x0e\xf8\x02\xd5\x7e\x2f" 367 - "\x7c\xeb\xcf\x1e\x00\xe0\x83\x84\x8b\xe1\x99\x29\xc6\x1b\x42\x37", 368 - .prk_size = 64, 369 - .okm = "\x83\x23\x90\x08\x6c\xda\x71\xfb\x47\x62\x5b\xb5\xce\xb1\x68\xe4" 370 - "\xc8\xe2\x6a\x1a\x16\xed\x34\xd9\xfc\x7f\xe9\x2c\x14\x81\x57\x93" 371 - "\x38\xda\x36\x2c\xb8\xd9\xf9\x25\xd7\xcb", 372 - .okm_size = 42, 373 - }, { 374 - .test = "hkdf test with long input", 375 - .ikm = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" 376 - "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" 377 - "\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f" 378 - "\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f" 379 - "\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f", 380 - .ikm_size = 80, 381 - .salt = "\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f" 382 - "\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f" 383 - "\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f" 384 - "\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f" 385 - "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf", 386 - .salt_size = 80, 387 - .info = "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf" 388 - "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf" 389 - "\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf" 390 - "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef" 391 - "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff", 392 - .info_size = 80, 393 - .prk = "\x35\x67\x25\x42\x90\x7d\x4e\x14\x2c\x00\xe8\x44\x99\xe7\x4e\x1d" 394 - "\xe0\x8b\xe8\x65\x35\xf9\x24\xe0\x22\x80\x4a\xd7\x75\xdd\xe2\x7e" 395 - "\xc8\x6c\xd1\xe5\xb7\xd1\x78\xc7\x44\x89\xbd\xbe\xb3\x07\x12\xbe" 396 - "\xb8\x2d\x4f\x97\x41\x6c\x5a\x94\xea\x81\xeb\xdf\x3e\x62\x9e\x4a", 397 - .prk_size = 64, 398 - .okm = "\xce\x6c\x97\x19\x28\x05\xb3\x46\xe6\x16\x1e\x82\x1e\xd1\x65\x67" 399 - "\x3b\x84\xf4\x00\xa2\xb5\x14\xb2\xfe\x23\xd8\x4c\xd1\x89\xdd\xf1" 400 - "\xb6\x95\xb4\x8c\xbd\x1c\x83\x88\x44\x11\x37\xb3\xce\x28\xf1\x6a" 401 - "\xa6\x4b\xa3\x3b\xa4\x66\xb2\x4d\xf6\xcf\xcb\x02\x1e\xcf\xf2\x35" 402 - "\xf6\xa2\x05\x6c\xe3\xaf\x1d\xe4\x4d\x57\x20\x97\xa8\x50\x5d\x9e" 403 - "\x7a\x93", 404 - .okm_size = 82, 405 - }, { 406 - .test = "hkdf test with zero salt and info", 407 - .ikm = "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" 408 - "\x0b\x0b\x0b\x0b\x0b\x0b", 409 - .ikm_size = 22, 410 - .salt = NULL, 411 - .salt_size = 0, 412 - .info = NULL, 413 - .info_size = 0, 414 - .prk = "\xfd\x20\x0c\x49\x87\xac\x49\x13\x13\xbd\x4a\x2a\x13\x28\x71\x21" 415 - "\x24\x72\x39\xe1\x1c\x9e\xf8\x28\x02\x04\x4b\x66\xef\x35\x7e\x5b" 416 - "\x19\x44\x98\xd0\x68\x26\x11\x38\x23\x48\x57\x2a\x7b\x16\x11\xde" 417 - "\x54\x76\x40\x94\x28\x63\x20\x57\x8a\x86\x3f\x36\x56\x2b\x0d\xf6", 418 - .prk_size = 64, 419 - .okm = "\xf5\xfa\x02\xb1\x82\x98\xa7\x2a\x8c\x23\x89\x8a\x87\x03\x47\x2c" 420 - "\x6e\xb1\x79\xdc\x20\x4c\x03\x42\x5c\x97\x0e\x3b\x16\x4b\xf9\x0f" 421 - "\xff\x22\xd0\x48\x36\xd0\xe2\x34\x3b\xac", 422 - .okm_size = 42, 423 - }, { 424 - .test = "hkdf test with short input", 425 - .ikm = "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b", 426 - .ikm_size = 11, 427 - .salt = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c", 428 - .salt_size = 13, 429 - .info = "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9", 430 - .info_size = 10, 431 - .prk = "\x67\x40\x9c\x9c\xac\x28\xb5\x2e\xe9\xfa\xd9\x1c\x2f\xda\x99\x9f" 432 - "\x7c\xa2\x2e\x34\x34\xf0\xae\x77\x28\x63\x83\x65\x68\xad\x6a\x7f" 433 - "\x10\xcf\x11\x3b\xfd\xdd\x56\x01\x29\xa5\x94\xa8\xf5\x23\x85\xc2" 434 - "\xd6\x61\xd7\x85\xd2\x9c\xe9\x3a\x11\x40\x0c\x92\x06\x83\x18\x1d", 435 - .prk_size = 64, 436 - .okm = "\x74\x13\xe8\x99\x7e\x02\x06\x10\xfb\xf6\x82\x3f\x2c\xe1\x4b\xff" 437 - "\x01\x87\x5d\xb1\xca\x55\xf6\x8c\xfc\xf3\x95\x4d\xc8\xaf\xf5\x35" 438 - "\x59\xbd\x5e\x30\x28\xb0\x80\xf7\xc0\x68", 439 - .okm_size = 42, 440 - }, { 441 - .test = "unsalted hkdf test with zero info", 442 - .ikm = "\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c" 443 - "\x0c\x0c\x0c\x0c\x0c\x0c", 444 - .ikm_size = 22, 445 - .salt = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" 446 - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" 447 - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" 448 - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 449 - .salt_size = 64, 450 - .info = NULL, 451 - .info_size = 0, 452 - .prk = "\x53\x46\xb3\x76\xbf\x3a\xa9\xf8\x4f\x8f\x6e\xd5\xb1\xc4\xf4\x89" 453 - "\x17\x2e\x24\x4d\xac\x30\x3d\x12\xf6\x8e\xcc\x76\x6e\xa6\x00\xaa" 454 - "\x88\x49\x5e\x7f\xb6\x05\x80\x31\x22\xfa\x13\x69\x24\xa8\x40\xb1" 455 - "\xf0\x71\x9d\x2d\x5f\x68\xe2\x9b\x24\x22\x99\xd7\x58\xed\x68\x0c", 456 - .prk_size = 64, 457 - .okm = "\x14\x07\xd4\x60\x13\xd9\x8b\xc6\xde\xce\xfc\xfe\xe5\x5f\x0f\x90" 458 - "\xb0\xc7\xf6\x3d\x68\xeb\x1a\x80\xea\xf0\x7e\x95\x3c\xfc\x0a\x3a" 459 - "\x52\x40\xa1\x55\xd6\xe4\xda\xa9\x65\xbb", 460 - .okm_size = 42, 461 - } 462 - }; 463 - 464 - static int hkdf_test(const char *shash, const struct hkdf_testvec *tv) 465 - { struct crypto_shash *tfm = NULL; 466 - u8 *prk = NULL, *okm = NULL; 467 - unsigned int prk_size; 468 - const char *driver; 469 - int err; 470 - 471 - tfm = crypto_alloc_shash(shash, 0, 0); 472 - if (IS_ERR(tfm)) { 473 - pr_err("%s(%s): failed to allocate transform: %ld\n", 474 - tv->test, shash, PTR_ERR(tfm)); 475 - return PTR_ERR(tfm); 476 - } 477 - driver = crypto_shash_driver_name(tfm); 478 - 479 - prk_size = crypto_shash_digestsize(tfm); 480 - prk = kzalloc(prk_size, GFP_KERNEL); 481 - if (!prk) { 482 - err = -ENOMEM; 483 - goto out_free; 484 - } 485 - 486 - if (tv->prk_size != prk_size) { 487 - pr_err("%s(%s): prk size mismatch (vec %u, digest %u\n", 488 - tv->test, driver, tv->prk_size, prk_size); 489 - err = -EINVAL; 490 - goto out_free; 491 - } 492 - 493 - err = hkdf_extract(tfm, tv->ikm, tv->ikm_size, 494 - tv->salt, tv->salt_size, prk); 495 - if (err) { 496 - pr_err("%s(%s): hkdf_extract failed with %d\n", 497 - tv->test, driver, err); 498 - goto out_free; 499 - } 500 - 501 - if (memcmp(prk, tv->prk, tv->prk_size)) { 502 - pr_err("%s(%s): hkdf_extract prk mismatch\n", 503 - tv->test, driver); 504 - print_hex_dump(KERN_ERR, "prk: ", DUMP_PREFIX_NONE, 505 - 16, 1, prk, tv->prk_size, false); 506 - err = -EINVAL; 507 - goto out_free; 508 - } 509 - 510 - okm = kzalloc(tv->okm_size, GFP_KERNEL); 511 - if (!okm) { 512 - err = -ENOMEM; 513 - goto out_free; 514 - } 515 - 516 - err = crypto_shash_setkey(tfm, tv->prk, tv->prk_size); 517 - if (err) { 518 - pr_err("%s(%s): failed to set prk, error %d\n", 519 - tv->test, driver, err); 520 - goto out_free; 521 - } 522 - 523 - err = hkdf_expand(tfm, tv->info, tv->info_size, 524 - okm, tv->okm_size); 525 - if (err) { 526 - pr_err("%s(%s): hkdf_expand() failed with %d\n", 527 - tv->test, driver, err); 528 - } else if (memcmp(okm, tv->okm, tv->okm_size)) { 529 - pr_err("%s(%s): hkdf_expand() okm mismatch\n", 530 - tv->test, driver); 531 - print_hex_dump(KERN_ERR, "okm: ", DUMP_PREFIX_NONE, 532 - 16, 1, okm, tv->okm_size, false); 533 - err = -EINVAL; 534 - } 535 - out_free: 536 - kfree(okm); 537 - kfree(prk); 538 - crypto_free_shash(tfm); 539 - return err; 540 - } 541 - 542 - static int __init crypto_hkdf_module_init(void) 543 - { 544 - int ret = 0, i; 545 - 546 - if (!IS_ENABLED(CONFIG_CRYPTO_SELFTESTS)) 547 - return 0; 548 - 549 - for (i = 0; i < ARRAY_SIZE(hkdf_sha256_tv); i++) { 550 - ret = hkdf_test("hmac(sha256)", &hkdf_sha256_tv[i]); 551 - if (ret) 552 - return ret; 553 - } 554 - for (i = 0; i < ARRAY_SIZE(hkdf_sha384_tv); i++) { 555 - ret = hkdf_test("hmac(sha384)", &hkdf_sha384_tv[i]); 556 - if (ret) 557 - return ret; 558 - } 559 - for (i = 0; i < ARRAY_SIZE(hkdf_sha512_tv); i++) { 560 - ret = hkdf_test("hmac(sha512)", &hkdf_sha512_tv[i]); 561 - if (ret) 562 - return ret; 563 - } 564 - return 0; 565 - } 566 - 567 - static void __exit crypto_hkdf_module_exit(void) {} 568 - 569 - late_initcall(crypto_hkdf_module_init); 570 - module_exit(crypto_hkdf_module_exit); 571 - 572 - MODULE_LICENSE("GPL"); 573 - MODULE_DESCRIPTION("HMAC-based Key Derivation Function (HKDF)");
+6
drivers/nvme/common/.kunitconfig
··· 1 + CONFIG_KUNIT=y 2 + CONFIG_PCI=y 3 + CONFIG_BLOCK=y 4 + CONFIG_BLK_DEV_NVME=y 5 + CONFIG_NVME_HOST_AUTH=y 6 + CONFIG_NVME_AUTH_KUNIT_TEST=y
+10 -4
drivers/nvme/common/Kconfig
··· 7 7 config NVME_AUTH 8 8 tristate 9 9 select CRYPTO 10 - select CRYPTO_HMAC 11 - select CRYPTO_SHA256 12 - select CRYPTO_SHA512 13 10 select CRYPTO_DH 14 11 select CRYPTO_DH_RFC7919_GROUPS 15 - select CRYPTO_HKDF 12 + select CRYPTO_LIB_SHA256 13 + select CRYPTO_LIB_SHA512 14 + 15 + config NVME_AUTH_KUNIT_TEST 16 + tristate "KUnit tests for NVMe authentication" if !KUNIT_ALL_TESTS 17 + depends on KUNIT && NVME_AUTH 18 + default KUNIT_ALL_TESTS 19 + help 20 + Enable KUnit tests for some of the common code for NVMe over Fabrics 21 + In-Band Authentication.
+2
drivers/nvme/common/Makefile
··· 7 7 8 8 nvme-auth-y += auth.o 9 9 nvme-keyring-y += keyring.o 10 + 11 + obj-$(CONFIG_NVME_AUTH_KUNIT_TEST) += tests/auth_kunit.o
+236 -355
drivers/nvme/common/auth.c
··· 9 9 #include <linux/prandom.h> 10 10 #include <linux/scatterlist.h> 11 11 #include <linux/unaligned.h> 12 - #include <crypto/hash.h> 13 12 #include <crypto/dh.h> 14 - #include <crypto/hkdf.h> 13 + #include <crypto/sha2.h> 15 14 #include <linux/nvme.h> 16 15 #include <linux/nvme-auth.h> 17 - 18 - #define HKDF_MAX_HASHLEN 64 19 16 20 17 static u32 nvme_dhchap_seqnum; 21 18 static DEFINE_MUTEX(nvme_dhchap_mutex); ··· 35 38 } 36 39 EXPORT_SYMBOL_GPL(nvme_auth_get_seqnum); 37 40 38 - static struct nvme_auth_dhgroup_map { 39 - const char name[16]; 40 - const char kpp[16]; 41 + static const struct nvme_auth_dhgroup_map { 42 + char name[16]; 43 + char kpp[16]; 41 44 } dhgroup_map[] = { 42 45 [NVME_AUTH_DHGROUP_NULL] = { 43 46 .name = "null", .kpp = "null" }, ··· 86 89 } 87 90 EXPORT_SYMBOL_GPL(nvme_auth_dhgroup_id); 88 91 89 - static struct nvme_dhchap_hash_map { 92 + static const struct nvme_dhchap_hash_map { 90 93 int len; 91 - const char hmac[15]; 92 - const char digest[8]; 94 + char hmac[15]; 93 95 } hash_map[] = { 94 96 [NVME_AUTH_HASH_SHA256] = { 95 97 .len = 32, 96 98 .hmac = "hmac(sha256)", 97 - .digest = "sha256", 98 99 }, 99 100 [NVME_AUTH_HASH_SHA384] = { 100 101 .len = 48, 101 102 .hmac = "hmac(sha384)", 102 - .digest = "sha384", 103 103 }, 104 104 [NVME_AUTH_HASH_SHA512] = { 105 105 .len = 64, 106 106 .hmac = "hmac(sha512)", 107 - .digest = "sha512", 108 107 }, 109 108 }; 110 109 ··· 111 118 return hash_map[hmac_id].hmac; 112 119 } 113 120 EXPORT_SYMBOL_GPL(nvme_auth_hmac_name); 114 - 115 - const char *nvme_auth_digest_name(u8 hmac_id) 116 - { 117 - if (hmac_id >= ARRAY_SIZE(hash_map)) 118 - return NULL; 119 - return hash_map[hmac_id].digest; 120 - } 121 - EXPORT_SYMBOL_GPL(nvme_auth_digest_name); 122 121 123 122 u8 nvme_auth_hmac_id(const char *hmac_name) 124 123 { ··· 146 161 } 147 162 EXPORT_SYMBOL_GPL(nvme_auth_key_struct_size); 148 163 149 - struct nvme_dhchap_key *nvme_auth_extract_key(unsigned char *secret, 150 - u8 key_hash) 164 + struct nvme_dhchap_key *nvme_auth_extract_key(const char *secret, u8 key_hash) 151 165 { 152 166 struct nvme_dhchap_key *key; 153 - unsigned char *p; 167 + const char *p; 154 168 u32 crc; 155 169 int ret, key_len; 156 170 size_t allocated_len = strlen(secret); ··· 167 183 pr_debug("base64 key decoding error %d\n", 168 184 key_len); 169 185 ret = key_len; 170 - goto out_free_secret; 186 + goto out_free_key; 171 187 } 172 188 173 189 if (key_len != 36 && key_len != 52 && 174 190 key_len != 68) { 175 191 pr_err("Invalid key len %d\n", key_len); 176 192 ret = -EINVAL; 177 - goto out_free_secret; 193 + goto out_free_key; 178 194 } 179 195 180 196 /* The last four bytes is the CRC in little-endian format */ ··· 189 205 pr_err("key crc mismatch (key %08x, crc %08x)\n", 190 206 get_unaligned_le32(key->key + key_len), crc); 191 207 ret = -EKEYREJECTED; 192 - goto out_free_secret; 208 + goto out_free_key; 193 209 } 194 210 key->len = key_len; 195 211 key->hash = key_hash; 196 212 return key; 197 - out_free_secret: 213 + out_free_key: 198 214 nvme_auth_free_key(key); 199 215 return ERR_PTR(ret); 200 216 } ··· 221 237 } 222 238 EXPORT_SYMBOL_GPL(nvme_auth_free_key); 223 239 224 - struct nvme_dhchap_key *nvme_auth_transform_key( 225 - struct nvme_dhchap_key *key, char *nqn) 240 + /* 241 + * Start computing an HMAC value, given the algorithm ID and raw key. 242 + * 243 + * The context should be zeroized at the end of its lifetime. The caller can do 244 + * that implicitly by calling nvme_auth_hmac_final(), or explicitly (needed when 245 + * a context is abandoned without finalizing it) by calling memzero_explicit(). 246 + */ 247 + int nvme_auth_hmac_init(struct nvme_auth_hmac_ctx *hmac, u8 hmac_id, 248 + const u8 *key, size_t key_len) 226 249 { 227 - const char *hmac_name; 228 - struct crypto_shash *key_tfm; 229 - SHASH_DESC_ON_STACK(shash, key_tfm); 250 + hmac->hmac_id = hmac_id; 251 + switch (hmac_id) { 252 + case NVME_AUTH_HASH_SHA256: 253 + hmac_sha256_init_usingrawkey(&hmac->sha256, key, key_len); 254 + return 0; 255 + case NVME_AUTH_HASH_SHA384: 256 + hmac_sha384_init_usingrawkey(&hmac->sha384, key, key_len); 257 + return 0; 258 + case NVME_AUTH_HASH_SHA512: 259 + hmac_sha512_init_usingrawkey(&hmac->sha512, key, key_len); 260 + return 0; 261 + } 262 + pr_warn("%s: invalid hash algorithm %d\n", __func__, hmac_id); 263 + return -EINVAL; 264 + } 265 + EXPORT_SYMBOL_GPL(nvme_auth_hmac_init); 266 + 267 + void nvme_auth_hmac_update(struct nvme_auth_hmac_ctx *hmac, const u8 *data, 268 + size_t data_len) 269 + { 270 + switch (hmac->hmac_id) { 271 + case NVME_AUTH_HASH_SHA256: 272 + hmac_sha256_update(&hmac->sha256, data, data_len); 273 + return; 274 + case NVME_AUTH_HASH_SHA384: 275 + hmac_sha384_update(&hmac->sha384, data, data_len); 276 + return; 277 + case NVME_AUTH_HASH_SHA512: 278 + hmac_sha512_update(&hmac->sha512, data, data_len); 279 + return; 280 + } 281 + /* Unreachable because nvme_auth_hmac_init() validated hmac_id */ 282 + WARN_ON_ONCE(1); 283 + } 284 + EXPORT_SYMBOL_GPL(nvme_auth_hmac_update); 285 + 286 + /* Finish computing an HMAC value. Note that this zeroizes the HMAC context. */ 287 + void nvme_auth_hmac_final(struct nvme_auth_hmac_ctx *hmac, u8 *out) 288 + { 289 + switch (hmac->hmac_id) { 290 + case NVME_AUTH_HASH_SHA256: 291 + hmac_sha256_final(&hmac->sha256, out); 292 + return; 293 + case NVME_AUTH_HASH_SHA384: 294 + hmac_sha384_final(&hmac->sha384, out); 295 + return; 296 + case NVME_AUTH_HASH_SHA512: 297 + hmac_sha512_final(&hmac->sha512, out); 298 + return; 299 + } 300 + /* Unreachable because nvme_auth_hmac_init() validated hmac_id */ 301 + WARN_ON_ONCE(1); 302 + } 303 + EXPORT_SYMBOL_GPL(nvme_auth_hmac_final); 304 + 305 + static int nvme_auth_hmac(u8 hmac_id, const u8 *key, size_t key_len, 306 + const u8 *data, size_t data_len, u8 *out) 307 + { 308 + struct nvme_auth_hmac_ctx hmac; 309 + int ret; 310 + 311 + ret = nvme_auth_hmac_init(&hmac, hmac_id, key, key_len); 312 + if (ret == 0) { 313 + nvme_auth_hmac_update(&hmac, data, data_len); 314 + nvme_auth_hmac_final(&hmac, out); 315 + } 316 + return ret; 317 + } 318 + 319 + static int nvme_auth_hash(u8 hmac_id, const u8 *data, size_t data_len, u8 *out) 320 + { 321 + switch (hmac_id) { 322 + case NVME_AUTH_HASH_SHA256: 323 + sha256(data, data_len, out); 324 + return 0; 325 + case NVME_AUTH_HASH_SHA384: 326 + sha384(data, data_len, out); 327 + return 0; 328 + case NVME_AUTH_HASH_SHA512: 329 + sha512(data, data_len, out); 330 + return 0; 331 + } 332 + pr_warn("%s: invalid hash algorithm %d\n", __func__, hmac_id); 333 + return -EINVAL; 334 + } 335 + 336 + struct nvme_dhchap_key *nvme_auth_transform_key( 337 + const struct nvme_dhchap_key *key, const char *nqn) 338 + { 339 + struct nvme_auth_hmac_ctx hmac; 230 340 struct nvme_dhchap_key *transformed_key; 231 341 int ret, key_len; 232 342 ··· 335 257 return ERR_PTR(-ENOMEM); 336 258 return transformed_key; 337 259 } 338 - hmac_name = nvme_auth_hmac_name(key->hash); 339 - if (!hmac_name) { 340 - pr_warn("Invalid key hash id %d\n", key->hash); 341 - return ERR_PTR(-EINVAL); 342 - } 343 - 344 - key_tfm = crypto_alloc_shash(hmac_name, 0, 0); 345 - if (IS_ERR(key_tfm)) 346 - return ERR_CAST(key_tfm); 347 - 348 - key_len = crypto_shash_digestsize(key_tfm); 260 + ret = nvme_auth_hmac_init(&hmac, key->hash, key->key, key->len); 261 + if (ret) 262 + return ERR_PTR(ret); 263 + key_len = nvme_auth_hmac_hash_len(key->hash); 349 264 transformed_key = nvme_auth_alloc_key(key_len, key->hash); 350 265 if (!transformed_key) { 351 - ret = -ENOMEM; 352 - goto out_free_key; 266 + memzero_explicit(&hmac, sizeof(hmac)); 267 + return ERR_PTR(-ENOMEM); 353 268 } 354 - 355 - shash->tfm = key_tfm; 356 - ret = crypto_shash_setkey(key_tfm, key->key, key->len); 357 - if (ret < 0) 358 - goto out_free_transformed_key; 359 - ret = crypto_shash_init(shash); 360 - if (ret < 0) 361 - goto out_free_transformed_key; 362 - ret = crypto_shash_update(shash, nqn, strlen(nqn)); 363 - if (ret < 0) 364 - goto out_free_transformed_key; 365 - ret = crypto_shash_update(shash, "NVMe-over-Fabrics", 17); 366 - if (ret < 0) 367 - goto out_free_transformed_key; 368 - ret = crypto_shash_final(shash, transformed_key->key); 369 - if (ret < 0) 370 - goto out_free_transformed_key; 371 - 372 - crypto_free_shash(key_tfm); 373 - 269 + nvme_auth_hmac_update(&hmac, nqn, strlen(nqn)); 270 + nvme_auth_hmac_update(&hmac, "NVMe-over-Fabrics", 17); 271 + nvme_auth_hmac_final(&hmac, transformed_key->key); 374 272 return transformed_key; 375 - 376 - out_free_transformed_key: 377 - nvme_auth_free_key(transformed_key); 378 - out_free_key: 379 - crypto_free_shash(key_tfm); 380 - 381 - return ERR_PTR(ret); 382 273 } 383 274 EXPORT_SYMBOL_GPL(nvme_auth_transform_key); 384 275 385 - static int nvme_auth_hash_skey(int hmac_id, u8 *skey, size_t skey_len, u8 *hkey) 276 + int nvme_auth_augmented_challenge(u8 hmac_id, const u8 *skey, size_t skey_len, 277 + const u8 *challenge, u8 *aug, size_t hlen) 386 278 { 387 - const char *digest_name; 388 - struct crypto_shash *tfm; 279 + u8 hashed_key[NVME_AUTH_MAX_DIGEST_SIZE]; 389 280 int ret; 390 281 391 - digest_name = nvme_auth_digest_name(hmac_id); 392 - if (!digest_name) { 393 - pr_debug("%s: failed to get digest for %d\n", __func__, 394 - hmac_id); 395 - return -EINVAL; 396 - } 397 - tfm = crypto_alloc_shash(digest_name, 0, 0); 398 - if (IS_ERR(tfm)) 399 - return -ENOMEM; 400 - 401 - ret = crypto_shash_tfm_digest(tfm, skey, skey_len, hkey); 402 - if (ret < 0) 403 - pr_debug("%s: Failed to hash digest len %zu\n", __func__, 404 - skey_len); 405 - 406 - crypto_free_shash(tfm); 407 - return ret; 408 - } 409 - 410 - int nvme_auth_augmented_challenge(u8 hmac_id, u8 *skey, size_t skey_len, 411 - u8 *challenge, u8 *aug, size_t hlen) 412 - { 413 - struct crypto_shash *tfm; 414 - u8 *hashed_key; 415 - const char *hmac_name; 416 - int ret; 417 - 418 - hashed_key = kmalloc(hlen, GFP_KERNEL); 419 - if (!hashed_key) 420 - return -ENOMEM; 421 - 422 - ret = nvme_auth_hash_skey(hmac_id, skey, 423 - skey_len, hashed_key); 424 - if (ret < 0) 425 - goto out_free_key; 426 - 427 - hmac_name = nvme_auth_hmac_name(hmac_id); 428 - if (!hmac_name) { 429 - pr_warn("%s: invalid hash algorithm %d\n", 430 - __func__, hmac_id); 431 - ret = -EINVAL; 432 - goto out_free_key; 433 - } 434 - 435 - tfm = crypto_alloc_shash(hmac_name, 0, 0); 436 - if (IS_ERR(tfm)) { 437 - ret = PTR_ERR(tfm); 438 - goto out_free_key; 439 - } 440 - 441 - ret = crypto_shash_setkey(tfm, hashed_key, hlen); 282 + ret = nvme_auth_hash(hmac_id, skey, skey_len, hashed_key); 442 283 if (ret) 443 - goto out_free_hash; 444 - 445 - ret = crypto_shash_tfm_digest(tfm, challenge, hlen, aug); 446 - out_free_hash: 447 - crypto_free_shash(tfm); 448 - out_free_key: 449 - kfree_sensitive(hashed_key); 284 + return ret; 285 + ret = nvme_auth_hmac(hmac_id, hashed_key, hlen, challenge, hlen, aug); 286 + memzero_explicit(hashed_key, sizeof(hashed_key)); 450 287 return ret; 451 288 } 452 289 EXPORT_SYMBOL_GPL(nvme_auth_augmented_challenge); ··· 404 411 EXPORT_SYMBOL_GPL(nvme_auth_gen_pubkey); 405 412 406 413 int nvme_auth_gen_shared_secret(struct crypto_kpp *dh_tfm, 407 - u8 *ctrl_key, size_t ctrl_key_len, 414 + const u8 *ctrl_key, size_t ctrl_key_len, 408 415 u8 *sess_key, size_t sess_key_len) 409 416 { 410 417 struct kpp_request *req; ··· 431 438 } 432 439 EXPORT_SYMBOL_GPL(nvme_auth_gen_shared_secret); 433 440 434 - int nvme_auth_generate_key(u8 *secret, struct nvme_dhchap_key **ret_key) 441 + int nvme_auth_parse_key(const char *secret, struct nvme_dhchap_key **ret_key) 435 442 { 436 443 struct nvme_dhchap_key *key; 437 444 u8 key_hash; ··· 454 461 *ret_key = key; 455 462 return 0; 456 463 } 457 - EXPORT_SYMBOL_GPL(nvme_auth_generate_key); 464 + EXPORT_SYMBOL_GPL(nvme_auth_parse_key); 458 465 459 466 /** 460 467 * nvme_auth_generate_psk - Generate a PSK for TLS ··· 479 486 * Returns 0 on success with a valid generated PSK pointer in @ret_psk and 480 487 * the length of @ret_psk in @ret_len, or a negative error number otherwise. 481 488 */ 482 - int nvme_auth_generate_psk(u8 hmac_id, u8 *skey, size_t skey_len, 483 - u8 *c1, u8 *c2, size_t hash_len, u8 **ret_psk, size_t *ret_len) 489 + int nvme_auth_generate_psk(u8 hmac_id, const u8 *skey, size_t skey_len, 490 + const u8 *c1, const u8 *c2, size_t hash_len, 491 + u8 **ret_psk, size_t *ret_len) 484 492 { 485 - struct crypto_shash *tfm; 486 - SHASH_DESC_ON_STACK(shash, tfm); 493 + size_t psk_len = nvme_auth_hmac_hash_len(hmac_id); 494 + struct nvme_auth_hmac_ctx hmac; 487 495 u8 *psk; 488 - const char *hmac_name; 489 - int ret, psk_len; 496 + int ret; 490 497 491 498 if (!c1 || !c2) 492 499 return -EINVAL; 493 500 494 - hmac_name = nvme_auth_hmac_name(hmac_id); 495 - if (!hmac_name) { 496 - pr_warn("%s: invalid hash algorithm %d\n", 497 - __func__, hmac_id); 498 - return -EINVAL; 499 - } 500 - 501 - tfm = crypto_alloc_shash(hmac_name, 0, 0); 502 - if (IS_ERR(tfm)) 503 - return PTR_ERR(tfm); 504 - 505 - psk_len = crypto_shash_digestsize(tfm); 501 + ret = nvme_auth_hmac_init(&hmac, hmac_id, skey, skey_len); 502 + if (ret) 503 + return ret; 506 504 psk = kzalloc(psk_len, GFP_KERNEL); 507 505 if (!psk) { 508 - ret = -ENOMEM; 509 - goto out_free_tfm; 506 + memzero_explicit(&hmac, sizeof(hmac)); 507 + return -ENOMEM; 510 508 } 511 - 512 - shash->tfm = tfm; 513 - ret = crypto_shash_setkey(tfm, skey, skey_len); 514 - if (ret) 515 - goto out_free_psk; 516 - 517 - ret = crypto_shash_init(shash); 518 - if (ret) 519 - goto out_free_psk; 520 - 521 - ret = crypto_shash_update(shash, c1, hash_len); 522 - if (ret) 523 - goto out_free_psk; 524 - 525 - ret = crypto_shash_update(shash, c2, hash_len); 526 - if (ret) 527 - goto out_free_psk; 528 - 529 - ret = crypto_shash_final(shash, psk); 530 - if (!ret) { 531 - *ret_psk = psk; 532 - *ret_len = psk_len; 533 - } 534 - 535 - out_free_psk: 536 - if (ret) 537 - kfree_sensitive(psk); 538 - out_free_tfm: 539 - crypto_free_shash(tfm); 540 - 541 - return ret; 509 + nvme_auth_hmac_update(&hmac, c1, hash_len); 510 + nvme_auth_hmac_update(&hmac, c2, hash_len); 511 + nvme_auth_hmac_final(&hmac, psk); 512 + *ret_psk = psk; 513 + *ret_len = psk_len; 514 + return 0; 542 515 } 543 516 EXPORT_SYMBOL_GPL(nvme_auth_generate_psk); 544 517 ··· 543 584 * Returns 0 on success with a valid digest pointer in @ret_digest, or a 544 585 * negative error number on failure. 545 586 */ 546 - int nvme_auth_generate_digest(u8 hmac_id, u8 *psk, size_t psk_len, 547 - char *subsysnqn, char *hostnqn, u8 **ret_digest) 587 + int nvme_auth_generate_digest(u8 hmac_id, const u8 *psk, size_t psk_len, 588 + const char *subsysnqn, const char *hostnqn, 589 + char **ret_digest) 548 590 { 549 - struct crypto_shash *tfm; 550 - SHASH_DESC_ON_STACK(shash, tfm); 551 - u8 *digest, *enc; 552 - const char *hmac_name; 553 - size_t digest_len, hmac_len; 591 + struct nvme_auth_hmac_ctx hmac; 592 + u8 digest[NVME_AUTH_MAX_DIGEST_SIZE]; 593 + size_t hash_len = nvme_auth_hmac_hash_len(hmac_id); 594 + char *enc; 595 + size_t enc_len; 554 596 int ret; 555 597 556 598 if (WARN_ON(!subsysnqn || !hostnqn)) 557 599 return -EINVAL; 558 600 559 - hmac_name = nvme_auth_hmac_name(hmac_id); 560 - if (!hmac_name) { 601 + if (hash_len == 0) { 561 602 pr_warn("%s: invalid hash algorithm %d\n", 562 603 __func__, hmac_id); 563 604 return -EINVAL; 564 605 } 565 606 566 - switch (nvme_auth_hmac_hash_len(hmac_id)) { 607 + switch (hash_len) { 567 608 case 32: 568 - hmac_len = 44; 609 + enc_len = 44; 569 610 break; 570 611 case 48: 571 - hmac_len = 64; 612 + enc_len = 64; 572 613 break; 573 614 default: 574 615 pr_warn("%s: invalid hash algorithm '%s'\n", 575 - __func__, hmac_name); 616 + __func__, nvme_auth_hmac_name(hmac_id)); 576 617 return -EINVAL; 577 618 } 578 619 579 - enc = kzalloc(hmac_len + 1, GFP_KERNEL); 580 - if (!enc) 581 - return -ENOMEM; 582 - 583 - tfm = crypto_alloc_shash(hmac_name, 0, 0); 584 - if (IS_ERR(tfm)) { 585 - ret = PTR_ERR(tfm); 586 - goto out_free_enc; 587 - } 588 - 589 - digest_len = crypto_shash_digestsize(tfm); 590 - digest = kzalloc(digest_len, GFP_KERNEL); 591 - if (!digest) { 620 + enc = kzalloc(enc_len + 1, GFP_KERNEL); 621 + if (!enc) { 592 622 ret = -ENOMEM; 593 - goto out_free_tfm; 623 + goto out; 594 624 } 595 625 596 - shash->tfm = tfm; 597 - ret = crypto_shash_setkey(tfm, psk, psk_len); 626 + ret = nvme_auth_hmac_init(&hmac, hmac_id, psk, psk_len); 598 627 if (ret) 599 - goto out_free_digest; 628 + goto out; 629 + nvme_auth_hmac_update(&hmac, hostnqn, strlen(hostnqn)); 630 + nvme_auth_hmac_update(&hmac, " ", 1); 631 + nvme_auth_hmac_update(&hmac, subsysnqn, strlen(subsysnqn)); 632 + nvme_auth_hmac_update(&hmac, " NVMe-over-Fabrics", 18); 633 + nvme_auth_hmac_final(&hmac, digest); 600 634 601 - ret = crypto_shash_init(shash); 602 - if (ret) 603 - goto out_free_digest; 604 - 605 - ret = crypto_shash_update(shash, hostnqn, strlen(hostnqn)); 606 - if (ret) 607 - goto out_free_digest; 608 - 609 - ret = crypto_shash_update(shash, " ", 1); 610 - if (ret) 611 - goto out_free_digest; 612 - 613 - ret = crypto_shash_update(shash, subsysnqn, strlen(subsysnqn)); 614 - if (ret) 615 - goto out_free_digest; 616 - 617 - ret = crypto_shash_update(shash, " NVMe-over-Fabrics", 18); 618 - if (ret) 619 - goto out_free_digest; 620 - 621 - ret = crypto_shash_final(shash, digest); 622 - if (ret) 623 - goto out_free_digest; 624 - 625 - ret = base64_encode(digest, digest_len, enc, true, BASE64_STD); 626 - if (ret < hmac_len) { 635 + ret = base64_encode(digest, hash_len, enc, true, BASE64_STD); 636 + if (ret < enc_len) { 627 637 ret = -ENOKEY; 628 - goto out_free_digest; 638 + goto out; 629 639 } 630 640 *ret_digest = enc; 631 641 ret = 0; 632 642 633 - out_free_digest: 634 - kfree_sensitive(digest); 635 - out_free_tfm: 636 - crypto_free_shash(tfm); 637 - out_free_enc: 643 + out: 638 644 if (ret) 639 645 kfree_sensitive(enc); 640 - 646 + memzero_explicit(digest, sizeof(digest)); 641 647 return ret; 642 648 } 643 649 EXPORT_SYMBOL_GPL(nvme_auth_generate_digest); 644 - 645 - /** 646 - * hkdf_expand_label - HKDF-Expand-Label (RFC 8846 section 7.1) 647 - * @hmac_tfm: hash context keyed with pseudorandom key 648 - * @label: ASCII label without "tls13 " prefix 649 - * @labellen: length of @label 650 - * @context: context bytes 651 - * @contextlen: length of @context 652 - * @okm: output keying material 653 - * @okmlen: length of @okm 654 - * 655 - * Build the TLS 1.3 HkdfLabel structure and invoke hkdf_expand(). 656 - * 657 - * Returns 0 on success with output keying material stored in @okm, 658 - * or a negative errno value otherwise. 659 - */ 660 - static int hkdf_expand_label(struct crypto_shash *hmac_tfm, 661 - const u8 *label, unsigned int labellen, 662 - const u8 *context, unsigned int contextlen, 663 - u8 *okm, unsigned int okmlen) 664 - { 665 - int err; 666 - u8 *info; 667 - unsigned int infolen; 668 - const char *tls13_prefix = "tls13 "; 669 - unsigned int prefixlen = strlen(tls13_prefix); 670 - 671 - if (WARN_ON(labellen > (255 - prefixlen))) 672 - return -EINVAL; 673 - if (WARN_ON(contextlen > 255)) 674 - return -EINVAL; 675 - 676 - infolen = 2 + (1 + prefixlen + labellen) + (1 + contextlen); 677 - info = kzalloc(infolen, GFP_KERNEL); 678 - if (!info) 679 - return -ENOMEM; 680 - 681 - /* HkdfLabel.Length */ 682 - put_unaligned_be16(okmlen, info); 683 - 684 - /* HkdfLabel.Label */ 685 - info[2] = prefixlen + labellen; 686 - memcpy(info + 3, tls13_prefix, prefixlen); 687 - memcpy(info + 3 + prefixlen, label, labellen); 688 - 689 - /* HkdfLabel.Context */ 690 - info[3 + prefixlen + labellen] = contextlen; 691 - memcpy(info + 4 + prefixlen + labellen, context, contextlen); 692 - 693 - err = hkdf_expand(hmac_tfm, info, infolen, okm, okmlen); 694 - kfree_sensitive(info); 695 - return err; 696 - } 697 650 698 651 /** 699 652 * nvme_auth_derive_tls_psk - Derive TLS PSK ··· 634 763 * Returns 0 on success with a valid psk pointer in @ret_psk or a negative 635 764 * error number otherwise. 636 765 */ 637 - int nvme_auth_derive_tls_psk(int hmac_id, u8 *psk, size_t psk_len, 638 - u8 *psk_digest, u8 **ret_psk) 766 + int nvme_auth_derive_tls_psk(int hmac_id, const u8 *psk, size_t psk_len, 767 + const char *psk_digest, u8 **ret_psk) 639 768 { 640 - struct crypto_shash *hmac_tfm; 641 - const char *hmac_name; 642 - const char *label = "nvme-tls-psk"; 643 - static const char default_salt[HKDF_MAX_HASHLEN]; 644 - size_t prk_len; 645 - const char *ctx; 646 - unsigned char *prk, *tls_key; 769 + static const u8 default_salt[NVME_AUTH_MAX_DIGEST_SIZE]; 770 + static const char label[] = "tls13 nvme-tls-psk"; 771 + const size_t label_len = sizeof(label) - 1; 772 + u8 prk[NVME_AUTH_MAX_DIGEST_SIZE]; 773 + size_t hash_len, ctx_len; 774 + u8 *hmac_data = NULL, *tls_key; 775 + size_t i; 647 776 int ret; 648 777 649 - hmac_name = nvme_auth_hmac_name(hmac_id); 650 - if (!hmac_name) { 778 + hash_len = nvme_auth_hmac_hash_len(hmac_id); 779 + if (hash_len == 0) { 651 780 pr_warn("%s: invalid hash algorithm %d\n", 652 781 __func__, hmac_id); 653 782 return -EINVAL; 654 783 } 655 784 if (hmac_id == NVME_AUTH_HASH_SHA512) { 656 785 pr_warn("%s: unsupported hash algorithm %s\n", 657 - __func__, hmac_name); 786 + __func__, nvme_auth_hmac_name(hmac_id)); 658 787 return -EINVAL; 659 788 } 660 789 661 - hmac_tfm = crypto_alloc_shash(hmac_name, 0, 0); 662 - if (IS_ERR(hmac_tfm)) 663 - return PTR_ERR(hmac_tfm); 664 - 665 - prk_len = crypto_shash_digestsize(hmac_tfm); 666 - prk = kzalloc(prk_len, GFP_KERNEL); 667 - if (!prk) { 668 - ret = -ENOMEM; 669 - goto out_free_shash; 790 + if (psk_len != hash_len) { 791 + pr_warn("%s: unexpected psk_len %zu\n", __func__, psk_len); 792 + return -EINVAL; 670 793 } 671 794 672 - if (WARN_ON(prk_len > HKDF_MAX_HASHLEN)) { 795 + /* HKDF-Extract */ 796 + ret = nvme_auth_hmac(hmac_id, default_salt, hash_len, psk, psk_len, 797 + prk); 798 + if (ret) 799 + goto out; 800 + 801 + /* 802 + * HKDF-Expand-Label (RFC 8446 section 7.1), with output length equal to 803 + * the hash length (so only a single HMAC operation is needed) 804 + */ 805 + 806 + hmac_data = kmalloc(/* output length */ 2 + 807 + /* label */ 1 + label_len + 808 + /* context (max) */ 1 + 3 + 1 + strlen(psk_digest) + 809 + /* counter */ 1, 810 + GFP_KERNEL); 811 + if (!hmac_data) { 812 + ret = -ENOMEM; 813 + goto out; 814 + } 815 + /* output length */ 816 + i = 0; 817 + hmac_data[i++] = hash_len >> 8; 818 + hmac_data[i++] = hash_len; 819 + 820 + /* label */ 821 + static_assert(label_len <= 255); 822 + hmac_data[i] = label_len; 823 + memcpy(&hmac_data[i + 1], label, label_len); 824 + i += 1 + label_len; 825 + 826 + /* context */ 827 + ctx_len = sprintf(&hmac_data[i + 1], "%02d %s", hmac_id, psk_digest); 828 + if (ctx_len > 255) { 673 829 ret = -EINVAL; 674 - goto out_free_prk; 830 + goto out; 675 831 } 676 - ret = hkdf_extract(hmac_tfm, psk, psk_len, 677 - default_salt, prk_len, prk); 678 - if (ret) 679 - goto out_free_prk; 832 + hmac_data[i] = ctx_len; 833 + i += 1 + ctx_len; 680 834 681 - ret = crypto_shash_setkey(hmac_tfm, prk, prk_len); 682 - if (ret) 683 - goto out_free_prk; 684 - 685 - ctx = kasprintf(GFP_KERNEL, "%02d %s", hmac_id, psk_digest); 686 - if (!ctx) { 687 - ret = -ENOMEM; 688 - goto out_free_prk; 689 - } 835 + /* counter (this overwrites the NUL terminator written by sprintf) */ 836 + hmac_data[i++] = 1; 690 837 691 838 tls_key = kzalloc(psk_len, GFP_KERNEL); 692 839 if (!tls_key) { 693 840 ret = -ENOMEM; 694 - goto out_free_ctx; 841 + goto out; 695 842 } 696 - ret = hkdf_expand_label(hmac_tfm, 697 - label, strlen(label), 698 - ctx, strlen(ctx), 699 - tls_key, psk_len); 843 + ret = nvme_auth_hmac(hmac_id, prk, hash_len, hmac_data, i, tls_key); 700 844 if (ret) { 701 - kfree(tls_key); 702 - goto out_free_ctx; 845 + kfree_sensitive(tls_key); 846 + goto out; 703 847 } 704 848 *ret_psk = tls_key; 705 - 706 - out_free_ctx: 707 - kfree(ctx); 708 - out_free_prk: 709 - kfree(prk); 710 - out_free_shash: 711 - crypto_free_shash(hmac_tfm); 712 - 849 + out: 850 + kfree_sensitive(hmac_data); 851 + memzero_explicit(prk, sizeof(prk)); 713 852 return ret; 714 853 } 715 854 EXPORT_SYMBOL_GPL(nvme_auth_derive_tls_psk);
+175
drivers/nvme/common/tests/auth_kunit.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * Unit tests for NVMe authentication functions 4 + * 5 + * Copyright 2026 Google LLC 6 + */ 7 + 8 + #include <crypto/sha2.h> 9 + #include <kunit/test.h> 10 + #include <linux/nvme.h> 11 + #include <linux/nvme-auth.h> 12 + #include <linux/slab.h> 13 + 14 + struct nvme_auth_test_values { 15 + u8 hmac_id; 16 + size_t hash_len; 17 + u8 expected_psk[NVME_AUTH_MAX_DIGEST_SIZE]; 18 + char *expected_psk_digest; 19 + u8 expected_tls_psk[NVME_AUTH_MAX_DIGEST_SIZE]; 20 + }; 21 + 22 + static void kfree_action(void *ptr) 23 + { 24 + kfree(ptr); 25 + } 26 + 27 + static void kunit_add_kfree_action(struct kunit *test, void *ptr) 28 + { 29 + KUNIT_ASSERT_EQ(test, 0, 30 + kunit_add_action_or_reset(test, kfree_action, ptr)); 31 + } 32 + 33 + /* 34 + * Test the derivation of a TLS PSK from the initial skey. The vals parameter 35 + * gives the expected value of tls_psk as well as the intermediate values psk 36 + * and psk_digest. The inputs are implicitly the fixed values set below. 37 + */ 38 + static void 39 + test_nvme_auth_derive_tls_psk(struct kunit *test, 40 + const struct nvme_auth_test_values *vals) 41 + { 42 + const u8 hmac_id = vals->hmac_id; 43 + const size_t hash_len = vals->hash_len; 44 + const size_t skey_len = hash_len; 45 + u8 skey[NVME_AUTH_MAX_DIGEST_SIZE]; 46 + u8 c1[NVME_AUTH_MAX_DIGEST_SIZE]; 47 + u8 c2[NVME_AUTH_MAX_DIGEST_SIZE]; 48 + const char *subsysnqn = "subsysnqn"; 49 + const char *hostnqn = "hostnqn"; 50 + u8 *psk = NULL, *tls_psk = NULL; 51 + char *psk_digest = NULL; 52 + size_t psk_len; 53 + int ret; 54 + 55 + for (int i = 0; i < NVME_AUTH_MAX_DIGEST_SIZE; i++) { 56 + skey[i] = 'A' + i; 57 + c1[i] = i; 58 + c2[i] = 0xff - i; 59 + } 60 + 61 + ret = nvme_auth_generate_psk(hmac_id, skey, skey_len, c1, c2, hash_len, 62 + &psk, &psk_len); 63 + kunit_add_kfree_action(test, psk); 64 + KUNIT_ASSERT_EQ(test, 0, ret); 65 + KUNIT_ASSERT_EQ(test, hash_len, psk_len); 66 + KUNIT_ASSERT_MEMEQ(test, vals->expected_psk, psk, psk_len); 67 + 68 + ret = nvme_auth_generate_digest(hmac_id, psk, psk_len, subsysnqn, 69 + hostnqn, &psk_digest); 70 + kunit_add_kfree_action(test, psk_digest); 71 + if (vals->expected_psk_digest == NULL) { 72 + /* 73 + * Algorithm has an ID assigned but is not supported by 74 + * nvme_auth_generate_digest(). 75 + */ 76 + KUNIT_ASSERT_EQ(test, -EINVAL, ret); 77 + return; 78 + } 79 + KUNIT_ASSERT_EQ(test, 0, ret); 80 + KUNIT_ASSERT_STREQ(test, vals->expected_psk_digest, psk_digest); 81 + 82 + ret = nvme_auth_derive_tls_psk(hmac_id, psk, psk_len, psk_digest, 83 + &tls_psk); 84 + kunit_add_kfree_action(test, tls_psk); 85 + KUNIT_ASSERT_EQ(test, 0, ret); 86 + KUNIT_ASSERT_MEMEQ(test, vals->expected_tls_psk, tls_psk, psk_len); 87 + } 88 + 89 + static void test_nvme_auth_derive_tls_psk_hmac_sha256(struct kunit *test) 90 + { 91 + static const struct nvme_auth_test_values vals = { 92 + .hmac_id = NVME_AUTH_HASH_SHA256, 93 + .hash_len = SHA256_DIGEST_SIZE, 94 + .expected_psk = { 95 + 0x17, 0x33, 0xc5, 0x9f, 0xa7, 0xf4, 0x8f, 0xcf, 96 + 0x37, 0xf5, 0xf2, 0x6f, 0xc4, 0xff, 0x02, 0x68, 97 + 0xad, 0x4f, 0x78, 0xe0, 0x30, 0xf4, 0xf3, 0xb0, 98 + 0xbf, 0xd1, 0xd4, 0x7e, 0x7b, 0xb1, 0x44, 0x7a, 99 + }, 100 + .expected_psk_digest = "OldoKuTfKddMuyCznAZojkWD7P4D9/AtzDzLimtOxqI=", 101 + .expected_tls_psk = { 102 + 0x3c, 0x17, 0xda, 0x62, 0x84, 0x74, 0xa0, 0x4d, 103 + 0x22, 0x47, 0xc4, 0xca, 0xb4, 0x79, 0x68, 0xc9, 104 + 0x15, 0x38, 0x81, 0x93, 0xf7, 0xc0, 0x71, 0xbd, 105 + 0x94, 0x89, 0xcc, 0x36, 0x66, 0xcd, 0x7c, 0xc8, 106 + }, 107 + }; 108 + 109 + test_nvme_auth_derive_tls_psk(test, &vals); 110 + } 111 + 112 + static void test_nvme_auth_derive_tls_psk_hmac_sha384(struct kunit *test) 113 + { 114 + static const struct nvme_auth_test_values vals = { 115 + .hmac_id = NVME_AUTH_HASH_SHA384, 116 + .hash_len = SHA384_DIGEST_SIZE, 117 + .expected_psk = { 118 + 0xf1, 0x4b, 0x2d, 0xd3, 0x23, 0x4c, 0x45, 0x96, 119 + 0x94, 0xd3, 0xbc, 0x63, 0xf8, 0x96, 0x8b, 0xd6, 120 + 0xb3, 0x7c, 0x2c, 0x6d, 0xe8, 0x49, 0xe2, 0x2e, 121 + 0x11, 0x87, 0x49, 0x00, 0x1c, 0xe4, 0xbb, 0xe8, 122 + 0x64, 0x0b, 0x9e, 0x3a, 0x74, 0x8c, 0xb1, 0x1c, 123 + 0xe4, 0xb1, 0xd7, 0x1d, 0x35, 0x9c, 0xce, 0x39, 124 + }, 125 + .expected_psk_digest = "cffMWk8TSS7HOQebjgYEIkrPrjWPV4JE5cdPB8WhEvY4JBW5YynKyv66XscN4A9n", 126 + .expected_tls_psk = { 127 + 0x27, 0x74, 0x75, 0x32, 0x33, 0x53, 0x7b, 0x3f, 128 + 0xa5, 0x0e, 0xb7, 0xd1, 0x6a, 0x8e, 0x43, 0x45, 129 + 0x7d, 0x85, 0xf4, 0x90, 0x6c, 0x00, 0x5b, 0x22, 130 + 0x36, 0x61, 0x6c, 0x5d, 0x80, 0x93, 0x9d, 0x08, 131 + 0x98, 0xff, 0xf1, 0x5b, 0xb8, 0xb7, 0x71, 0x19, 132 + 0xd2, 0xbe, 0x0a, 0xac, 0x42, 0x3e, 0x75, 0x90, 133 + }, 134 + }; 135 + 136 + test_nvme_auth_derive_tls_psk(test, &vals); 137 + } 138 + 139 + static void test_nvme_auth_derive_tls_psk_hmac_sha512(struct kunit *test) 140 + { 141 + static const struct nvme_auth_test_values vals = { 142 + .hmac_id = NVME_AUTH_HASH_SHA512, 143 + .hash_len = SHA512_DIGEST_SIZE, 144 + .expected_psk = { 145 + 0x9c, 0x9f, 0x08, 0x9a, 0x61, 0x8b, 0x47, 0xd2, 146 + 0xd7, 0x5f, 0x4b, 0x6c, 0x28, 0x07, 0x04, 0x24, 147 + 0x48, 0x7b, 0x44, 0x5d, 0xd9, 0x6e, 0x70, 0xc4, 148 + 0xc0, 0x9b, 0x55, 0xe8, 0xb6, 0x00, 0x01, 0x52, 149 + 0xa3, 0x36, 0x3c, 0x34, 0x54, 0x04, 0x3f, 0x38, 150 + 0xf0, 0xb8, 0x50, 0x36, 0xde, 0xd4, 0x06, 0x55, 151 + 0x35, 0x0a, 0xa8, 0x7b, 0x8b, 0x6a, 0x28, 0x2b, 152 + 0x5c, 0x1a, 0xca, 0xe1, 0x62, 0x33, 0xdd, 0x5b, 153 + }, 154 + /* nvme_auth_generate_digest() doesn't support SHA-512 yet. */ 155 + .expected_psk_digest = NULL, 156 + }; 157 + 158 + test_nvme_auth_derive_tls_psk(test, &vals); 159 + } 160 + 161 + static struct kunit_case nvme_auth_test_cases[] = { 162 + KUNIT_CASE(test_nvme_auth_derive_tls_psk_hmac_sha256), 163 + KUNIT_CASE(test_nvme_auth_derive_tls_psk_hmac_sha384), 164 + KUNIT_CASE(test_nvme_auth_derive_tls_psk_hmac_sha512), 165 + {}, 166 + }; 167 + 168 + static struct kunit_suite nvme_auth_test_suite = { 169 + .name = "nvme-auth", 170 + .test_cases = nvme_auth_test_cases, 171 + }; 172 + kunit_test_suite(nvme_auth_test_suite); 173 + 174 + MODULE_DESCRIPTION("Unit tests for NVMe authentication functions"); 175 + MODULE_LICENSE("GPL");
+67 -120
drivers/nvme/host/auth.c
··· 7 7 #include <linux/base64.h> 8 8 #include <linux/prandom.h> 9 9 #include <linux/unaligned.h> 10 - #include <crypto/hash.h> 11 10 #include <crypto/dh.h> 12 11 #include "nvme.h" 13 12 #include "fabrics.h" ··· 21 22 struct list_head entry; 22 23 struct work_struct auth_work; 23 24 struct nvme_ctrl *ctrl; 24 - struct crypto_shash *shash_tfm; 25 25 struct crypto_kpp *dh_tfm; 26 26 struct nvme_dhchap_key *transformed_key; 27 27 void *buf; ··· 36 38 u8 hash_id; 37 39 u8 sc_c; 38 40 size_t hash_len; 39 - u8 c1[64]; 40 - u8 c2[64]; 41 - u8 response[64]; 41 + u8 c1[NVME_AUTH_MAX_DIGEST_SIZE]; 42 + u8 c2[NVME_AUTH_MAX_DIGEST_SIZE]; 43 + u8 response[NVME_AUTH_MAX_DIGEST_SIZE]; 42 44 u8 *ctrl_key; 43 45 u8 *host_key; 44 46 u8 *sess_key; ··· 123 125 { 124 126 struct nvmf_auth_dhchap_negotiate_data *data = chap->buf; 125 127 size_t size = sizeof(*data) + sizeof(union nvmf_auth_protocol); 128 + u8 dh_list_offset = NVME_AUTH_DHCHAP_MAX_DH_IDS; 129 + u8 *idlist = data->auth_protocol[0].dhchap.idlist; 126 130 127 131 if (size > CHAP_BUF_SIZE) { 128 132 chap->status = NVME_AUTH_DHCHAP_FAILURE_INCORRECT_PAYLOAD; ··· 141 141 data->sc_c = NVME_AUTH_SECP_NEWTLSPSK; 142 142 } else 143 143 data->sc_c = NVME_AUTH_SECP_NOSC; 144 + chap->sc_c = data->sc_c; 144 145 data->napd = 1; 145 146 data->auth_protocol[0].dhchap.authid = NVME_AUTH_DHCHAP_AUTH_ID; 146 147 data->auth_protocol[0].dhchap.halen = 3; 147 - data->auth_protocol[0].dhchap.dhlen = 6; 148 - data->auth_protocol[0].dhchap.idlist[0] = NVME_AUTH_HASH_SHA256; 149 - data->auth_protocol[0].dhchap.idlist[1] = NVME_AUTH_HASH_SHA384; 150 - data->auth_protocol[0].dhchap.idlist[2] = NVME_AUTH_HASH_SHA512; 151 - data->auth_protocol[0].dhchap.idlist[30] = NVME_AUTH_DHGROUP_NULL; 152 - data->auth_protocol[0].dhchap.idlist[31] = NVME_AUTH_DHGROUP_2048; 153 - data->auth_protocol[0].dhchap.idlist[32] = NVME_AUTH_DHGROUP_3072; 154 - data->auth_protocol[0].dhchap.idlist[33] = NVME_AUTH_DHGROUP_4096; 155 - data->auth_protocol[0].dhchap.idlist[34] = NVME_AUTH_DHGROUP_6144; 156 - data->auth_protocol[0].dhchap.idlist[35] = NVME_AUTH_DHGROUP_8192; 157 - 158 - chap->sc_c = data->sc_c; 148 + idlist[0] = NVME_AUTH_HASH_SHA256; 149 + idlist[1] = NVME_AUTH_HASH_SHA384; 150 + idlist[2] = NVME_AUTH_HASH_SHA512; 151 + if (chap->sc_c == NVME_AUTH_SECP_NOSC) 152 + idlist[dh_list_offset++] = NVME_AUTH_DHGROUP_NULL; 153 + idlist[dh_list_offset++] = NVME_AUTH_DHGROUP_2048; 154 + idlist[dh_list_offset++] = NVME_AUTH_DHGROUP_3072; 155 + idlist[dh_list_offset++] = NVME_AUTH_DHGROUP_4096; 156 + idlist[dh_list_offset++] = NVME_AUTH_DHGROUP_6144; 157 + idlist[dh_list_offset++] = NVME_AUTH_DHGROUP_8192; 158 + data->auth_protocol[0].dhchap.dhlen = 159 + dh_list_offset - NVME_AUTH_DHCHAP_MAX_DH_IDS; 159 160 160 161 return size; 161 162 } ··· 184 183 return -EPROTO; 185 184 } 186 185 187 - if (chap->hash_id == data->hashid && chap->shash_tfm && 188 - !strcmp(crypto_shash_alg_name(chap->shash_tfm), hmac_name) && 189 - crypto_shash_digestsize(chap->shash_tfm) == data->hl) { 186 + if (chap->hash_id == data->hashid && chap->hash_len == data->hl) { 190 187 dev_dbg(ctrl->device, 191 188 "qid %d: reuse existing hash %s\n", 192 189 chap->qid, hmac_name); 193 190 goto select_kpp; 194 191 } 195 192 196 - /* Reset if hash cannot be reused */ 197 - if (chap->shash_tfm) { 198 - crypto_free_shash(chap->shash_tfm); 199 - chap->hash_id = 0; 200 - chap->hash_len = 0; 201 - } 202 - chap->shash_tfm = crypto_alloc_shash(hmac_name, 0, 203 - CRYPTO_ALG_ALLOCATES_MEMORY); 204 - if (IS_ERR(chap->shash_tfm)) { 205 - dev_warn(ctrl->device, 206 - "qid %d: failed to allocate hash %s, error %ld\n", 207 - chap->qid, hmac_name, PTR_ERR(chap->shash_tfm)); 208 - chap->shash_tfm = NULL; 209 - chap->status = NVME_AUTH_DHCHAP_FAILURE_FAILED; 210 - return -ENOMEM; 211 - } 212 - 213 - if (crypto_shash_digestsize(chap->shash_tfm) != data->hl) { 193 + if (nvme_auth_hmac_hash_len(data->hashid) != data->hl) { 214 194 dev_warn(ctrl->device, 215 195 "qid %d: invalid hash length %d\n", 216 196 chap->qid, data->hl); 217 - crypto_free_shash(chap->shash_tfm); 218 - chap->shash_tfm = NULL; 219 197 chap->status = NVME_AUTH_DHCHAP_FAILURE_HASH_UNUSABLE; 220 198 return -EPROTO; 221 199 } ··· 414 434 static int nvme_auth_dhchap_setup_host_response(struct nvme_ctrl *ctrl, 415 435 struct nvme_dhchap_queue_context *chap) 416 436 { 417 - SHASH_DESC_ON_STACK(shash, chap->shash_tfm); 437 + struct nvme_auth_hmac_ctx hmac; 418 438 u8 buf[4], *challenge = chap->c1; 419 439 int ret; 420 440 ··· 434 454 __func__, chap->qid); 435 455 } 436 456 437 - ret = crypto_shash_setkey(chap->shash_tfm, 438 - chap->transformed_key->key, chap->transformed_key->len); 439 - if (ret) { 440 - dev_warn(ctrl->device, "qid %d: failed to set key, error %d\n", 441 - chap->qid, ret); 457 + ret = nvme_auth_hmac_init(&hmac, chap->hash_id, 458 + chap->transformed_key->key, 459 + chap->transformed_key->len); 460 + if (ret) 442 461 goto out; 443 - } 444 462 445 463 if (chap->dh_tfm) { 446 464 challenge = kmalloc(chap->hash_len, GFP_KERNEL); ··· 455 477 goto out; 456 478 } 457 479 458 - shash->tfm = chap->shash_tfm; 459 - ret = crypto_shash_init(shash); 460 - if (ret) 461 - goto out; 462 - ret = crypto_shash_update(shash, challenge, chap->hash_len); 463 - if (ret) 464 - goto out; 480 + nvme_auth_hmac_update(&hmac, challenge, chap->hash_len); 481 + 465 482 put_unaligned_le32(chap->s1, buf); 466 - ret = crypto_shash_update(shash, buf, 4); 467 - if (ret) 468 - goto out; 483 + nvme_auth_hmac_update(&hmac, buf, 4); 484 + 469 485 put_unaligned_le16(chap->transaction, buf); 470 - ret = crypto_shash_update(shash, buf, 2); 471 - if (ret) 472 - goto out; 486 + nvme_auth_hmac_update(&hmac, buf, 2); 487 + 473 488 *buf = chap->sc_c; 474 - ret = crypto_shash_update(shash, buf, 1); 475 - if (ret) 476 - goto out; 477 - ret = crypto_shash_update(shash, "HostHost", 8); 478 - if (ret) 479 - goto out; 480 - ret = crypto_shash_update(shash, ctrl->opts->host->nqn, 481 - strlen(ctrl->opts->host->nqn)); 482 - if (ret) 483 - goto out; 489 + nvme_auth_hmac_update(&hmac, buf, 1); 490 + nvme_auth_hmac_update(&hmac, "HostHost", 8); 491 + nvme_auth_hmac_update(&hmac, ctrl->opts->host->nqn, 492 + strlen(ctrl->opts->host->nqn)); 484 493 memset(buf, 0, sizeof(buf)); 485 - ret = crypto_shash_update(shash, buf, 1); 486 - if (ret) 487 - goto out; 488 - ret = crypto_shash_update(shash, ctrl->opts->subsysnqn, 489 - strlen(ctrl->opts->subsysnqn)); 490 - if (ret) 491 - goto out; 492 - ret = crypto_shash_final(shash, chap->response); 494 + nvme_auth_hmac_update(&hmac, buf, 1); 495 + nvme_auth_hmac_update(&hmac, ctrl->opts->subsysnqn, 496 + strlen(ctrl->opts->subsysnqn)); 497 + nvme_auth_hmac_final(&hmac, chap->response); 498 + ret = 0; 493 499 out: 494 500 if (challenge != chap->c1) 495 501 kfree(challenge); 502 + memzero_explicit(&hmac, sizeof(hmac)); 496 503 return ret; 497 504 } 498 505 499 506 static int nvme_auth_dhchap_setup_ctrl_response(struct nvme_ctrl *ctrl, 500 507 struct nvme_dhchap_queue_context *chap) 501 508 { 502 - SHASH_DESC_ON_STACK(shash, chap->shash_tfm); 509 + struct nvme_auth_hmac_ctx hmac; 503 510 struct nvme_dhchap_key *transformed_key; 504 511 u8 buf[4], *challenge = chap->c2; 505 512 int ret; ··· 496 533 return ret; 497 534 } 498 535 499 - ret = crypto_shash_setkey(chap->shash_tfm, 500 - transformed_key->key, transformed_key->len); 536 + ret = nvme_auth_hmac_init(&hmac, chap->hash_id, transformed_key->key, 537 + transformed_key->len); 501 538 if (ret) { 502 - dev_warn(ctrl->device, "qid %d: failed to set key, error %d\n", 539 + dev_warn(ctrl->device, "qid %d: failed to init hmac, error %d\n", 503 540 chap->qid, ret); 504 541 goto out; 505 542 } ··· 526 563 __func__, chap->qid, ctrl->opts->subsysnqn); 527 564 dev_dbg(ctrl->device, "%s: qid %d hostnqn %s\n", 528 565 __func__, chap->qid, ctrl->opts->host->nqn); 529 - shash->tfm = chap->shash_tfm; 530 - ret = crypto_shash_init(shash); 531 - if (ret) 532 - goto out; 533 - ret = crypto_shash_update(shash, challenge, chap->hash_len); 534 - if (ret) 535 - goto out; 566 + 567 + nvme_auth_hmac_update(&hmac, challenge, chap->hash_len); 568 + 536 569 put_unaligned_le32(chap->s2, buf); 537 - ret = crypto_shash_update(shash, buf, 4); 538 - if (ret) 539 - goto out; 570 + nvme_auth_hmac_update(&hmac, buf, 4); 571 + 540 572 put_unaligned_le16(chap->transaction, buf); 541 - ret = crypto_shash_update(shash, buf, 2); 542 - if (ret) 543 - goto out; 573 + nvme_auth_hmac_update(&hmac, buf, 2); 574 + 544 575 memset(buf, 0, 4); 545 - ret = crypto_shash_update(shash, buf, 1); 546 - if (ret) 547 - goto out; 548 - ret = crypto_shash_update(shash, "Controller", 10); 549 - if (ret) 550 - goto out; 551 - ret = crypto_shash_update(shash, ctrl->opts->subsysnqn, 552 - strlen(ctrl->opts->subsysnqn)); 553 - if (ret) 554 - goto out; 555 - ret = crypto_shash_update(shash, buf, 1); 556 - if (ret) 557 - goto out; 558 - ret = crypto_shash_update(shash, ctrl->opts->host->nqn, 559 - strlen(ctrl->opts->host->nqn)); 560 - if (ret) 561 - goto out; 562 - ret = crypto_shash_final(shash, chap->response); 576 + nvme_auth_hmac_update(&hmac, buf, 1); 577 + nvme_auth_hmac_update(&hmac, "Controller", 10); 578 + nvme_auth_hmac_update(&hmac, ctrl->opts->subsysnqn, 579 + strlen(ctrl->opts->subsysnqn)); 580 + nvme_auth_hmac_update(&hmac, buf, 1); 581 + nvme_auth_hmac_update(&hmac, ctrl->opts->host->nqn, 582 + strlen(ctrl->opts->host->nqn)); 583 + nvme_auth_hmac_final(&hmac, chap->response); 584 + ret = 0; 563 585 out: 564 586 if (challenge != chap->c2) 565 587 kfree(challenge); 588 + memzero_explicit(&hmac, sizeof(hmac)); 566 589 nvme_auth_free_key(transformed_key); 567 590 return ret; 568 591 } ··· 638 689 { 639 690 nvme_auth_reset_dhchap(chap); 640 691 chap->authenticated = false; 641 - if (chap->shash_tfm) 642 - crypto_free_shash(chap->shash_tfm); 643 692 if (chap->dh_tfm) 644 693 crypto_free_kpp(chap->dh_tfm); 645 694 } ··· 655 708 static int nvme_auth_secure_concat(struct nvme_ctrl *ctrl, 656 709 struct nvme_dhchap_queue_context *chap) 657 710 { 658 - u8 *psk, *digest, *tls_psk; 711 + u8 *psk, *tls_psk; 712 + char *digest; 659 713 struct key *tls_key; 660 714 size_t psk_len; 661 715 int ret = 0; ··· 1019 1071 INIT_WORK(&ctrl->dhchap_auth_work, nvme_ctrl_auth_work); 1020 1072 if (!ctrl->opts) 1021 1073 return 0; 1022 - ret = nvme_auth_generate_key(ctrl->opts->dhchap_secret, 1023 - &ctrl->host_key); 1074 + ret = nvme_auth_parse_key(ctrl->opts->dhchap_secret, &ctrl->host_key); 1024 1075 if (ret) 1025 1076 return ret; 1026 - ret = nvme_auth_generate_key(ctrl->opts->dhchap_ctrl_secret, 1027 - &ctrl->ctrl_key); 1077 + ret = nvme_auth_parse_key(ctrl->opts->dhchap_ctrl_secret, 1078 + &ctrl->ctrl_key); 1028 1079 if (ret) 1029 1080 goto err_free_dhchap_secret; 1030 1081
+59 -29
drivers/nvme/host/core.c
··· 1884 1884 return true; 1885 1885 } 1886 1886 1887 - static void nvme_config_discard(struct nvme_ns *ns, struct queue_limits *lim) 1888 - { 1889 - struct nvme_ctrl *ctrl = ns->ctrl; 1890 - 1891 - if (ctrl->dmrsl && ctrl->dmrsl <= nvme_sect_to_lba(ns->head, UINT_MAX)) 1892 - lim->max_hw_discard_sectors = 1893 - nvme_lba_to_sect(ns->head, ctrl->dmrsl); 1894 - else if (ctrl->oncs & NVME_CTRL_ONCS_DSM) 1895 - lim->max_hw_discard_sectors = UINT_MAX; 1896 - else 1897 - lim->max_hw_discard_sectors = 0; 1898 - 1899 - lim->discard_granularity = lim->logical_block_size; 1900 - 1901 - if (ctrl->dmrl) 1902 - lim->max_discard_segments = ctrl->dmrl; 1903 - else 1904 - lim->max_discard_segments = NVME_DSM_MAX_RANGES; 1905 - } 1906 - 1907 1887 static bool nvme_ns_ids_equal(struct nvme_ns_ids *a, struct nvme_ns_ids *b) 1908 1888 { 1909 1889 return uuid_equal(&a->uuid, &b->uuid) && ··· 2059 2079 } 2060 2080 2061 2081 static bool nvme_update_disk_info(struct nvme_ns *ns, struct nvme_id_ns *id, 2062 - struct queue_limits *lim) 2082 + struct nvme_id_ns_nvm *nvm, struct queue_limits *lim) 2063 2083 { 2064 2084 struct nvme_ns_head *head = ns->head; 2085 + struct nvme_ctrl *ctrl = ns->ctrl; 2065 2086 u32 bs = 1U << head->lba_shift; 2066 2087 u32 atomic_bs, phys_bs, io_opt = 0; 2088 + u32 npdg = 1, npda = 1; 2067 2089 bool valid = true; 2090 + u8 optperf; 2068 2091 2069 2092 /* 2070 2093 * The block layer can't support LBA sizes larger than the page size ··· 2082 2099 phys_bs = bs; 2083 2100 atomic_bs = nvme_configure_atomic_write(ns, id, lim, bs); 2084 2101 2085 - if (id->nsfeat & NVME_NS_FEAT_IO_OPT) { 2102 + optperf = id->nsfeat >> NVME_NS_FEAT_OPTPERF_SHIFT; 2103 + if (ctrl->vs >= NVME_VS(2, 1, 0)) 2104 + optperf &= NVME_NS_FEAT_OPTPERF_MASK_2_1; 2105 + else 2106 + optperf &= NVME_NS_FEAT_OPTPERF_MASK; 2107 + if (optperf) { 2086 2108 /* NPWG = Namespace Preferred Write Granularity */ 2087 2109 phys_bs = bs * (1 + le16_to_cpu(id->npwg)); 2088 2110 /* NOWS = Namespace Optimal Write Size */ ··· 2104 2116 lim->physical_block_size = min(phys_bs, atomic_bs); 2105 2117 lim->io_min = phys_bs; 2106 2118 lim->io_opt = io_opt; 2107 - if ((ns->ctrl->quirks & NVME_QUIRK_DEALLOCATE_ZEROES) && 2108 - (ns->ctrl->oncs & NVME_CTRL_ONCS_DSM)) 2119 + if ((ctrl->quirks & NVME_QUIRK_DEALLOCATE_ZEROES) && 2120 + (ctrl->oncs & NVME_CTRL_ONCS_DSM)) 2109 2121 lim->max_write_zeroes_sectors = UINT_MAX; 2110 2122 else 2111 - lim->max_write_zeroes_sectors = ns->ctrl->max_zeroes_sectors; 2123 + lim->max_write_zeroes_sectors = ctrl->max_zeroes_sectors; 2124 + 2125 + if (ctrl->dmrsl && ctrl->dmrsl <= nvme_sect_to_lba(ns->head, UINT_MAX)) 2126 + lim->max_hw_discard_sectors = 2127 + nvme_lba_to_sect(ns->head, ctrl->dmrsl); 2128 + else if (ctrl->oncs & NVME_CTRL_ONCS_DSM) 2129 + lim->max_hw_discard_sectors = UINT_MAX; 2130 + else 2131 + lim->max_hw_discard_sectors = 0; 2132 + 2133 + /* 2134 + * NVMe namespaces advertise both a preferred deallocate granularity 2135 + * (for a discard length) and alignment (for a discard starting offset). 2136 + * However, Linux block devices advertise a single discard_granularity. 2137 + * From NVM Command Set specification 1.1 section 5.2.2, the NPDGL/NPDAL 2138 + * fields in the NVM Command Set Specific Identify Namespace structure 2139 + * are preferred to NPDG/NPDA in the Identify Namespace structure since 2140 + * they can represent larger values. However, NPDGL or NPDAL may be 0 if 2141 + * unsupported. NPDG and NPDA are 0's based. 2142 + * From Figure 115 of NVM Command Set specification 1.1, NPDGL and NPDAL 2143 + * are supported if the high bit of OPTPERF is set. NPDG is supported if 2144 + * the low bit of OPTPERF is set. NPDA is supported if either is set. 2145 + * NPDG should be a multiple of NPDA, and likewise NPDGL should be a 2146 + * multiple of NPDAL, but the spec doesn't say anything about NPDG vs. 2147 + * NPDAL or NPDGL vs. NPDA. So compute the maximum instead of assuming 2148 + * NPDG(L) is the larger. If neither NPDG, NPDGL, NPDA, nor NPDAL are 2149 + * supported, default the discard_granularity to the logical block size. 2150 + */ 2151 + if (optperf & 0x2 && nvm && nvm->npdgl) 2152 + npdg = le32_to_cpu(nvm->npdgl); 2153 + else if (optperf & 0x1) 2154 + npdg = from0based(id->npdg); 2155 + if (optperf & 0x2 && nvm && nvm->npdal) 2156 + npda = le32_to_cpu(nvm->npdal); 2157 + else if (optperf) 2158 + npda = from0based(id->npda); 2159 + if (check_mul_overflow(max(npdg, npda), lim->logical_block_size, 2160 + &lim->discard_granularity)) 2161 + lim->discard_granularity = lim->logical_block_size; 2162 + 2163 + if (ctrl->dmrl) 2164 + lim->max_discard_segments = ctrl->dmrl; 2165 + else 2166 + lim->max_discard_segments = NVME_DSM_MAX_RANGES; 2112 2167 return valid; 2113 2168 } 2114 2169 ··· 2385 2354 } 2386 2355 lbaf = nvme_lbaf_index(id->flbas); 2387 2356 2388 - if (ns->ctrl->ctratt & NVME_CTRL_ATTR_ELBAS) { 2357 + if (nvme_id_cns_ok(ns->ctrl, NVME_ID_CNS_CS_NS)) { 2389 2358 ret = nvme_identify_ns_nvm(ns->ctrl, info->nsid, &nvm); 2390 2359 if (ret < 0) 2391 2360 goto out; ··· 2413 2382 nvme_set_ctrl_limits(ns->ctrl, &lim, false); 2414 2383 nvme_configure_metadata(ns->ctrl, ns->head, id, nvm, info); 2415 2384 nvme_set_chunk_sectors(ns, id, &lim); 2416 - if (!nvme_update_disk_info(ns, id, &lim)) 2385 + if (!nvme_update_disk_info(ns, id, nvm, &lim)) 2417 2386 capacity = 0; 2418 2387 2419 - nvme_config_discard(ns, &lim); 2420 2388 if (IS_ENABLED(CONFIG_BLK_DEV_ZONED) && 2421 2389 ns->head->ids.csi == NVME_CSI_ZNS) 2422 2390 nvme_update_zone_info(ns, &lim, &zi); ··· 3419 3389 3420 3390 ctrl->dmrl = id->dmrl; 3421 3391 ctrl->dmrsl = le32_to_cpu(id->dmrsl); 3422 - if (id->wzsl) 3392 + if (id->wzsl && !(ctrl->quirks & NVME_QUIRK_DISABLE_WRITE_ZEROES)) 3423 3393 ctrl->max_zeroes_sectors = nvme_mps_to_sectors(ctrl, id->wzsl); 3424 3394 3425 3395 free_data:
+6
drivers/nvme/host/nvme.h
··· 762 762 return (len >> 2) - 1; 763 763 } 764 764 765 + /* Decode a 2-byte "0's based"/"0-based" field */ 766 + static inline u32 from0based(__le16 value) 767 + { 768 + return (u32)le16_to_cpu(value) + 1; 769 + } 770 + 765 771 static inline bool nvme_is_ana_error(u16 status) 766 772 { 767 773 switch (status & NVME_SCT_SC_MASK) {
+2
drivers/nvme/host/pci.c
··· 4176 4176 .driver_data = NVME_QUIRK_DISABLE_WRITE_ZEROES, }, 4177 4177 { PCI_DEVICE(0x2646, 0x501E), /* KINGSTON OM3PGP4xxxxQ OS21011 NVMe SSD */ 4178 4178 .driver_data = NVME_QUIRK_DISABLE_WRITE_ZEROES, }, 4179 + { PCI_DEVICE(0x2646, 0x502F), /* KINGSTON OM3SGP4xxxxK NVMe SSD */ 4180 + .driver_data = NVME_QUIRK_DISABLE_WRITE_ZEROES, }, 4179 4181 { PCI_DEVICE(0x1f40, 0x1202), /* Netac Technologies Co. NV3000 NVMe SSD */ 4180 4182 .driver_data = NVME_QUIRK_BOGUS_NID, }, 4181 4183 { PCI_DEVICE(0x1f40, 0x5236), /* Netac Technologies Co. NV7000 NVMe SSD */
+46 -4
drivers/nvme/host/sysfs.c
··· 658 658 struct nvme_dhchap_key *key, *host_key; 659 659 int ret; 660 660 661 - ret = nvme_auth_generate_key(dhchap_secret, &key); 661 + ret = nvme_auth_parse_key(dhchap_secret, &key); 662 662 if (ret) { 663 663 kfree(dhchap_secret); 664 664 return ret; ··· 716 716 struct nvme_dhchap_key *key, *ctrl_key; 717 717 int ret; 718 718 719 - ret = nvme_auth_generate_key(dhchap_secret, &key); 719 + ret = nvme_auth_parse_key(dhchap_secret, &key); 720 720 if (ret) { 721 721 kfree(dhchap_secret); 722 722 return ret; ··· 829 829 830 830 return sysfs_emit(buf, "%08x\n", key_serial(key)); 831 831 } 832 - static DEVICE_ATTR_RO(tls_configured_key); 832 + 833 + static ssize_t tls_configured_key_store(struct device *dev, 834 + struct device_attribute *attr, 835 + const char *buf, size_t count) 836 + { 837 + struct nvme_ctrl *ctrl = dev_get_drvdata(dev); 838 + int error, qid; 839 + 840 + error = kstrtoint(buf, 10, &qid); 841 + if (error) 842 + return error; 843 + 844 + /* 845 + * We currently only allow userspace to write a `0` indicating 846 + * generate a new key. 847 + */ 848 + if (qid) 849 + return -EINVAL; 850 + 851 + if (!ctrl->opts || !ctrl->opts->concat) 852 + return -EOPNOTSUPP; 853 + 854 + error = nvme_auth_negotiate(ctrl, 0); 855 + if (error < 0) { 856 + nvme_reset_ctrl(ctrl); 857 + return error; 858 + } 859 + 860 + error = nvme_auth_wait(ctrl, 0); 861 + if (error < 0) { 862 + nvme_reset_ctrl(ctrl); 863 + return error; 864 + } 865 + 866 + /* 867 + * We need to reset the TLS connection, so let's just 868 + * reset the controller. 869 + */ 870 + nvme_reset_ctrl(ctrl); 871 + 872 + return count; 873 + } 874 + static DEVICE_ATTR_RW(tls_configured_key); 833 875 834 876 static ssize_t tls_keyring_show(struct device *dev, 835 877 struct device_attribute *attr, char *buf) ··· 903 861 !ctrl->opts->tls && !ctrl->opts->concat) 904 862 return 0; 905 863 if (a == &dev_attr_tls_configured_key.attr && 906 - (!ctrl->opts->tls_key || ctrl->opts->concat)) 864 + !ctrl->opts->concat) 907 865 return 0; 908 866 if (a == &dev_attr_tls_keyring.attr && 909 867 !ctrl->opts->keyring)
+3 -1
drivers/nvme/target/admin-cmd.c
··· 1057 1057 status = NVME_SC_INTERNAL; 1058 1058 goto out; 1059 1059 } 1060 + if (req->ns->bdev) 1061 + nvmet_bdev_set_nvm_limits(req->ns->bdev, id); 1060 1062 status = nvmet_copy_to_sgl(req, 0, id, sizeof(*id)); 1061 1063 kfree(id); 1062 1064 out: ··· 1605 1603 1606 1604 pr_debug("ctrl %d update keep-alive timer for %d secs\n", 1607 1605 ctrl->cntlid, ctrl->kato); 1608 - mod_delayed_work(system_wq, &ctrl->ka_work, ctrl->kato * HZ); 1606 + mod_delayed_work(system_percpu_wq, &ctrl->ka_work, ctrl->kato * HZ); 1609 1607 out: 1610 1608 nvmet_req_complete(req, status); 1611 1609 }
+58 -144
drivers/nvme/target/auth.c
··· 9 9 #include <linux/init.h> 10 10 #include <linux/slab.h> 11 11 #include <linux/err.h> 12 - #include <crypto/hash.h> 13 12 #include <linux/crc32.h> 14 13 #include <linux/base64.h> 15 14 #include <linux/ctype.h> ··· 43 44 pr_warn("Invalid DH-HMAC-CHAP hash id %d\n", 44 45 key_hash); 45 46 return -EINVAL; 46 - } 47 - if (key_hash > 0) { 48 - /* Validate selected hash algorithm */ 49 - const char *hmac = nvme_auth_hmac_name(key_hash); 50 - 51 - if (!crypto_has_shash(hmac, 0, 0)) { 52 - pr_err("DH-HMAC-CHAP hash %s unsupported\n", hmac); 53 - return -ENOTSUPP; 54 - } 55 47 } 56 48 dhchap_secret = kstrdup(secret, GFP_KERNEL); 57 49 if (!dhchap_secret) ··· 130 140 return ret; 131 141 } 132 142 133 - u8 nvmet_setup_auth(struct nvmet_ctrl *ctrl, struct nvmet_sq *sq) 143 + u8 nvmet_setup_auth(struct nvmet_ctrl *ctrl, struct nvmet_sq *sq, bool reset) 134 144 { 135 145 int ret = 0; 136 146 struct nvmet_host_link *p; ··· 156 166 goto out_unlock; 157 167 } 158 168 159 - if (nvmet_queue_tls_keyid(sq)) { 169 + if (!reset && nvmet_queue_tls_keyid(sq)) { 160 170 pr_debug("host %s tls enabled\n", ctrl->hostnqn); 161 171 goto out_unlock; 162 172 } ··· 282 292 int nvmet_auth_host_hash(struct nvmet_req *req, u8 *response, 283 293 unsigned int shash_len) 284 294 { 285 - struct crypto_shash *shash_tfm; 286 - SHASH_DESC_ON_STACK(shash, shash_tfm); 295 + struct nvme_auth_hmac_ctx hmac; 287 296 struct nvmet_ctrl *ctrl = req->sq->ctrl; 288 - const char *hash_name; 289 297 u8 *challenge = req->sq->dhchap_c1; 290 298 struct nvme_dhchap_key *transformed_key; 291 299 u8 buf[4]; 292 300 int ret; 293 301 294 - hash_name = nvme_auth_hmac_name(ctrl->shash_id); 295 - if (!hash_name) { 296 - pr_warn("Hash ID %d invalid\n", ctrl->shash_id); 297 - return -EINVAL; 298 - } 299 - 300 - shash_tfm = crypto_alloc_shash(hash_name, 0, 0); 301 - if (IS_ERR(shash_tfm)) { 302 - pr_err("failed to allocate shash %s\n", hash_name); 303 - return PTR_ERR(shash_tfm); 304 - } 305 - 306 - if (shash_len != crypto_shash_digestsize(shash_tfm)) { 307 - pr_err("%s: hash len mismatch (len %d digest %d)\n", 308 - __func__, shash_len, 309 - crypto_shash_digestsize(shash_tfm)); 310 - ret = -EINVAL; 311 - goto out_free_tfm; 312 - } 313 - 314 302 transformed_key = nvme_auth_transform_key(ctrl->host_key, 315 303 ctrl->hostnqn); 316 - if (IS_ERR(transformed_key)) { 317 - ret = PTR_ERR(transformed_key); 318 - goto out_free_tfm; 319 - } 304 + if (IS_ERR(transformed_key)) 305 + return PTR_ERR(transformed_key); 320 306 321 - ret = crypto_shash_setkey(shash_tfm, transformed_key->key, 307 + ret = nvme_auth_hmac_init(&hmac, ctrl->shash_id, transformed_key->key, 322 308 transformed_key->len); 323 309 if (ret) 324 310 goto out_free_response; 311 + 312 + if (shash_len != nvme_auth_hmac_hash_len(ctrl->shash_id)) { 313 + pr_err("%s: hash len mismatch (len %u digest %zu)\n", __func__, 314 + shash_len, nvme_auth_hmac_hash_len(ctrl->shash_id)); 315 + ret = -EINVAL; 316 + goto out_free_response; 317 + } 325 318 326 319 if (ctrl->dh_gid != NVME_AUTH_DHGROUP_NULL) { 327 320 challenge = kmalloc(shash_len, GFP_KERNEL); ··· 318 345 req->sq->dhchap_c1, 319 346 challenge, shash_len); 320 347 if (ret) 321 - goto out; 348 + goto out_free_challenge; 322 349 } 323 350 324 351 pr_debug("ctrl %d qid %d host response seq %u transaction %d\n", 325 352 ctrl->cntlid, req->sq->qid, req->sq->dhchap_s1, 326 353 req->sq->dhchap_tid); 327 354 328 - shash->tfm = shash_tfm; 329 - ret = crypto_shash_init(shash); 330 - if (ret) 331 - goto out; 332 - ret = crypto_shash_update(shash, challenge, shash_len); 333 - if (ret) 334 - goto out; 355 + nvme_auth_hmac_update(&hmac, challenge, shash_len); 356 + 335 357 put_unaligned_le32(req->sq->dhchap_s1, buf); 336 - ret = crypto_shash_update(shash, buf, 4); 337 - if (ret) 338 - goto out; 358 + nvme_auth_hmac_update(&hmac, buf, 4); 359 + 339 360 put_unaligned_le16(req->sq->dhchap_tid, buf); 340 - ret = crypto_shash_update(shash, buf, 2); 341 - if (ret) 342 - goto out; 361 + nvme_auth_hmac_update(&hmac, buf, 2); 362 + 343 363 *buf = req->sq->sc_c; 344 - ret = crypto_shash_update(shash, buf, 1); 345 - if (ret) 346 - goto out; 347 - ret = crypto_shash_update(shash, "HostHost", 8); 348 - if (ret) 349 - goto out; 364 + nvme_auth_hmac_update(&hmac, buf, 1); 365 + nvme_auth_hmac_update(&hmac, "HostHost", 8); 350 366 memset(buf, 0, 4); 351 - ret = crypto_shash_update(shash, ctrl->hostnqn, strlen(ctrl->hostnqn)); 352 - if (ret) 353 - goto out; 354 - ret = crypto_shash_update(shash, buf, 1); 355 - if (ret) 356 - goto out; 357 - ret = crypto_shash_update(shash, ctrl->subsys->subsysnqn, 358 - strlen(ctrl->subsys->subsysnqn)); 359 - if (ret) 360 - goto out; 361 - ret = crypto_shash_final(shash, response); 362 - out: 367 + nvme_auth_hmac_update(&hmac, ctrl->hostnqn, strlen(ctrl->hostnqn)); 368 + nvme_auth_hmac_update(&hmac, buf, 1); 369 + nvme_auth_hmac_update(&hmac, ctrl->subsys->subsysnqn, 370 + strlen(ctrl->subsys->subsysnqn)); 371 + nvme_auth_hmac_final(&hmac, response); 372 + ret = 0; 373 + out_free_challenge: 363 374 if (challenge != req->sq->dhchap_c1) 364 375 kfree(challenge); 365 376 out_free_response: 377 + memzero_explicit(&hmac, sizeof(hmac)); 366 378 nvme_auth_free_key(transformed_key); 367 - out_free_tfm: 368 - crypto_free_shash(shash_tfm); 369 379 return ret; 370 380 } 371 381 372 382 int nvmet_auth_ctrl_hash(struct nvmet_req *req, u8 *response, 373 383 unsigned int shash_len) 374 384 { 375 - struct crypto_shash *shash_tfm; 376 - struct shash_desc *shash; 385 + struct nvme_auth_hmac_ctx hmac; 377 386 struct nvmet_ctrl *ctrl = req->sq->ctrl; 378 - const char *hash_name; 379 387 u8 *challenge = req->sq->dhchap_c2; 380 388 struct nvme_dhchap_key *transformed_key; 381 389 u8 buf[4]; 382 390 int ret; 383 391 384 - hash_name = nvme_auth_hmac_name(ctrl->shash_id); 385 - if (!hash_name) { 386 - pr_warn("Hash ID %d invalid\n", ctrl->shash_id); 387 - return -EINVAL; 388 - } 389 - 390 - shash_tfm = crypto_alloc_shash(hash_name, 0, 0); 391 - if (IS_ERR(shash_tfm)) { 392 - pr_err("failed to allocate shash %s\n", hash_name); 393 - return PTR_ERR(shash_tfm); 394 - } 395 - 396 - if (shash_len != crypto_shash_digestsize(shash_tfm)) { 397 - pr_debug("%s: hash len mismatch (len %d digest %d)\n", 398 - __func__, shash_len, 399 - crypto_shash_digestsize(shash_tfm)); 400 - ret = -EINVAL; 401 - goto out_free_tfm; 402 - } 403 - 404 392 transformed_key = nvme_auth_transform_key(ctrl->ctrl_key, 405 393 ctrl->subsys->subsysnqn); 406 - if (IS_ERR(transformed_key)) { 407 - ret = PTR_ERR(transformed_key); 408 - goto out_free_tfm; 409 - } 394 + if (IS_ERR(transformed_key)) 395 + return PTR_ERR(transformed_key); 410 396 411 - ret = crypto_shash_setkey(shash_tfm, transformed_key->key, 397 + ret = nvme_auth_hmac_init(&hmac, ctrl->shash_id, transformed_key->key, 412 398 transformed_key->len); 413 399 if (ret) 414 400 goto out_free_response; 401 + 402 + if (shash_len != nvme_auth_hmac_hash_len(ctrl->shash_id)) { 403 + pr_err("%s: hash len mismatch (len %u digest %zu)\n", __func__, 404 + shash_len, nvme_auth_hmac_hash_len(ctrl->shash_id)); 405 + ret = -EINVAL; 406 + goto out_free_response; 407 + } 415 408 416 409 if (ctrl->dh_gid != NVME_AUTH_DHGROUP_NULL) { 417 410 challenge = kmalloc(shash_len, GFP_KERNEL); ··· 394 455 goto out_free_challenge; 395 456 } 396 457 397 - shash = kzalloc(sizeof(*shash) + crypto_shash_descsize(shash_tfm), 398 - GFP_KERNEL); 399 - if (!shash) { 400 - ret = -ENOMEM; 401 - goto out_free_challenge; 402 - } 403 - shash->tfm = shash_tfm; 458 + nvme_auth_hmac_update(&hmac, challenge, shash_len); 404 459 405 - ret = crypto_shash_init(shash); 406 - if (ret) 407 - goto out; 408 - ret = crypto_shash_update(shash, challenge, shash_len); 409 - if (ret) 410 - goto out; 411 460 put_unaligned_le32(req->sq->dhchap_s2, buf); 412 - ret = crypto_shash_update(shash, buf, 4); 413 - if (ret) 414 - goto out; 461 + nvme_auth_hmac_update(&hmac, buf, 4); 462 + 415 463 put_unaligned_le16(req->sq->dhchap_tid, buf); 416 - ret = crypto_shash_update(shash, buf, 2); 417 - if (ret) 418 - goto out; 464 + nvme_auth_hmac_update(&hmac, buf, 2); 465 + 419 466 memset(buf, 0, 4); 420 - ret = crypto_shash_update(shash, buf, 1); 421 - if (ret) 422 - goto out; 423 - ret = crypto_shash_update(shash, "Controller", 10); 424 - if (ret) 425 - goto out; 426 - ret = crypto_shash_update(shash, ctrl->subsys->subsysnqn, 427 - strlen(ctrl->subsys->subsysnqn)); 428 - if (ret) 429 - goto out; 430 - ret = crypto_shash_update(shash, buf, 1); 431 - if (ret) 432 - goto out; 433 - ret = crypto_shash_update(shash, ctrl->hostnqn, strlen(ctrl->hostnqn)); 434 - if (ret) 435 - goto out; 436 - ret = crypto_shash_final(shash, response); 437 - out: 438 - kfree(shash); 467 + nvme_auth_hmac_update(&hmac, buf, 1); 468 + nvme_auth_hmac_update(&hmac, "Controller", 10); 469 + nvme_auth_hmac_update(&hmac, ctrl->subsys->subsysnqn, 470 + strlen(ctrl->subsys->subsysnqn)); 471 + nvme_auth_hmac_update(&hmac, buf, 1); 472 + nvme_auth_hmac_update(&hmac, ctrl->hostnqn, strlen(ctrl->hostnqn)); 473 + nvme_auth_hmac_final(&hmac, response); 474 + ret = 0; 439 475 out_free_challenge: 440 476 if (challenge != req->sq->dhchap_c2) 441 477 kfree(challenge); 442 478 out_free_response: 479 + memzero_explicit(&hmac, sizeof(hmac)); 443 480 nvme_auth_free_key(transformed_key); 444 - out_free_tfm: 445 - crypto_free_shash(shash_tfm); 446 481 return ret; 447 482 } 448 483 ··· 444 531 } 445 532 446 533 int nvmet_auth_ctrl_sesskey(struct nvmet_req *req, 447 - u8 *pkey, int pkey_size) 534 + const u8 *pkey, int pkey_size) 448 535 { 449 536 struct nvmet_ctrl *ctrl = req->sq->ctrl; 450 537 int ret; ··· 470 557 void nvmet_auth_insert_psk(struct nvmet_sq *sq) 471 558 { 472 559 int hash_len = nvme_auth_hmac_hash_len(sq->ctrl->shash_id); 473 - u8 *psk, *digest, *tls_psk; 560 + u8 *psk, *tls_psk; 561 + char *digest; 474 562 size_t psk_len; 475 563 int ret; 476 564 #ifdef CONFIG_NVME_TARGET_TCP_TLS
-3
drivers/nvme/target/configfs.c
··· 17 17 #include <linux/nvme-auth.h> 18 18 #endif 19 19 #include <linux/nvme-keyring.h> 20 - #include <crypto/hash.h> 21 20 #include <crypto/kpp.h> 22 21 #include <linux/nospec.h> 23 22 ··· 2180 2181 hmac_id = nvme_auth_hmac_id(page); 2181 2182 if (hmac_id == NVME_AUTH_HASH_INVALID) 2182 2183 return -EINVAL; 2183 - if (!crypto_has_shash(nvme_auth_hmac_name(hmac_id), 0, 0)) 2184 - return -ENOTSUPP; 2185 2184 host->dhchap_hash_id = hmac_id; 2186 2185 return count; 2187 2186 }
+4 -3
drivers/nvme/target/core.c
··· 1686 1686 if (args->hostid) 1687 1687 uuid_copy(&ctrl->hostid, args->hostid); 1688 1688 1689 - dhchap_status = nvmet_setup_auth(ctrl, args->sq); 1689 + dhchap_status = nvmet_setup_auth(ctrl, args->sq, false); 1690 1690 if (dhchap_status) { 1691 1691 pr_err("Failed to setup authentication, dhchap status %u\n", 1692 1692 dhchap_status); ··· 1942 1942 if (!nvmet_bvec_cache) 1943 1943 return -ENOMEM; 1944 1944 1945 - zbd_wq = alloc_workqueue("nvmet-zbd-wq", WQ_MEM_RECLAIM, 0); 1945 + zbd_wq = alloc_workqueue("nvmet-zbd-wq", WQ_MEM_RECLAIM | WQ_PERCPU, 1946 + 0); 1946 1947 if (!zbd_wq) 1947 1948 goto out_destroy_bvec_cache; 1948 1949 1949 1950 buffered_io_wq = alloc_workqueue("nvmet-buffered-io-wq", 1950 - WQ_MEM_RECLAIM, 0); 1951 + WQ_MEM_RECLAIM | WQ_PERCPU, 0); 1951 1952 if (!buffered_io_wq) 1952 1953 goto out_free_zbd_work_queue; 1953 1954
+8 -10
drivers/nvme/target/fabrics-cmd-auth.c
··· 8 8 #include <linux/blkdev.h> 9 9 #include <linux/random.h> 10 10 #include <linux/nvme-auth.h> 11 - #include <crypto/hash.h> 12 11 #include <crypto/kpp.h> 13 12 #include "nvmet.h" 14 13 ··· 74 75 for (i = 0; i < data->auth_protocol[0].dhchap.halen; i++) { 75 76 u8 host_hmac_id = data->auth_protocol[0].dhchap.idlist[i]; 76 77 77 - if (!fallback_hash_id && 78 - crypto_has_shash(nvme_auth_hmac_name(host_hmac_id), 0, 0)) 78 + if (!fallback_hash_id && nvme_auth_hmac_hash_len(host_hmac_id)) 79 79 fallback_hash_id = host_hmac_id; 80 80 if (ctrl->shash_id != host_hmac_id) 81 81 continue; ··· 291 293 pr_debug("%s: ctrl %d qid %d reset negotiation\n", 292 294 __func__, ctrl->cntlid, req->sq->qid); 293 295 if (!req->sq->qid) { 294 - dhchap_status = nvmet_setup_auth(ctrl, req->sq); 296 + dhchap_status = nvmet_setup_auth(ctrl, req->sq, 297 + true); 295 298 if (dhchap_status) { 296 299 pr_err("ctrl %d qid 0 failed to setup re-authentication\n", 297 300 ctrl->cntlid); ··· 390 391 req->sq->dhchap_step != NVME_AUTH_DHCHAP_MESSAGE_FAILURE2) { 391 392 unsigned long auth_expire_secs = ctrl->kato ? ctrl->kato : 120; 392 393 393 - mod_delayed_work(system_wq, &req->sq->auth_expired_work, 394 + mod_delayed_work(system_percpu_wq, &req->sq->auth_expired_work, 394 395 auth_expire_secs * HZ); 395 396 goto complete; 396 397 } 397 398 /* Final states, clear up variables */ 398 - nvmet_auth_sq_free(req->sq); 399 - if (req->sq->dhchap_step == NVME_AUTH_DHCHAP_MESSAGE_FAILURE2) 399 + if (req->sq->dhchap_step == NVME_AUTH_DHCHAP_MESSAGE_FAILURE2) { 400 + nvmet_auth_sq_free(req->sq); 400 401 nvmet_ctrl_fatal_error(ctrl); 402 + } 401 403 402 404 complete: 403 405 nvmet_req_complete(req, status); ··· 574 574 status = nvmet_copy_to_sgl(req, 0, d, al); 575 575 kfree(d); 576 576 done: 577 - if (req->sq->dhchap_step == NVME_AUTH_DHCHAP_MESSAGE_SUCCESS2) 578 - nvmet_auth_sq_free(req->sq); 579 - else if (req->sq->dhchap_step == NVME_AUTH_DHCHAP_MESSAGE_FAILURE1) { 577 + if (req->sq->dhchap_step == NVME_AUTH_DHCHAP_MESSAGE_FAILURE1) { 580 578 nvmet_auth_sq_free(req->sq); 581 579 nvmet_ctrl_fatal_error(ctrl); 582 580 }
+3 -3
drivers/nvme/target/fc.c
··· 792 792 if (!queue) 793 793 return NULL; 794 794 795 - queue->work_q = alloc_workqueue("ntfc%d.%d.%d", 0, 0, 796 - assoc->tgtport->fc_target_port.port_num, 797 - assoc->a_id, qid); 795 + queue->work_q = alloc_workqueue("ntfc%d.%d.%d", WQ_PERCPU, 0, 796 + assoc->tgtport->fc_target_port.port_num, 797 + assoc->a_id, qid); 798 798 if (!queue->work_q) 799 799 goto out_free_queue; 800 800
+15 -4
drivers/nvme/target/io-cmd-bdev.c
··· 30 30 id->nacwu = lpp0b; 31 31 32 32 /* 33 - * Bit 4 indicates that the fields NPWG, NPWA, NPDG, NPDA, and 34 - * NOWS are defined for this namespace and should be used by 35 - * the host for I/O optimization. 33 + * OPTPERF = 11b indicates that the fields NPWG, NPWA, NPDG, NPDA, 34 + * NPDGL, NPDAL, and NOWS are defined for this namespace and should be 35 + * used by the host for I/O optimization. 36 36 */ 37 - id->nsfeat |= 1 << 4; 37 + id->nsfeat |= 0x3 << NVME_NS_FEAT_OPTPERF_SHIFT; 38 38 /* NPWG = Namespace Preferred Write Granularity. 0's based */ 39 39 id->npwg = to0based(bdev_io_min(bdev) / bdev_logical_block_size(bdev)); 40 40 /* NPWA = Namespace Preferred Write Alignment. 0's based */ ··· 50 50 /* Set WZDS and DRB if device supports unmapped write zeroes */ 51 51 if (bdev_write_zeroes_unmap_sectors(bdev)) 52 52 id->dlfeat = (1 << 3) | 0x1; 53 + } 54 + 55 + void nvmet_bdev_set_nvm_limits(struct block_device *bdev, 56 + struct nvme_id_ns_nvm *id) 57 + { 58 + /* 59 + * NPDGL = Namespace Preferred Deallocate Granularity Large 60 + * NPDAL = Namespace Preferred Deallocate Alignment Large 61 + */ 62 + id->npdgl = id->npdal = cpu_to_le32(bdev_discard_granularity(bdev) / 63 + bdev_logical_block_size(bdev)); 53 64 } 54 65 55 66 void nvmet_bdev_ns_disable(struct nvmet_ns *ns)
-2
drivers/nvme/target/loop.c
··· 419 419 { 420 420 if (ctrl->ctrl.queue_count > 1) { 421 421 nvme_quiesce_io_queues(&ctrl->ctrl); 422 - nvme_cancel_tagset(&ctrl->ctrl); 423 422 nvme_loop_destroy_io_queues(ctrl); 424 423 } 425 424 ··· 426 427 if (nvme_ctrl_state(&ctrl->ctrl) == NVME_CTRL_LIVE) 427 428 nvme_disable_ctrl(&ctrl->ctrl, true); 428 429 429 - nvme_cancel_admin_tagset(&ctrl->ctrl); 430 430 nvme_loop_destroy_admin_queue(ctrl); 431 431 } 432 432
+5 -3
drivers/nvme/target/nvmet.h
··· 549 549 u16 nvmet_parse_connect_cmd(struct nvmet_req *req); 550 550 u32 nvmet_connect_cmd_data_len(struct nvmet_req *req); 551 551 void nvmet_bdev_set_limits(struct block_device *bdev, struct nvme_id_ns *id); 552 + void nvmet_bdev_set_nvm_limits(struct block_device *bdev, 553 + struct nvme_id_ns_nvm *id); 552 554 u16 nvmet_bdev_parse_io_cmd(struct nvmet_req *req); 553 555 u16 nvmet_file_parse_io_cmd(struct nvmet_req *req); 554 556 u16 nvmet_bdev_zns_parse_io_cmd(struct nvmet_req *req); ··· 897 895 int nvmet_auth_set_key(struct nvmet_host *host, const char *secret, 898 896 bool set_ctrl); 899 897 int nvmet_auth_set_host_hash(struct nvmet_host *host, const char *hash); 900 - u8 nvmet_setup_auth(struct nvmet_ctrl *ctrl, struct nvmet_sq *sq); 898 + u8 nvmet_setup_auth(struct nvmet_ctrl *ctrl, struct nvmet_sq *sq, bool reset); 901 899 void nvmet_auth_sq_init(struct nvmet_sq *sq); 902 900 void nvmet_destroy_auth(struct nvmet_ctrl *ctrl); 903 901 void nvmet_auth_sq_free(struct nvmet_sq *sq); ··· 914 912 int nvmet_auth_ctrl_exponential(struct nvmet_req *req, 915 913 u8 *buf, int buf_size); 916 914 int nvmet_auth_ctrl_sesskey(struct nvmet_req *req, 917 - u8 *buf, int buf_size); 915 + const u8 *pkey, int pkey_size); 918 916 void nvmet_auth_insert_psk(struct nvmet_sq *sq); 919 917 #else 920 918 static inline u8 nvmet_setup_auth(struct nvmet_ctrl *ctrl, 921 - struct nvmet_sq *sq) 919 + struct nvmet_sq *sq, bool reset) 922 920 { 923 921 return 0; 924 922 }
+1 -1
drivers/nvme/target/tcp.c
··· 2225 2225 int ret; 2226 2226 2227 2227 nvmet_tcp_wq = alloc_workqueue("nvmet_tcp_wq", 2228 - WQ_MEM_RECLAIM | WQ_HIGHPRI, 0); 2228 + WQ_MEM_RECLAIM | WQ_HIGHPRI | WQ_PERCPU, 0); 2229 2229 if (!nvmet_tcp_wq) 2230 2230 return -ENOMEM; 2231 2231
-20
include/crypto/hkdf.h
··· 1 - /* SPDX-License-Identifier: GPL-2.0 */ 2 - /* 3 - * HKDF: HMAC-based Key Derivation Function (HKDF), RFC 5869 4 - * 5 - * Extracted from fs/crypto/hkdf.c, which has 6 - * Copyright 2019 Google LLC 7 - */ 8 - 9 - #ifndef _CRYPTO_HKDF_H 10 - #define _CRYPTO_HKDF_H 11 - 12 - #include <crypto/hash.h> 13 - 14 - int hkdf_extract(struct crypto_shash *hmac_tfm, const u8 *ikm, 15 - unsigned int ikmlen, const u8 *salt, unsigned int saltlen, 16 - u8 *prk); 17 - int hkdf_expand(struct crypto_shash *hmac_tfm, 18 - const u8 *info, unsigned int infolen, 19 - u8 *okm, unsigned int okmlen); 20 - #endif
+27 -14
include/linux/nvme-auth.h
··· 7 7 #define _NVME_AUTH_H 8 8 9 9 #include <crypto/kpp.h> 10 + #include <crypto/sha2.h> 10 11 11 12 struct nvme_dhchap_key { 12 13 size_t len; ··· 21 20 u8 nvme_auth_dhgroup_id(const char *dhgroup_name); 22 21 23 22 const char *nvme_auth_hmac_name(u8 hmac_id); 24 - const char *nvme_auth_digest_name(u8 hmac_id); 25 23 size_t nvme_auth_hmac_hash_len(u8 hmac_id); 26 24 u8 nvme_auth_hmac_id(const char *hmac_name); 25 + struct nvme_auth_hmac_ctx { 26 + u8 hmac_id; 27 + union { 28 + struct hmac_sha256_ctx sha256; 29 + struct hmac_sha384_ctx sha384; 30 + struct hmac_sha512_ctx sha512; 31 + }; 32 + }; 33 + int nvme_auth_hmac_init(struct nvme_auth_hmac_ctx *hmac, u8 hmac_id, 34 + const u8 *key, size_t key_len); 35 + void nvme_auth_hmac_update(struct nvme_auth_hmac_ctx *hmac, const u8 *data, 36 + size_t data_len); 37 + void nvme_auth_hmac_final(struct nvme_auth_hmac_ctx *hmac, u8 *out); 27 38 28 39 u32 nvme_auth_key_struct_size(u32 key_len); 29 - struct nvme_dhchap_key *nvme_auth_extract_key(unsigned char *secret, 30 - u8 key_hash); 40 + struct nvme_dhchap_key *nvme_auth_extract_key(const char *secret, u8 key_hash); 31 41 void nvme_auth_free_key(struct nvme_dhchap_key *key); 32 42 struct nvme_dhchap_key *nvme_auth_alloc_key(u32 len, u8 hash); 33 43 struct nvme_dhchap_key *nvme_auth_transform_key( 34 - struct nvme_dhchap_key *key, char *nqn); 35 - int nvme_auth_generate_key(u8 *secret, struct nvme_dhchap_key **ret_key); 36 - int nvme_auth_augmented_challenge(u8 hmac_id, u8 *skey, size_t skey_len, 37 - u8 *challenge, u8 *aug, size_t hlen); 44 + const struct nvme_dhchap_key *key, const char *nqn); 45 + int nvme_auth_parse_key(const char *secret, struct nvme_dhchap_key **ret_key); 46 + int nvme_auth_augmented_challenge(u8 hmac_id, const u8 *skey, size_t skey_len, 47 + const u8 *challenge, u8 *aug, size_t hlen); 38 48 int nvme_auth_gen_privkey(struct crypto_kpp *dh_tfm, u8 dh_gid); 39 49 int nvme_auth_gen_pubkey(struct crypto_kpp *dh_tfm, 40 50 u8 *host_key, size_t host_key_len); 41 51 int nvme_auth_gen_shared_secret(struct crypto_kpp *dh_tfm, 42 - u8 *ctrl_key, size_t ctrl_key_len, 52 + const u8 *ctrl_key, size_t ctrl_key_len, 43 53 u8 *sess_key, size_t sess_key_len); 44 - int nvme_auth_generate_psk(u8 hmac_id, u8 *skey, size_t skey_len, 45 - u8 *c1, u8 *c2, size_t hash_len, 54 + int nvme_auth_generate_psk(u8 hmac_id, const u8 *skey, size_t skey_len, 55 + const u8 *c1, const u8 *c2, size_t hash_len, 46 56 u8 **ret_psk, size_t *ret_len); 47 - int nvme_auth_generate_digest(u8 hmac_id, u8 *psk, size_t psk_len, 48 - char *subsysnqn, char *hostnqn, u8 **ret_digest); 49 - int nvme_auth_derive_tls_psk(int hmac_id, u8 *psk, size_t psk_len, 50 - u8 *psk_digest, u8 **ret_psk); 57 + int nvme_auth_generate_digest(u8 hmac_id, const u8 *psk, size_t psk_len, 58 + const char *subsysnqn, const char *hostnqn, 59 + char **ret_digest); 60 + int nvme_auth_derive_tls_psk(int hmac_id, const u8 *psk, size_t psk_len, 61 + const char *psk_digest, u8 **ret_psk); 51 62 52 63 #endif /* _NVME_AUTH_H */
+22 -2
include/linux/nvme.h
··· 513 513 __u8 pic; 514 514 __u8 rsvd9[3]; 515 515 __le32 elbaf[64]; 516 - __u8 rsvd268[3828]; 516 + __le32 npdgl; 517 + __le32 nprg; 518 + __le32 npra; 519 + __le32 nors; 520 + __le32 npdal; 521 + __u8 rsvd288[3808]; 517 522 }; 523 + 524 + static_assert(sizeof(struct nvme_id_ns_nvm) == 4096); 518 525 519 526 enum { 520 527 NVME_ID_NS_NVM_STS_MASK = 0x7f, ··· 597 590 enum { 598 591 NVME_NS_FEAT_THIN = 1 << 0, 599 592 NVME_NS_FEAT_ATOMICS = 1 << 1, 600 - NVME_NS_FEAT_IO_OPT = 1 << 4, 593 + NVME_NS_FEAT_OPTPERF_SHIFT = 4, 594 + /* In NVMe version 2.0 and below, OPTPERF is only bit 4 of NSFEAT */ 595 + NVME_NS_FEAT_OPTPERF_MASK = 0x1, 596 + /* Since version 2.1, OPTPERF is bits 4 and 5 of NSFEAT */ 597 + NVME_NS_FEAT_OPTPERF_MASK_2_1 = 0x3, 601 598 NVME_NS_ATTR_RO = 1 << 0, 602 599 NVME_NS_FLBAS_LBA_MASK = 0xf, 603 600 NVME_NS_FLBAS_LBA_UMASK = 0x60, ··· 1848 1837 NVME_AUTH_HASH_INVALID = 0xff, 1849 1838 }; 1850 1839 1840 + /* Maximum digest size for any NVME_AUTH_HASH_* value */ 1841 + enum { 1842 + NVME_AUTH_MAX_DIGEST_SIZE = 64, 1843 + }; 1844 + 1851 1845 /* Defined Diffie-Hellman group identifiers for DH-HMAC-CHAP authentication */ 1852 1846 enum { 1853 1847 NVME_AUTH_DHGROUP_NULL = 0x00, ··· 2347 2331 }; 2348 2332 2349 2333 #define NVME_PR_IGNORE_KEY (1 << 3) 2334 + 2335 + /* Section 8.3.4.5.2 of the NVMe 2.1 */ 2336 + #define NVME_AUTH_DHCHAP_MAX_HASH_IDS 30 2337 + #define NVME_AUTH_DHCHAP_MAX_DH_IDS 30 2350 2338 2351 2339 #endif /* _LINUX_NVME_H */