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>
10 static enum nvdimm_security_state
intel_security_state(struct nvdimm
*nvdimm
,
11 enum nvdimm_passphrase_type ptype
)
13 struct nfit_mem
*nfit_mem
= nvdimm_provider_data(nvdimm
);
15 struct nd_cmd_pkg pkg
;
16 struct nd_intel_get_security_state cmd
;
19 .nd_command
= NVDIMM_INTEL_GET_SECURITY_STATE
,
20 .nd_family
= NVDIMM_FAMILY_INTEL
,
22 sizeof(struct nd_intel_get_security_state
),
24 sizeof(struct nd_intel_get_security_state
),
29 if (!test_bit(NVDIMM_INTEL_GET_SECURITY_STATE
, &nfit_mem
->dsm_mask
))
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.
37 if (nvdimm_in_overwrite(nvdimm
) && ptype
== NVDIMM_USER
)
38 return NVDIMM_SECURITY_OVERWRITE
;
40 rc
= nvdimm_ctl(nvdimm
, ND_CMD_CALL
, &nd_cmd
, sizeof(nd_cmd
), NULL
);
43 if (nd_cmd
.cmd
.status
)
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
;
54 if (nd_cmd
.cmd
.state
& ND_INTEL_SEC_STATE_UNSUPPORTED
)
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
61 ND_INTEL_SEC_STATE_PLIMIT
)
62 return NVDIMM_SECURITY_FROZEN
;
64 return NVDIMM_SECURITY_UNLOCKED
;
68 /* this should cover master security disabled as well */
69 return NVDIMM_SECURITY_DISABLED
;
72 static int intel_security_freeze(struct nvdimm
*nvdimm
)
74 struct nfit_mem
*nfit_mem
= nvdimm_provider_data(nvdimm
);
76 struct nd_cmd_pkg pkg
;
77 struct nd_intel_freeze_lock cmd
;
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
,
88 if (!test_bit(NVDIMM_INTEL_FREEZE_LOCK
, &nfit_mem
->dsm_mask
))
91 rc
= nvdimm_ctl(nvdimm
, ND_CMD_CALL
, &nd_cmd
, sizeof(nd_cmd
), NULL
);
94 if (nd_cmd
.cmd
.status
)
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
)
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
;
109 struct nd_cmd_pkg pkg
;
110 struct nd_intel_set_passphrase cmd
;
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
,
122 if (!test_bit(cmd
, &nfit_mem
->dsm_mask
))
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
);
134 switch (nd_cmd
.cmd
.status
) {
137 case ND_INTEL_STATUS_INVALID_PASS
:
139 case ND_INTEL_STATUS_NOT_SUPPORTED
:
141 case ND_INTEL_STATUS_INVALID_STATE
:
147 static void nvdimm_invalidate_cache(void);
149 static int intel_security_unlock(struct nvdimm
*nvdimm
,
150 const struct nvdimm_key_data
*key_data
)
152 struct nfit_mem
*nfit_mem
= nvdimm_provider_data(nvdimm
);
154 struct nd_cmd_pkg pkg
;
155 struct nd_intel_unlock_unit cmd
;
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
,
167 if (!test_bit(NVDIMM_INTEL_UNLOCK_UNIT
, &nfit_mem
->dsm_mask
))
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
);
175 switch (nd_cmd
.cmd
.status
) {
178 case ND_INTEL_STATUS_INVALID_PASS
:
184 /* DIMM unlocked, invalidate all CPU caches before we read it */
185 nvdimm_invalidate_cache();
190 static int intel_security_disable(struct nvdimm
*nvdimm
,
191 const struct nvdimm_key_data
*key_data
)
194 struct nfit_mem
*nfit_mem
= nvdimm_provider_data(nvdimm
);
196 struct nd_cmd_pkg pkg
;
197 struct nd_intel_disable_passphrase cmd
;
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
,
208 if (!test_bit(NVDIMM_INTEL_DISABLE_PASSPHRASE
, &nfit_mem
->dsm_mask
))
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
);
217 switch (nd_cmd
.cmd
.status
) {
220 case ND_INTEL_STATUS_INVALID_PASS
:
222 case ND_INTEL_STATUS_INVALID_STATE
:
230 static int intel_security_erase(struct nvdimm
*nvdimm
,
231 const struct nvdimm_key_data
*key
,
232 enum nvdimm_passphrase_type ptype
)
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
;
239 struct nd_cmd_pkg pkg
;
240 struct nd_intel_secure_erase cmd
;
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
,
251 if (!test_bit(cmd
, &nfit_mem
->dsm_mask
))
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
);
262 switch (nd_cmd
.cmd
.status
) {
265 case ND_INTEL_STATUS_NOT_SUPPORTED
:
267 case ND_INTEL_STATUS_INVALID_PASS
:
269 case ND_INTEL_STATUS_INVALID_STATE
:
274 /* DIMM erased, invalidate all CPU caches before we read it */
275 nvdimm_invalidate_cache();
279 static int intel_security_query_overwrite(struct nvdimm
*nvdimm
)
282 struct nfit_mem
*nfit_mem
= nvdimm_provider_data(nvdimm
);
284 struct nd_cmd_pkg pkg
;
285 struct nd_intel_query_overwrite cmd
;
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
,
295 if (!test_bit(NVDIMM_INTEL_QUERY_OVERWRITE
, &nfit_mem
->dsm_mask
))
298 rc
= nvdimm_ctl(nvdimm
, ND_CMD_CALL
, &nd_cmd
, sizeof(nd_cmd
), NULL
);
302 switch (nd_cmd
.cmd
.status
) {
305 case ND_INTEL_STATUS_OQUERY_INPROGRESS
:
311 /* flush all cache before we make the nvdimms available */
312 nvdimm_invalidate_cache();
316 static int intel_security_overwrite(struct nvdimm
*nvdimm
,
317 const struct nvdimm_key_data
*nkey
)
320 struct nfit_mem
*nfit_mem
= nvdimm_provider_data(nvdimm
);
322 struct nd_cmd_pkg pkg
;
323 struct nd_intel_overwrite cmd
;
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
,
334 if (!test_bit(NVDIMM_INTEL_OVERWRITE
, &nfit_mem
->dsm_mask
))
337 /* flush all cache before we erase DIMM */
338 nvdimm_invalidate_cache();
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
);
346 switch (nd_cmd
.cmd
.status
) {
349 case ND_INTEL_STATUS_OVERWRITE_UNSUPPORTED
:
351 case ND_INTEL_STATUS_INVALID_PASS
:
353 case ND_INTEL_STATUS_INVALID_STATE
:
360 * TODO: define a cross arch wbinvd equivalent when/if
361 * NVDIMM_FAMILY_INTEL command support arrives on another arch.
364 static void nvdimm_invalidate_cache(void)
366 wbinvd_on_all_cpus();
369 static void nvdimm_invalidate_cache(void)
371 WARN_ON_ONCE("cache invalidation required after unlock\n");
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
,
381 .unlock
= intel_security_unlock
,
382 .erase
= intel_security_erase
,
383 .overwrite
= intel_security_overwrite
,
384 .query_overwrite
= intel_security_query_overwrite
,
388 const struct nvdimm_security_ops
*intel_security_ops
= &__intel_security_ops
;