GNU Linux-libre 6.7.9-gnu
[releases.git] / drivers / nvme / common / keyring.c
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 void nvme_tls_psk_describe(const struct key *key, struct seq_file *m)
24 {
25         seq_puts(m, key->description);
26         seq_printf(m, ": %u", key->datalen);
27 }
28
29 static bool nvme_tls_psk_match(const struct key *key,
30                                const struct key_match_data *match_data)
31 {
32         const char *match_id;
33         size_t match_len;
34
35         if (!key->description) {
36                 pr_debug("%s: no key description\n", __func__);
37                 return false;
38         }
39         match_len = strlen(key->description);
40         pr_debug("%s: id %s len %zd\n", __func__, key->description, match_len);
41
42         if (!match_data->raw_data) {
43                 pr_debug("%s: no match data\n", __func__);
44                 return false;
45         }
46         match_id = match_data->raw_data;
47         pr_debug("%s: match '%s' '%s' len %zd\n",
48                  __func__, match_id, key->description, match_len);
49         return !memcmp(key->description, match_id, match_len);
50 }
51
52 static int nvme_tls_psk_match_preparse(struct key_match_data *match_data)
53 {
54         match_data->lookup_type = KEYRING_SEARCH_LOOKUP_ITERATE;
55         match_data->cmp = nvme_tls_psk_match;
56         return 0;
57 }
58
59 static struct key_type nvme_tls_psk_key_type = {
60         .name           = "psk",
61         .flags          = KEY_TYPE_NET_DOMAIN,
62         .preparse       = user_preparse,
63         .free_preparse  = user_free_preparse,
64         .match_preparse = nvme_tls_psk_match_preparse,
65         .instantiate    = generic_key_instantiate,
66         .revoke         = user_revoke,
67         .destroy        = user_destroy,
68         .describe       = nvme_tls_psk_describe,
69         .read           = user_read,
70 };
71
72 static struct key *nvme_tls_psk_lookup(struct key *keyring,
73                 const char *hostnqn, const char *subnqn,
74                 int hmac, bool generated)
75 {
76         char *identity;
77         size_t identity_len = (NVMF_NQN_SIZE) * 2 + 11;
78         key_ref_t keyref;
79         key_serial_t keyring_id;
80
81         identity = kzalloc(identity_len, GFP_KERNEL);
82         if (!identity)
83                 return ERR_PTR(-ENOMEM);
84
85         snprintf(identity, identity_len, "NVMe0%c%02d %s %s",
86                  generated ? 'G' : 'R', hmac, hostnqn, subnqn);
87
88         if (!keyring)
89                 keyring = nvme_keyring;
90         keyring_id = key_serial(keyring);
91         pr_debug("keyring %x lookup tls psk '%s'\n",
92                  keyring_id, identity);
93         keyref = keyring_search(make_key_ref(keyring, true),
94                                 &nvme_tls_psk_key_type,
95                                 identity, false);
96         if (IS_ERR(keyref)) {
97                 pr_debug("lookup tls psk '%s' failed, error %ld\n",
98                          identity, PTR_ERR(keyref));
99                 kfree(identity);
100                 return ERR_PTR(-ENOKEY);
101         }
102         kfree(identity);
103
104         return key_ref_to_ptr(keyref);
105 }
106
107 /*
108  * NVMe PSK priority list
109  *
110  * 'Retained' PSKs (ie 'generated == false')
111  * should be preferred to 'generated' PSKs,
112  * and SHA-384 should be preferred to SHA-256.
113  */
114 struct nvme_tls_psk_priority_list {
115         bool generated;
116         enum nvme_tcp_tls_cipher cipher;
117 } nvme_tls_psk_prio[] = {
118         { .generated = false,
119           .cipher = NVME_TCP_TLS_CIPHER_SHA384, },
120         { .generated = false,
121           .cipher = NVME_TCP_TLS_CIPHER_SHA256, },
122         { .generated = true,
123           .cipher = NVME_TCP_TLS_CIPHER_SHA384, },
124         { .generated = true,
125           .cipher = NVME_TCP_TLS_CIPHER_SHA256, },
126 };
127
128 /*
129  * nvme_tls_psk_default - Return the preferred PSK to use for TLS ClientHello
130  */
131 key_serial_t nvme_tls_psk_default(struct key *keyring,
132                       const char *hostnqn, const char *subnqn)
133 {
134         struct key *tls_key;
135         key_serial_t tls_key_id;
136         int prio;
137
138         for (prio = 0; prio < ARRAY_SIZE(nvme_tls_psk_prio); prio++) {
139                 bool generated = nvme_tls_psk_prio[prio].generated;
140                 enum nvme_tcp_tls_cipher cipher = nvme_tls_psk_prio[prio].cipher;
141
142                 tls_key = nvme_tls_psk_lookup(keyring, hostnqn, subnqn,
143                                               cipher, generated);
144                 if (!IS_ERR(tls_key)) {
145                         tls_key_id = tls_key->serial;
146                         key_put(tls_key);
147                         return tls_key_id;
148                 }
149         }
150         return 0;
151 }
152 EXPORT_SYMBOL_GPL(nvme_tls_psk_default);
153
154 static int __init nvme_keyring_init(void)
155 {
156         int err;
157
158         nvme_keyring = keyring_alloc(".nvme",
159                                      GLOBAL_ROOT_UID, GLOBAL_ROOT_GID,
160                                      current_cred(),
161                                      (KEY_POS_ALL & ~KEY_POS_SETATTR) |
162                                      (KEY_USR_ALL & ~KEY_USR_SETATTR),
163                                      KEY_ALLOC_NOT_IN_QUOTA, NULL, NULL);
164         if (IS_ERR(nvme_keyring))
165                 return PTR_ERR(nvme_keyring);
166
167         err = register_key_type(&nvme_tls_psk_key_type);
168         if (err) {
169                 key_put(nvme_keyring);
170                 return err;
171         }
172         return 0;
173 }
174
175 static void __exit nvme_keyring_exit(void)
176 {
177         unregister_key_type(&nvme_tls_psk_key_type);
178         key_revoke(nvme_keyring);
179         key_put(nvme_keyring);
180 }
181
182 MODULE_LICENSE("GPL v2");
183 MODULE_AUTHOR("Hannes Reinecke <hare@suse.de>");
184 module_init(nvme_keyring_init);
185 module_exit(nvme_keyring_exit);