xref: /openbmc/linux/drivers/acpi/nfit/intel.c (revision 8a5aaf97)
1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright(c) 2018 Intel Corporation. All rights reserved. */
3 #include <linux/libnvdimm.h>
4 #include <linux/ndctl.h>
5 #include <linux/acpi.h>
6 #include <asm/smp.h>
7 #include "intel.h"
8 #include "nfit.h"
9 
10 static enum nvdimm_security_state intel_security_state(struct nvdimm *nvdimm,
11 		enum nvdimm_passphrase_type ptype)
12 {
13 	struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm);
14 	struct {
15 		struct nd_cmd_pkg pkg;
16 		struct nd_intel_get_security_state cmd;
17 	} nd_cmd = {
18 		.pkg = {
19 			.nd_command = NVDIMM_INTEL_GET_SECURITY_STATE,
20 			.nd_family = NVDIMM_FAMILY_INTEL,
21 			.nd_size_out =
22 				sizeof(struct nd_intel_get_security_state),
23 			.nd_fw_size =
24 				sizeof(struct nd_intel_get_security_state),
25 		},
26 	};
27 	int rc;
28 
29 	if (!test_bit(NVDIMM_INTEL_GET_SECURITY_STATE, &nfit_mem->dsm_mask))
30 		return -ENXIO;
31 
32 	/*
33 	 * Short circuit the state retrieval while we are doing overwrite.
34 	 * The DSM spec states that the security state is indeterminate
35 	 * until the overwrite DSM completes.
36 	 */
37 	if (nvdimm_in_overwrite(nvdimm) && ptype == NVDIMM_USER)
38 		return NVDIMM_SECURITY_OVERWRITE;
39 
40 	rc = nvdimm_ctl(nvdimm, ND_CMD_CALL, &nd_cmd, sizeof(nd_cmd), NULL);
41 	if (rc < 0)
42 		return rc;
43 	if (nd_cmd.cmd.status)
44 		return -EIO;
45 
46 	/* check and see if security is enabled and locked */
47 	if (ptype == NVDIMM_MASTER) {
48 		if (nd_cmd.cmd.extended_state & ND_INTEL_SEC_ESTATE_ENABLED)
49 			return NVDIMM_SECURITY_UNLOCKED;
50 		else if (nd_cmd.cmd.extended_state &
51 				ND_INTEL_SEC_ESTATE_PLIMIT)
52 			return NVDIMM_SECURITY_FROZEN;
53 	} else {
54 		if (nd_cmd.cmd.state & ND_INTEL_SEC_STATE_UNSUPPORTED)
55 			return -ENXIO;
56 		else if (nd_cmd.cmd.state & ND_INTEL_SEC_STATE_ENABLED) {
57 			if (nd_cmd.cmd.state & ND_INTEL_SEC_STATE_LOCKED)
58 				return NVDIMM_SECURITY_LOCKED;
59 			else if (nd_cmd.cmd.state & ND_INTEL_SEC_STATE_FROZEN
60 					|| nd_cmd.cmd.state &
61 					ND_INTEL_SEC_STATE_PLIMIT)
62 				return NVDIMM_SECURITY_FROZEN;
63 			else
64 				return NVDIMM_SECURITY_UNLOCKED;
65 		}
66 	}
67 
68 	/* this should cover master security disabled as well */
69 	return NVDIMM_SECURITY_DISABLED;
70 }
71 
72 static int intel_security_freeze(struct nvdimm *nvdimm)
73 {
74 	struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm);
75 	struct {
76 		struct nd_cmd_pkg pkg;
77 		struct nd_intel_freeze_lock cmd;
78 	} nd_cmd = {
79 		.pkg = {
80 			.nd_command = NVDIMM_INTEL_FREEZE_LOCK,
81 			.nd_family = NVDIMM_FAMILY_INTEL,
82 			.nd_size_out = ND_INTEL_STATUS_SIZE,
83 			.nd_fw_size = ND_INTEL_STATUS_SIZE,
84 		},
85 	};
86 	int rc;
87 
88 	if (!test_bit(NVDIMM_INTEL_FREEZE_LOCK, &nfit_mem->dsm_mask))
89 		return -ENOTTY;
90 
91 	rc = nvdimm_ctl(nvdimm, ND_CMD_CALL, &nd_cmd, sizeof(nd_cmd), NULL);
92 	if (rc < 0)
93 		return rc;
94 	if (nd_cmd.cmd.status)
95 		return -EIO;
96 	return 0;
97 }
98 
99 static int intel_security_change_key(struct nvdimm *nvdimm,
100 		const struct nvdimm_key_data *old_data,
101 		const struct nvdimm_key_data *new_data,
102 		enum nvdimm_passphrase_type ptype)
103 {
104 	struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm);
105 	unsigned int cmd = ptype == NVDIMM_MASTER ?
106 		NVDIMM_INTEL_SET_MASTER_PASSPHRASE :
107 		NVDIMM_INTEL_SET_PASSPHRASE;
108 	struct {
109 		struct nd_cmd_pkg pkg;
110 		struct nd_intel_set_passphrase cmd;
111 	} nd_cmd = {
112 		.pkg = {
113 			.nd_family = NVDIMM_FAMILY_INTEL,
114 			.nd_size_in = ND_INTEL_PASSPHRASE_SIZE * 2,
115 			.nd_size_out = ND_INTEL_STATUS_SIZE,
116 			.nd_fw_size = ND_INTEL_STATUS_SIZE,
117 			.nd_command = cmd,
118 		},
119 	};
120 	int rc;
121 
122 	if (!test_bit(cmd, &nfit_mem->dsm_mask))
123 		return -ENOTTY;
124 
125 	if (old_data)
126 		memcpy(nd_cmd.cmd.old_pass, old_data->data,
127 				sizeof(nd_cmd.cmd.old_pass));
128 	memcpy(nd_cmd.cmd.new_pass, new_data->data,
129 			sizeof(nd_cmd.cmd.new_pass));
130 	rc = nvdimm_ctl(nvdimm, ND_CMD_CALL, &nd_cmd, sizeof(nd_cmd), NULL);
131 	if (rc < 0)
132 		return rc;
133 
134 	switch (nd_cmd.cmd.status) {
135 	case 0:
136 		return 0;
137 	case ND_INTEL_STATUS_INVALID_PASS:
138 		return -EINVAL;
139 	case ND_INTEL_STATUS_NOT_SUPPORTED:
140 		return -EOPNOTSUPP;
141 	case ND_INTEL_STATUS_INVALID_STATE:
142 	default:
143 		return -EIO;
144 	}
145 }
146 
147 static void nvdimm_invalidate_cache(void);
148 
149 static int intel_security_unlock(struct nvdimm *nvdimm,
150 		const struct nvdimm_key_data *key_data)
151 {
152 	struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm);
153 	struct {
154 		struct nd_cmd_pkg pkg;
155 		struct nd_intel_unlock_unit cmd;
156 	} nd_cmd = {
157 		.pkg = {
158 			.nd_command = NVDIMM_INTEL_UNLOCK_UNIT,
159 			.nd_family = NVDIMM_FAMILY_INTEL,
160 			.nd_size_in = ND_INTEL_PASSPHRASE_SIZE,
161 			.nd_size_out = ND_INTEL_STATUS_SIZE,
162 			.nd_fw_size = ND_INTEL_STATUS_SIZE,
163 		},
164 	};
165 	int rc;
166 
167 	if (!test_bit(NVDIMM_INTEL_UNLOCK_UNIT, &nfit_mem->dsm_mask))
168 		return -ENOTTY;
169 
170 	memcpy(nd_cmd.cmd.passphrase, key_data->data,
171 			sizeof(nd_cmd.cmd.passphrase));
172 	rc = nvdimm_ctl(nvdimm, ND_CMD_CALL, &nd_cmd, sizeof(nd_cmd), NULL);
173 	if (rc < 0)
174 		return rc;
175 	switch (nd_cmd.cmd.status) {
176 	case 0:
177 		break;
178 	case ND_INTEL_STATUS_INVALID_PASS:
179 		return -EINVAL;
180 	default:
181 		return -EIO;
182 	}
183 
184 	/* DIMM unlocked, invalidate all CPU caches before we read it */
185 	nvdimm_invalidate_cache();
186 
187 	return 0;
188 }
189 
190 static int intel_security_disable(struct nvdimm *nvdimm,
191 		const struct nvdimm_key_data *key_data)
192 {
193 	int rc;
194 	struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm);
195 	struct {
196 		struct nd_cmd_pkg pkg;
197 		struct nd_intel_disable_passphrase cmd;
198 	} nd_cmd = {
199 		.pkg = {
200 			.nd_command = NVDIMM_INTEL_DISABLE_PASSPHRASE,
201 			.nd_family = NVDIMM_FAMILY_INTEL,
202 			.nd_size_in = ND_INTEL_PASSPHRASE_SIZE,
203 			.nd_size_out = ND_INTEL_STATUS_SIZE,
204 			.nd_fw_size = ND_INTEL_STATUS_SIZE,
205 		},
206 	};
207 
208 	if (!test_bit(NVDIMM_INTEL_DISABLE_PASSPHRASE, &nfit_mem->dsm_mask))
209 		return -ENOTTY;
210 
211 	memcpy(nd_cmd.cmd.passphrase, key_data->data,
212 			sizeof(nd_cmd.cmd.passphrase));
213 	rc = nvdimm_ctl(nvdimm, ND_CMD_CALL, &nd_cmd, sizeof(nd_cmd), NULL);
214 	if (rc < 0)
215 		return rc;
216 
217 	switch (nd_cmd.cmd.status) {
218 	case 0:
219 		break;
220 	case ND_INTEL_STATUS_INVALID_PASS:
221 		return -EINVAL;
222 	case ND_INTEL_STATUS_INVALID_STATE:
223 	default:
224 		return -ENXIO;
225 	}
226 
227 	return 0;
228 }
229 
230 static int intel_security_erase(struct nvdimm *nvdimm,
231 		const struct nvdimm_key_data *key,
232 		enum nvdimm_passphrase_type ptype)
233 {
234 	int rc;
235 	struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm);
236 	unsigned int cmd = ptype == NVDIMM_MASTER ?
237 		NVDIMM_INTEL_MASTER_SECURE_ERASE : NVDIMM_INTEL_SECURE_ERASE;
238 	struct {
239 		struct nd_cmd_pkg pkg;
240 		struct nd_intel_secure_erase cmd;
241 	} nd_cmd = {
242 		.pkg = {
243 			.nd_family = NVDIMM_FAMILY_INTEL,
244 			.nd_size_in = ND_INTEL_PASSPHRASE_SIZE,
245 			.nd_size_out = ND_INTEL_STATUS_SIZE,
246 			.nd_fw_size = ND_INTEL_STATUS_SIZE,
247 			.nd_command = cmd,
248 		},
249 	};
250 
251 	if (!test_bit(cmd, &nfit_mem->dsm_mask))
252 		return -ENOTTY;
253 
254 	/* flush all cache before we erase DIMM */
255 	nvdimm_invalidate_cache();
256 	memcpy(nd_cmd.cmd.passphrase, key->data,
257 			sizeof(nd_cmd.cmd.passphrase));
258 	rc = nvdimm_ctl(nvdimm, ND_CMD_CALL, &nd_cmd, sizeof(nd_cmd), NULL);
259 	if (rc < 0)
260 		return rc;
261 
262 	switch (nd_cmd.cmd.status) {
263 	case 0:
264 		break;
265 	case ND_INTEL_STATUS_NOT_SUPPORTED:
266 		return -EOPNOTSUPP;
267 	case ND_INTEL_STATUS_INVALID_PASS:
268 		return -EINVAL;
269 	case ND_INTEL_STATUS_INVALID_STATE:
270 	default:
271 		return -ENXIO;
272 	}
273 
274 	/* DIMM erased, invalidate all CPU caches before we read it */
275 	nvdimm_invalidate_cache();
276 	return 0;
277 }
278 
279 static int intel_security_query_overwrite(struct nvdimm *nvdimm)
280 {
281 	int rc;
282 	struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm);
283 	struct {
284 		struct nd_cmd_pkg pkg;
285 		struct nd_intel_query_overwrite cmd;
286 	} nd_cmd = {
287 		.pkg = {
288 			.nd_command = NVDIMM_INTEL_QUERY_OVERWRITE,
289 			.nd_family = NVDIMM_FAMILY_INTEL,
290 			.nd_size_out = ND_INTEL_STATUS_SIZE,
291 			.nd_fw_size = ND_INTEL_STATUS_SIZE,
292 		},
293 	};
294 
295 	if (!test_bit(NVDIMM_INTEL_QUERY_OVERWRITE, &nfit_mem->dsm_mask))
296 		return -ENOTTY;
297 
298 	rc = nvdimm_ctl(nvdimm, ND_CMD_CALL, &nd_cmd, sizeof(nd_cmd), NULL);
299 	if (rc < 0)
300 		return rc;
301 
302 	switch (nd_cmd.cmd.status) {
303 	case 0:
304 		break;
305 	case ND_INTEL_STATUS_OQUERY_INPROGRESS:
306 		return -EBUSY;
307 	default:
308 		return -ENXIO;
309 	}
310 
311 	/* flush all cache before we make the nvdimms available */
312 	nvdimm_invalidate_cache();
313 	return 0;
314 }
315 
316 static int intel_security_overwrite(struct nvdimm *nvdimm,
317 		const struct nvdimm_key_data *nkey)
318 {
319 	int rc;
320 	struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm);
321 	struct {
322 		struct nd_cmd_pkg pkg;
323 		struct nd_intel_overwrite cmd;
324 	} nd_cmd = {
325 		.pkg = {
326 			.nd_command = NVDIMM_INTEL_OVERWRITE,
327 			.nd_family = NVDIMM_FAMILY_INTEL,
328 			.nd_size_in = ND_INTEL_PASSPHRASE_SIZE,
329 			.nd_size_out = ND_INTEL_STATUS_SIZE,
330 			.nd_fw_size = ND_INTEL_STATUS_SIZE,
331 		},
332 	};
333 
334 	if (!test_bit(NVDIMM_INTEL_OVERWRITE, &nfit_mem->dsm_mask))
335 		return -ENOTTY;
336 
337 	/* flush all cache before we erase DIMM */
338 	nvdimm_invalidate_cache();
339 	if (nkey)
340 		memcpy(nd_cmd.cmd.passphrase, nkey->data,
341 				sizeof(nd_cmd.cmd.passphrase));
342 	rc = nvdimm_ctl(nvdimm, ND_CMD_CALL, &nd_cmd, sizeof(nd_cmd), NULL);
343 	if (rc < 0)
344 		return rc;
345 
346 	switch (nd_cmd.cmd.status) {
347 	case 0:
348 		return 0;
349 	case ND_INTEL_STATUS_OVERWRITE_UNSUPPORTED:
350 		return -ENOTSUPP;
351 	case ND_INTEL_STATUS_INVALID_PASS:
352 		return -EINVAL;
353 	case ND_INTEL_STATUS_INVALID_STATE:
354 	default:
355 		return -ENXIO;
356 	}
357 }
358 
359 /*
360  * TODO: define a cross arch wbinvd equivalent when/if
361  * NVDIMM_FAMILY_INTEL command support arrives on another arch.
362  */
363 #ifdef CONFIG_X86
364 static void nvdimm_invalidate_cache(void)
365 {
366 	wbinvd_on_all_cpus();
367 }
368 #else
369 static void nvdimm_invalidate_cache(void)
370 {
371 	WARN_ON_ONCE("cache invalidation required after unlock\n");
372 }
373 #endif
374 
375 static const struct nvdimm_security_ops __intel_security_ops = {
376 	.state = intel_security_state,
377 	.freeze = intel_security_freeze,
378 	.change_key = intel_security_change_key,
379 	.disable = intel_security_disable,
380 #ifdef CONFIG_X86
381 	.unlock = intel_security_unlock,
382 	.erase = intel_security_erase,
383 	.overwrite = intel_security_overwrite,
384 	.query_overwrite = intel_security_query_overwrite,
385 #endif
386 };
387 
388 const struct nvdimm_security_ops *intel_security_ops = &__intel_security_ops;
389