xref: /linux/drivers/nvme/common/keyring.c (revision 26bb0d3f38a764b743a3ad5c8b6e5b5044d7ceb4)
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 
nvme_keyring_id(void)17 key_serial_t nvme_keyring_id(void)
18 {
19 	return nvme_keyring->serial;
20 }
21 EXPORT_SYMBOL_GPL(nvme_keyring_id);
22 
nvme_tls_psk_revoked(struct key * psk)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 
nvme_tls_key_lookup(key_serial_t key_id)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 
nvme_tls_psk_describe(const struct key * key,struct seq_file * m)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 
nvme_tls_psk_match(const struct key * key,const struct key_match_data * match_data)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 
nvme_tls_psk_match_preparse(struct key_match_data * match_data)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 
nvme_tls_psk_lookup(struct key * keyring,const char * hostnqn,const char * subnqn,u8 hmac,u8 psk_ver,bool generated)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  */
nvme_tls_psk_default(struct key * keyring,const char * hostnqn,const char * subnqn)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 
nvme_keyring_init(void)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 
nvme_keyring_exit(void)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