Skip to content

Commit 3c13e2a

Browse files
davejiangdjbw
authored andcommitted
tools/testing/nvdimm: Add test support for Intel nvdimm security DSMs
Add nfit_test support for DSM functions "Get Security State", "Set Passphrase", "Disable Passphrase", "Unlock Unit", "Freeze Lock", and "Secure Erase" for the fake DIMMs. Also adding a sysfs knob in order to put the DIMMs in "locked" state. The order of testing DIMM unlocking would be. 1a. Disable DIMM X. 1b. Set Passphrase to DIMM X. 2. Write to /sys/devices/platform/nfit_test.0/nfit_test_dimm/test_dimmX/lock_dimm 3. Renable DIMM X 4. Check DIMM X state via sysfs "security" attribute for nmemX. Signed-off-by: Dave Jiang <[email protected]> Signed-off-by: Dan Williams <[email protected]>
1 parent 89fa9d8 commit 3c13e2a

File tree

4 files changed

+223
-1
lines changed

4 files changed

+223
-1
lines changed

drivers/nvdimm/dimm_devs.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -370,7 +370,7 @@ static ssize_t available_slots_show(struct device *dev,
370370
}
371371
static DEVICE_ATTR_RO(available_slots);
372372

373-
static ssize_t security_show(struct device *dev,
373+
__weak ssize_t security_show(struct device *dev,
374374
struct device_attribute *attr, char *buf)
375375
{
376376
struct nvdimm *nvdimm = to_nvdimm(dev);

tools/testing/nvdimm/Kbuild

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ libnvdimm-$(CONFIG_BTT) += $(NVDIMM_SRC)/btt_devs.o
8181
libnvdimm-$(CONFIG_NVDIMM_PFN) += $(NVDIMM_SRC)/pfn_devs.o
8282
libnvdimm-$(CONFIG_NVDIMM_DAX) += $(NVDIMM_SRC)/dax_devs.o
8383
libnvdimm-$(CONFIG_NVDIMM_KEYS) += $(NVDIMM_SRC)/security.o
84+
libnvdimm-y += dimm_devs.o
8485
libnvdimm-y += libnvdimm_test.o
8586
libnvdimm-y += config_check.o
8687

tools/testing/nvdimm/dimm_devs.c

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
/* Copyright Intel Corp. 2018 */
3+
#include <linux/init.h>
4+
#include <linux/module.h>
5+
#include <linux/moduleparam.h>
6+
#include <linux/nd.h>
7+
#include "pmem.h"
8+
#include "pfn.h"
9+
#include "nd.h"
10+
#include "nd-core.h"
11+
12+
ssize_t security_show(struct device *dev,
13+
struct device_attribute *attr, char *buf)
14+
{
15+
struct nvdimm *nvdimm = to_nvdimm(dev);
16+
17+
/*
18+
* For the test version we need to poll the "hardware" in order
19+
* to get the updated status for unlock testing.
20+
*/
21+
nvdimm->sec.state = nvdimm_security_state(nvdimm, false);
22+
nvdimm->sec.ext_state = nvdimm_security_state(nvdimm, true);
23+
24+
switch (nvdimm->sec.state) {
25+
case NVDIMM_SECURITY_DISABLED:
26+
return sprintf(buf, "disabled\n");
27+
case NVDIMM_SECURITY_UNLOCKED:
28+
return sprintf(buf, "unlocked\n");
29+
case NVDIMM_SECURITY_LOCKED:
30+
return sprintf(buf, "locked\n");
31+
case NVDIMM_SECURITY_FROZEN:
32+
return sprintf(buf, "frozen\n");
33+
case NVDIMM_SECURITY_OVERWRITE:
34+
return sprintf(buf, "overwrite\n");
35+
default:
36+
return -ENOTTY;
37+
}
38+
39+
return -ENOTTY;
40+
}
41+

tools/testing/nvdimm/test/nfit.c

Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,10 @@ static u32 handle[] = {
142142

143143
static unsigned long dimm_fail_cmd_flags[ARRAY_SIZE(handle)];
144144
static int dimm_fail_cmd_code[ARRAY_SIZE(handle)];
145+
struct nfit_test_sec {
146+
u8 state;
147+
u8 passphrase[32];
148+
} dimm_sec_info[NUM_DCR];
145149

146150
static const struct nd_intel_smart smart_def = {
147151
.flags = ND_INTEL_SMART_HEALTH_VALID
@@ -933,6 +937,138 @@ static int override_return_code(int dimm, unsigned int func, int rc)
933937
return rc;
934938
}
935939

940+
static int nd_intel_test_cmd_security_status(struct nfit_test *t,
941+
struct nd_intel_get_security_state *nd_cmd,
942+
unsigned int buf_len, int dimm)
943+
{
944+
struct device *dev = &t->pdev.dev;
945+
struct nfit_test_sec *sec = &dimm_sec_info[dimm];
946+
947+
nd_cmd->status = 0;
948+
nd_cmd->state = sec->state;
949+
dev_dbg(dev, "security state (%#x) returned\n", nd_cmd->state);
950+
951+
return 0;
952+
}
953+
954+
static int nd_intel_test_cmd_unlock_unit(struct nfit_test *t,
955+
struct nd_intel_unlock_unit *nd_cmd,
956+
unsigned int buf_len, int dimm)
957+
{
958+
struct device *dev = &t->pdev.dev;
959+
struct nfit_test_sec *sec = &dimm_sec_info[dimm];
960+
961+
if (!(sec->state & ND_INTEL_SEC_STATE_LOCKED) ||
962+
(sec->state & ND_INTEL_SEC_STATE_FROZEN)) {
963+
nd_cmd->status = ND_INTEL_STATUS_INVALID_STATE;
964+
dev_dbg(dev, "unlock unit: invalid state: %#x\n",
965+
sec->state);
966+
} else if (memcmp(nd_cmd->passphrase, sec->passphrase,
967+
ND_INTEL_PASSPHRASE_SIZE) != 0) {
968+
nd_cmd->status = ND_INTEL_STATUS_INVALID_PASS;
969+
dev_dbg(dev, "unlock unit: invalid passphrase\n");
970+
} else {
971+
nd_cmd->status = 0;
972+
sec->state = ND_INTEL_SEC_STATE_ENABLED;
973+
dev_dbg(dev, "Unit unlocked\n");
974+
}
975+
976+
dev_dbg(dev, "unlocking status returned: %#x\n", nd_cmd->status);
977+
return 0;
978+
}
979+
980+
static int nd_intel_test_cmd_set_pass(struct nfit_test *t,
981+
struct nd_intel_set_passphrase *nd_cmd,
982+
unsigned int buf_len, int dimm)
983+
{
984+
struct device *dev = &t->pdev.dev;
985+
struct nfit_test_sec *sec = &dimm_sec_info[dimm];
986+
987+
if (sec->state & ND_INTEL_SEC_STATE_FROZEN) {
988+
nd_cmd->status = ND_INTEL_STATUS_INVALID_STATE;
989+
dev_dbg(dev, "set passphrase: wrong security state\n");
990+
} else if (memcmp(nd_cmd->old_pass, sec->passphrase,
991+
ND_INTEL_PASSPHRASE_SIZE) != 0) {
992+
nd_cmd->status = ND_INTEL_STATUS_INVALID_PASS;
993+
dev_dbg(dev, "set passphrase: wrong passphrase\n");
994+
} else {
995+
memcpy(sec->passphrase, nd_cmd->new_pass,
996+
ND_INTEL_PASSPHRASE_SIZE);
997+
sec->state |= ND_INTEL_SEC_STATE_ENABLED;
998+
nd_cmd->status = 0;
999+
dev_dbg(dev, "passphrase updated\n");
1000+
}
1001+
1002+
return 0;
1003+
}
1004+
1005+
static int nd_intel_test_cmd_freeze_lock(struct nfit_test *t,
1006+
struct nd_intel_freeze_lock *nd_cmd,
1007+
unsigned int buf_len, int dimm)
1008+
{
1009+
struct device *dev = &t->pdev.dev;
1010+
struct nfit_test_sec *sec = &dimm_sec_info[dimm];
1011+
1012+
if (!(sec->state & ND_INTEL_SEC_STATE_ENABLED)) {
1013+
nd_cmd->status = ND_INTEL_STATUS_INVALID_STATE;
1014+
dev_dbg(dev, "freeze lock: wrong security state\n");
1015+
} else {
1016+
sec->state |= ND_INTEL_SEC_STATE_FROZEN;
1017+
nd_cmd->status = 0;
1018+
dev_dbg(dev, "security frozen\n");
1019+
}
1020+
1021+
return 0;
1022+
}
1023+
1024+
static int nd_intel_test_cmd_disable_pass(struct nfit_test *t,
1025+
struct nd_intel_disable_passphrase *nd_cmd,
1026+
unsigned int buf_len, int dimm)
1027+
{
1028+
struct device *dev = &t->pdev.dev;
1029+
struct nfit_test_sec *sec = &dimm_sec_info[dimm];
1030+
1031+
if (!(sec->state & ND_INTEL_SEC_STATE_ENABLED) ||
1032+
(sec->state & ND_INTEL_SEC_STATE_FROZEN)) {
1033+
nd_cmd->status = ND_INTEL_STATUS_INVALID_STATE;
1034+
dev_dbg(dev, "disable passphrase: wrong security state\n");
1035+
} else if (memcmp(nd_cmd->passphrase, sec->passphrase,
1036+
ND_INTEL_PASSPHRASE_SIZE) != 0) {
1037+
nd_cmd->status = ND_INTEL_STATUS_INVALID_PASS;
1038+
dev_dbg(dev, "disable passphrase: wrong passphrase\n");
1039+
} else {
1040+
memset(sec->passphrase, 0, ND_INTEL_PASSPHRASE_SIZE);
1041+
sec->state = 0;
1042+
dev_dbg(dev, "disable passphrase: done\n");
1043+
}
1044+
1045+
return 0;
1046+
}
1047+
1048+
static int nd_intel_test_cmd_secure_erase(struct nfit_test *t,
1049+
struct nd_intel_secure_erase *nd_cmd,
1050+
unsigned int buf_len, int dimm)
1051+
{
1052+
struct device *dev = &t->pdev.dev;
1053+
struct nfit_test_sec *sec = &dimm_sec_info[dimm];
1054+
1055+
if (!(sec->state & ND_INTEL_SEC_STATE_ENABLED) ||
1056+
(sec->state & ND_INTEL_SEC_STATE_FROZEN)) {
1057+
nd_cmd->status = ND_INTEL_STATUS_INVALID_STATE;
1058+
dev_dbg(dev, "secure erase: wrong security state\n");
1059+
} else if (memcmp(nd_cmd->passphrase, sec->passphrase,
1060+
ND_INTEL_PASSPHRASE_SIZE) != 0) {
1061+
nd_cmd->status = ND_INTEL_STATUS_INVALID_PASS;
1062+
dev_dbg(dev, "secure erase: wrong passphrase\n");
1063+
} else {
1064+
memset(sec->passphrase, 0, ND_INTEL_PASSPHRASE_SIZE);
1065+
sec->state = 0;
1066+
dev_dbg(dev, "secure erase: done\n");
1067+
}
1068+
1069+
return 0;
1070+
}
1071+
9361072
static int get_dimm(struct nfit_mem *nfit_mem, unsigned int func)
9371073
{
9381074
int i;
@@ -980,6 +1116,30 @@ static int nfit_test_ctl(struct nvdimm_bus_descriptor *nd_desc,
9801116
return i;
9811117

9821118
switch (func) {
1119+
case NVDIMM_INTEL_GET_SECURITY_STATE:
1120+
rc = nd_intel_test_cmd_security_status(t,
1121+
buf, buf_len, i);
1122+
break;
1123+
case NVDIMM_INTEL_UNLOCK_UNIT:
1124+
rc = nd_intel_test_cmd_unlock_unit(t,
1125+
buf, buf_len, i);
1126+
break;
1127+
case NVDIMM_INTEL_SET_PASSPHRASE:
1128+
rc = nd_intel_test_cmd_set_pass(t,
1129+
buf, buf_len, i);
1130+
break;
1131+
case NVDIMM_INTEL_DISABLE_PASSPHRASE:
1132+
rc = nd_intel_test_cmd_disable_pass(t,
1133+
buf, buf_len, i);
1134+
break;
1135+
case NVDIMM_INTEL_FREEZE_LOCK:
1136+
rc = nd_intel_test_cmd_freeze_lock(t,
1137+
buf, buf_len, i);
1138+
break;
1139+
case NVDIMM_INTEL_SECURE_ERASE:
1140+
rc = nd_intel_test_cmd_secure_erase(t,
1141+
buf, buf_len, i);
1142+
break;
9831143
case ND_INTEL_ENABLE_LSS_STATUS:
9841144
rc = nd_intel_test_cmd_set_lss_status(t,
9851145
buf, buf_len);
@@ -1313,10 +1473,22 @@ static ssize_t fail_cmd_code_store(struct device *dev, struct device_attribute *
13131473
}
13141474
static DEVICE_ATTR_RW(fail_cmd_code);
13151475

1476+
static ssize_t lock_dimm_store(struct device *dev,
1477+
struct device_attribute *attr, const char *buf, size_t size)
1478+
{
1479+
int dimm = dimm_name_to_id(dev);
1480+
struct nfit_test_sec *sec = &dimm_sec_info[dimm];
1481+
1482+
sec->state = ND_INTEL_SEC_STATE_ENABLED | ND_INTEL_SEC_STATE_LOCKED;
1483+
return size;
1484+
}
1485+
static DEVICE_ATTR_WO(lock_dimm);
1486+
13161487
static struct attribute *nfit_test_dimm_attributes[] = {
13171488
&dev_attr_fail_cmd.attr,
13181489
&dev_attr_fail_cmd_code.attr,
13191490
&dev_attr_handle.attr,
1491+
&dev_attr_lock_dimm.attr,
13201492
NULL,
13211493
};
13221494

@@ -2195,6 +2367,14 @@ static void nfit_test0_setup(struct nfit_test *t)
21952367
set_bit(ND_INTEL_FW_FINISH_UPDATE, &acpi_desc->dimm_cmd_force_en);
21962368
set_bit(ND_INTEL_FW_FINISH_QUERY, &acpi_desc->dimm_cmd_force_en);
21972369
set_bit(ND_INTEL_ENABLE_LSS_STATUS, &acpi_desc->dimm_cmd_force_en);
2370+
set_bit(NVDIMM_INTEL_GET_SECURITY_STATE,
2371+
&acpi_desc->dimm_cmd_force_en);
2372+
set_bit(NVDIMM_INTEL_SET_PASSPHRASE, &acpi_desc->dimm_cmd_force_en);
2373+
set_bit(NVDIMM_INTEL_DISABLE_PASSPHRASE,
2374+
&acpi_desc->dimm_cmd_force_en);
2375+
set_bit(NVDIMM_INTEL_UNLOCK_UNIT, &acpi_desc->dimm_cmd_force_en);
2376+
set_bit(NVDIMM_INTEL_FREEZE_LOCK, &acpi_desc->dimm_cmd_force_en);
2377+
set_bit(NVDIMM_INTEL_SECURE_ERASE, &acpi_desc->dimm_cmd_force_en);
21982378
}
21992379

22002380
static void nfit_test1_setup(struct nfit_test *t)

0 commit comments

Comments
 (0)