aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/nvdimm/security.c
diff options
context:
space:
mode:
authorDave Jiang <dave.jiang@intel.com>2018-12-07 15:29:09 -0500
committerDan Williams <dan.j.williams@intel.com>2018-12-21 15:44:41 -0500
commitd2a4ac73f56a5d0709d28b41fec8d15e4500f8f1 (patch)
tree6ae066b618c3c0c68865b0783f88da25d2d69a7a /drivers/nvdimm/security.c
parent03b65b22ada8115a7a7bfdf0789f6a94adfd6070 (diff)
acpi/nfit, libnvdimm: Add enable/update passphrase support for Intel nvdimms
Add support for enabling and updating passphrase on the Intel nvdimms. The passphrase is the an encrypted key in the kernel user keyring. We trigger the update via writing "update <old_keyid> <new_keyid>" to the sysfs attribute "security". If no <old_keyid> exists (for enabling security) then a 0 should be used. Signed-off-by: Dave Jiang <dave.jiang@intel.com> Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Diffstat (limited to 'drivers/nvdimm/security.c')
-rw-r--r--drivers/nvdimm/security.c58
1 files changed, 54 insertions, 4 deletions
diff --git a/drivers/nvdimm/security.c b/drivers/nvdimm/security.c
index 647a99dd3182..df7f070e96fb 100644
--- a/drivers/nvdimm/security.c
+++ b/drivers/nvdimm/security.c
@@ -15,6 +15,9 @@
15#include "nd-core.h" 15#include "nd-core.h"
16#include "nd.h" 16#include "nd.h"
17 17
18#define NVDIMM_BASE_KEY 0
19#define NVDIMM_NEW_KEY 1
20
18static bool key_revalidate = true; 21static bool key_revalidate = true;
19module_param(key_revalidate, bool, 0444); 22module_param(key_revalidate, bool, 0444);
20MODULE_PARM_DESC(key_revalidate, "Require key validation at init."); 23MODULE_PARM_DESC(key_revalidate, "Require key validation at init.");
@@ -70,7 +73,7 @@ static struct key *nvdimm_request_key(struct nvdimm *nvdimm)
70} 73}
71 74
72static struct key *nvdimm_lookup_user_key(struct nvdimm *nvdimm, 75static struct key *nvdimm_lookup_user_key(struct nvdimm *nvdimm,
73 key_serial_t id) 76 key_serial_t id, int subclass)
74{ 77{
75 key_ref_t keyref; 78 key_ref_t keyref;
76 struct key *key; 79 struct key *key;
@@ -86,10 +89,10 @@ static struct key *nvdimm_lookup_user_key(struct nvdimm *nvdimm,
86 key_put(key); 89 key_put(key);
87 return NULL; 90 return NULL;
88 } 91 }
89 dev_dbg(dev, "%s: key found: %#x\n", __func__, key_serial(key));
90 92
93 dev_dbg(dev, "%s: key found: %#x\n", __func__, key_serial(key));
91 94
92 down_read(&key->sem); 95 down_read_nested(&key->sem, subclass);
93 epayload = dereference_key_locked(key); 96 epayload = dereference_key_locked(key);
94 if (epayload->decrypted_datalen != NVDIMM_PASSPHRASE_LEN) { 97 if (epayload->decrypted_datalen != NVDIMM_PASSPHRASE_LEN) {
95 up_read(&key->sem); 98 up_read(&key->sem);
@@ -197,7 +200,7 @@ int nvdimm_security_disable(struct nvdimm *nvdimm, unsigned int keyid)
197 return -EIO; 200 return -EIO;
198 } 201 }
199 202
200 key = nvdimm_lookup_user_key(nvdimm, keyid); 203 key = nvdimm_lookup_user_key(nvdimm, keyid, NVDIMM_BASE_KEY);
201 if (!key) 204 if (!key)
202 return -ENOKEY; 205 return -ENOKEY;
203 206
@@ -209,3 +212,50 @@ int nvdimm_security_disable(struct nvdimm *nvdimm, unsigned int keyid)
209 nvdimm->sec.state = nvdimm_security_state(nvdimm); 212 nvdimm->sec.state = nvdimm_security_state(nvdimm);
210 return rc; 213 return rc;
211} 214}
215
216int nvdimm_security_update(struct nvdimm *nvdimm, unsigned int keyid,
217 unsigned int new_keyid)
218{
219 struct device *dev = &nvdimm->dev;
220 struct nvdimm_bus *nvdimm_bus = walk_to_nvdimm_bus(dev);
221 struct key *key, *newkey;
222 int rc;
223
224 /* The bus lock should be held at the top level of the call stack */
225 lockdep_assert_held(&nvdimm_bus->reconfig_mutex);
226
227 if (!nvdimm->sec.ops || !nvdimm->sec.ops->change_key
228 || nvdimm->sec.state < 0)
229 return -EOPNOTSUPP;
230
231 if (nvdimm->sec.state >= NVDIMM_SECURITY_FROZEN) {
232 dev_warn(dev, "Incorrect security state: %d\n",
233 nvdimm->sec.state);
234 return -EIO;
235 }
236
237 if (keyid == 0)
238 key = NULL;
239 else {
240 key = nvdimm_lookup_user_key(nvdimm, keyid, NVDIMM_BASE_KEY);
241 if (!key)
242 return -ENOKEY;
243 }
244
245 newkey = nvdimm_lookup_user_key(nvdimm, new_keyid, NVDIMM_NEW_KEY);
246 if (!newkey) {
247 nvdimm_put_key(key);
248 return -ENOKEY;
249 }
250
251 rc = nvdimm->sec.ops->change_key(nvdimm, key ? key_data(key) : NULL,
252 key_data(newkey));
253 dev_dbg(dev, "key: %d %d update: %s\n",
254 key_serial(key), key_serial(newkey),
255 rc == 0 ? "success" : "fail");
256
257 nvdimm_put_key(newkey);
258 nvdimm_put_key(key);
259 nvdimm->sec.state = nvdimm_security_state(nvdimm);
260 return rc;
261}