aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/nvdimm/security.c
diff options
context:
space:
mode:
authorDave Jiang <dave.jiang@intel.com>2018-12-07 12:33:30 -0500
committerDan Williams <dan.j.williams@intel.com>2018-12-21 15:44:41 -0500
commit03b65b22ada8115a7a7bfdf0789f6a94adfd6070 (patch)
treed8ac0a260db2dcac8b52ed36566bd9b89ab2d116 /drivers/nvdimm/security.c
parent4c6926a23b76ea23403976290cd45a7a143f6500 (diff)
acpi/nfit, libnvdimm: Add disable passphrase support to Intel nvdimm.
Add support to disable passphrase (security) for the Intel nvdimm. The passphrase used for disabling is pulled from an encrypted-key in the kernel user keyring. The action is triggered by writing "disable <keyid>" to the sysfs attribute "security". 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.c63
1 files changed, 63 insertions, 0 deletions
diff --git a/drivers/nvdimm/security.c b/drivers/nvdimm/security.c
index 51d77a67a9fb..647a99dd3182 100644
--- a/drivers/nvdimm/security.c
+++ b/drivers/nvdimm/security.c
@@ -69,6 +69,36 @@ static struct key *nvdimm_request_key(struct nvdimm *nvdimm)
69 return key; 69 return key;
70} 70}
71 71
72static struct key *nvdimm_lookup_user_key(struct nvdimm *nvdimm,
73 key_serial_t id)
74{
75 key_ref_t keyref;
76 struct key *key;
77 struct encrypted_key_payload *epayload;
78 struct device *dev = &nvdimm->dev;
79
80 keyref = lookup_user_key(id, 0, 0);
81 if (IS_ERR(keyref))
82 return NULL;
83
84 key = key_ref_to_ptr(keyref);
85 if (key->type != &key_type_encrypted) {
86 key_put(key);
87 return NULL;
88 }
89 dev_dbg(dev, "%s: key found: %#x\n", __func__, key_serial(key));
90
91
92 down_read(&key->sem);
93 epayload = dereference_key_locked(key);
94 if (epayload->decrypted_datalen != NVDIMM_PASSPHRASE_LEN) {
95 up_read(&key->sem);
96 key_put(key);
97 key = NULL;
98 }
99 return key;
100}
101
72static struct key *nvdimm_key_revalidate(struct nvdimm *nvdimm) 102static struct key *nvdimm_key_revalidate(struct nvdimm *nvdimm)
73{ 103{
74 struct key *key; 104 struct key *key;
@@ -146,3 +176,36 @@ int nvdimm_security_unlock(struct device *dev)
146 nvdimm_bus_unlock(dev); 176 nvdimm_bus_unlock(dev);
147 return rc; 177 return rc;
148} 178}
179
180int nvdimm_security_disable(struct nvdimm *nvdimm, unsigned int keyid)
181{
182 struct device *dev = &nvdimm->dev;
183 struct nvdimm_bus *nvdimm_bus = walk_to_nvdimm_bus(dev);
184 struct key *key;
185 int rc;
186
187 /* The bus lock should be held at the top level of the call stack */
188 lockdep_assert_held(&nvdimm_bus->reconfig_mutex);
189
190 if (!nvdimm->sec.ops || !nvdimm->sec.ops->disable
191 || nvdimm->sec.state < 0)
192 return -EOPNOTSUPP;
193
194 if (nvdimm->sec.state >= NVDIMM_SECURITY_FROZEN) {
195 dev_warn(dev, "Incorrect security state: %d\n",
196 nvdimm->sec.state);
197 return -EIO;
198 }
199
200 key = nvdimm_lookup_user_key(nvdimm, keyid);
201 if (!key)
202 return -ENOKEY;
203
204 rc = nvdimm->sec.ops->disable(nvdimm, key_data(key));
205 dev_dbg(dev, "key: %d disable: %s\n", key_serial(key),
206 rc == 0 ? "success" : "fail");
207
208 nvdimm_put_key(key);
209 nvdimm->sec.state = nvdimm_security_state(nvdimm);
210 return rc;
211}