1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (c) 2023 Hannes Reinecke, SUSE Labs 4 */ 5 6 #include <linux/module.h> 7 #include <linux/seq_file.h> 8 #include <linux/key.h> 9 #include <linux/key-type.h> 10 #include <keys/user-type.h> 11 #include <linux/nvme.h> 12 #include <linux/nvme-tcp.h> 13 #include <linux/nvme-keyring.h> 14 15 static struct key *nvme_keyring; 16 17 key_serial_t nvme_keyring_id(void) 18 { 19 return nvme_keyring->serial; 20 } 21 EXPORT_SYMBOL_GPL(nvme_keyring_id); 22 23 static bool nvme_tls_psk_revoked(struct key *psk) 24 { 25 return test_bit(KEY_FLAG_REVOKED, &psk->flags) || 26 test_bit(KEY_FLAG_INVALIDATED, &psk->flags); 27 } 28 29 struct key *nvme_tls_key_lookup(key_serial_t key_id) 30 { 31 struct key *key = key_lookup(key_id); 32 33 if (IS_ERR(key)) { 34 pr_err("key id %08x not found\n", key_id); 35 return key; 36 } 37 if (nvme_tls_psk_revoked(key)) { 38 pr_err("key id %08x revoked\n", key_id); 39 return ERR_PTR(-EKEYREVOKED); 40 } 41 return key; 42 } 43 EXPORT_SYMBOL_GPL(nvme_tls_key_lookup); 44 45 static void nvme_tls_psk_describe(const struct key *key, struct seq_file *m) 46 { 47 seq_puts(m, key->description); 48 seq_printf(m, ": %u", key->datalen); 49 } 50 51 static bool nvme_tls_psk_match(const struct key *key, 52 const struct key_match_data *match_data) 53 { 54 const char *match_id; 55 size_t match_len; 56 57 if (!key->description) { 58 pr_debug("%s: no key description\n", __func__); 59 return false; 60 } 61 if (!match_data->raw_data) { 62 pr_debug("%s: no match data\n", __func__); 63 return false; 64 } 65 match_id = match_data->raw_data; 66 match_len = strlen(match_id); 67 pr_debug("%s: match '%s' '%s' len %zd\n", 68 __func__, match_id, key->description, match_len); 69 return !memcmp(key->description, match_id, match_len); 70 } 71 72 static int nvme_tls_psk_match_preparse(struct key_match_data *match_data) 73 { 74 match_data->lookup_type = KEYRING_SEARCH_LOOKUP_ITERATE; 75 match_data->cmp = nvme_tls_psk_match; 76 return 0; 77 } 78 79 static struct key_type nvme_tls_psk_key_type = { 80 .name = "psk", 81 .flags = KEY_TYPE_NET_DOMAIN, 82 .preparse = user_preparse, 83 .free_preparse = user_free_preparse, 84 .match_preparse = nvme_tls_psk_match_preparse, 85 .instantiate = generic_key_instantiate, 86 .revoke = user_revoke, 87 .destroy = user_destroy, 88 .describe = nvme_tls_psk_describe, 89 .read = user_read, 90 }; 91 92 static struct key *nvme_tls_psk_lookup(struct key *keyring, 93 const char *hostnqn, const char *subnqn, 94 u8 hmac, u8 psk_ver, bool generated) 95 { 96 char *identity; 97 size_t identity_len = (NVMF_NQN_SIZE) * 2 + 11; 98 key_ref_t keyref; 99 key_serial_t keyring_id; 100 101 identity = kzalloc(identity_len, GFP_KERNEL); 102 if (!identity) 103 return ERR_PTR(-ENOMEM); 104 105 snprintf(identity, identity_len, "NVMe%u%c%02u %s %s", 106 psk_ver, generated ? 'G' : 'R', hmac, hostnqn, subnqn); 107 108 if (!keyring) 109 keyring = nvme_keyring; 110 keyring_id = key_serial(keyring); 111 pr_debug("keyring %x lookup tls psk '%s'\n", 112 keyring_id, identity); 113 keyref = keyring_search(make_key_ref(keyring, true), 114 &nvme_tls_psk_key_type, 115 identity, false); 116 if (IS_ERR(keyref)) { 117 pr_debug("lookup tls psk '%s' failed, error %ld\n", 118 identity, PTR_ERR(keyref)); 119 kfree(identity); 120 return ERR_PTR(-ENOKEY); 121 } 122 kfree(identity); 123 124 return key_ref_to_ptr(keyref); 125 } 126 127 /* 128 * NVMe PSK priority list 129 * 130 * 'Retained' PSKs (ie 'generated == false') should be preferred to 'generated' 131 * PSKs, PSKs with hash (psk_ver 1) should be preferred to PSKs without hash 132 * (psk_ver 0), and SHA-384 should be preferred to SHA-256. 133 */ 134 static struct nvme_tls_psk_priority_list { 135 bool generated; 136 u8 psk_ver; 137 enum nvme_tcp_tls_cipher cipher; 138 } nvme_tls_psk_prio[] = { 139 { .generated = false, 140 .psk_ver = 1, 141 .cipher = NVME_TCP_TLS_CIPHER_SHA384, }, 142 { .generated = false, 143 .psk_ver = 1, 144 .cipher = NVME_TCP_TLS_CIPHER_SHA256, }, 145 { .generated = false, 146 .psk_ver = 0, 147 .cipher = NVME_TCP_TLS_CIPHER_SHA384, }, 148 { .generated = false, 149 .psk_ver = 0, 150 .cipher = NVME_TCP_TLS_CIPHER_SHA256, }, 151 { .generated = true, 152 .psk_ver = 1, 153 .cipher = NVME_TCP_TLS_CIPHER_SHA384, }, 154 { .generated = true, 155 .psk_ver = 1, 156 .cipher = NVME_TCP_TLS_CIPHER_SHA256, }, 157 { .generated = true, 158 .psk_ver = 0, 159 .cipher = NVME_TCP_TLS_CIPHER_SHA384, }, 160 { .generated = true, 161 .psk_ver = 0, 162 .cipher = NVME_TCP_TLS_CIPHER_SHA256, }, 163 }; 164 165 /* 166 * nvme_tls_psk_default - Return the preferred PSK to use for TLS ClientHello 167 */ 168 key_serial_t nvme_tls_psk_default(struct key *keyring, 169 const char *hostnqn, const char *subnqn) 170 { 171 struct key *tls_key; 172 key_serial_t tls_key_id; 173 int prio; 174 175 for (prio = 0; prio < ARRAY_SIZE(nvme_tls_psk_prio); prio++) { 176 bool generated = nvme_tls_psk_prio[prio].generated; 177 u8 ver = nvme_tls_psk_prio[prio].psk_ver; 178 enum nvme_tcp_tls_cipher cipher = nvme_tls_psk_prio[prio].cipher; 179 180 tls_key = nvme_tls_psk_lookup(keyring, hostnqn, subnqn, 181 cipher, ver, generated); 182 if (!IS_ERR(tls_key)) { 183 tls_key_id = tls_key->serial; 184 key_put(tls_key); 185 return tls_key_id; 186 } 187 } 188 return 0; 189 } 190 EXPORT_SYMBOL_GPL(nvme_tls_psk_default); 191 192 static int __init nvme_keyring_init(void) 193 { 194 int err; 195 196 nvme_keyring = keyring_alloc(".nvme", 197 GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, 198 current_cred(), 199 (KEY_POS_ALL & ~KEY_POS_SETATTR) | 200 (KEY_USR_ALL & ~KEY_USR_SETATTR), 201 KEY_ALLOC_NOT_IN_QUOTA, NULL, NULL); 202 if (IS_ERR(nvme_keyring)) 203 return PTR_ERR(nvme_keyring); 204 205 err = register_key_type(&nvme_tls_psk_key_type); 206 if (err) { 207 key_put(nvme_keyring); 208 return err; 209 } 210 return 0; 211 } 212 213 static void __exit nvme_keyring_exit(void) 214 { 215 unregister_key_type(&nvme_tls_psk_key_type); 216 key_revoke(nvme_keyring); 217 key_put(nvme_keyring); 218 } 219 220 MODULE_LICENSE("GPL v2"); 221 MODULE_AUTHOR("Hannes Reinecke <hare@suse.de>"); 222 MODULE_DESCRIPTION("NVMe Keyring implementation"); 223 module_init(nvme_keyring_init); 224 module_exit(nvme_keyring_exit); 225