1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2023 Hannes Reinecke, SUSE Labs
6 #include <linux/module.h>
7 #include <linux/seq_file.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>
15 static struct key
*nvme_keyring
;
17 key_serial_t
nvme_keyring_id(void)
19 return nvme_keyring
->serial
;
21 EXPORT_SYMBOL_GPL(nvme_keyring_id
);
23 static bool nvme_tls_psk_revoked(struct key
*psk
)
25 return test_bit(KEY_FLAG_REVOKED
, &psk
->flags
) ||
26 test_bit(KEY_FLAG_INVALIDATED
, &psk
->flags
);
29 struct key
*nvme_tls_key_lookup(key_serial_t key_id
)
31 struct key
*key
= key_lookup(key_id
);
34 pr_err("key id %08x not found\n", key_id
);
37 if (nvme_tls_psk_revoked(key
)) {
38 pr_err("key id %08x revoked\n", key_id
);
39 return ERR_PTR(-EKEYREVOKED
);
43 EXPORT_SYMBOL_GPL(nvme_tls_key_lookup
);
45 static void nvme_tls_psk_describe(const struct key
*key
, struct seq_file
*m
)
47 seq_puts(m
, key
->description
);
48 seq_printf(m
, ": %u", key
->datalen
);
51 static bool nvme_tls_psk_match(const struct key
*key
,
52 const struct key_match_data
*match_data
)
57 if (!key
->description
) {
58 pr_debug("%s: no key description\n", __func__
);
61 if (!match_data
->raw_data
) {
62 pr_debug("%s: no match data\n", __func__
);
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
);
72 static int nvme_tls_psk_match_preparse(struct key_match_data
*match_data
)
74 match_data
->lookup_type
= KEYRING_SEARCH_LOOKUP_ITERATE
;
75 match_data
->cmp
= nvme_tls_psk_match
;
79 static struct key_type nvme_tls_psk_key_type
= {
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
,
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
)
97 size_t identity_len
= (NVMF_NQN_SIZE
) * 2 + 11;
99 key_serial_t keyring_id
;
101 identity
= kzalloc(identity_len
, GFP_KERNEL
);
103 return ERR_PTR(-ENOMEM
);
105 snprintf(identity
, identity_len
, "NVMe%u%c%02u %s %s",
106 psk_ver
, generated
? 'G' : 'R', hmac
, hostnqn
, subnqn
);
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
,
116 if (IS_ERR(keyref
)) {
117 pr_debug("lookup tls psk '%s' failed, error %ld\n",
118 identity
, PTR_ERR(keyref
));
120 return ERR_PTR(-ENOKEY
);
124 return key_ref_to_ptr(keyref
);
128 * NVMe PSK priority list
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.
134 static struct nvme_tls_psk_priority_list
{
137 enum nvme_tcp_tls_cipher cipher
;
138 } nvme_tls_psk_prio
[] = {
139 { .generated
= false,
141 .cipher
= NVME_TCP_TLS_CIPHER_SHA384
, },
142 { .generated
= false,
144 .cipher
= NVME_TCP_TLS_CIPHER_SHA256
, },
145 { .generated
= false,
147 .cipher
= NVME_TCP_TLS_CIPHER_SHA384
, },
148 { .generated
= false,
150 .cipher
= NVME_TCP_TLS_CIPHER_SHA256
, },
153 .cipher
= NVME_TCP_TLS_CIPHER_SHA384
, },
156 .cipher
= NVME_TCP_TLS_CIPHER_SHA256
, },
159 .cipher
= NVME_TCP_TLS_CIPHER_SHA384
, },
162 .cipher
= NVME_TCP_TLS_CIPHER_SHA256
, },
166 * nvme_tls_psk_default - Return the preferred PSK to use for TLS ClientHello
168 key_serial_t
nvme_tls_psk_default(struct key
*keyring
,
169 const char *hostnqn
, const char *subnqn
)
172 key_serial_t tls_key_id
;
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
;
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
;
190 EXPORT_SYMBOL_GPL(nvme_tls_psk_default
);
192 static int __init
nvme_keyring_init(void)
196 nvme_keyring
= keyring_alloc(".nvme",
197 GLOBAL_ROOT_UID
, GLOBAL_ROOT_GID
,
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
);
205 err
= register_key_type(&nvme_tls_psk_key_type
);
207 key_put(nvme_keyring
);
213 static void __exit
nvme_keyring_exit(void)
215 unregister_key_type(&nvme_tls_psk_key_type
);
216 key_revoke(nvme_keyring
);
217 key_put(nvme_keyring
);
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
);