diff options
| -rw-r--r-- | drivers/nvdimm/dimm_devs.c | 2 | ||||
| -rw-r--r-- | tools/testing/nvdimm/Kbuild | 1 | ||||
| -rw-r--r-- | tools/testing/nvdimm/dimm_devs.c | 41 | ||||
| -rw-r--r-- | tools/testing/nvdimm/test/nfit.c | 180 |
4 files changed, 223 insertions, 1 deletions
diff --git a/drivers/nvdimm/dimm_devs.c b/drivers/nvdimm/dimm_devs.c index bd3f156463b1..4890310df874 100644 --- a/drivers/nvdimm/dimm_devs.c +++ b/drivers/nvdimm/dimm_devs.c | |||
| @@ -370,7 +370,7 @@ static ssize_t available_slots_show(struct device *dev, | |||
| 370 | } | 370 | } |
| 371 | static DEVICE_ATTR_RO(available_slots); | 371 | static DEVICE_ATTR_RO(available_slots); |
| 372 | 372 | ||
| 373 | static ssize_t security_show(struct device *dev, | 373 | __weak ssize_t security_show(struct device *dev, |
| 374 | struct device_attribute *attr, char *buf) | 374 | struct device_attribute *attr, char *buf) |
| 375 | { | 375 | { |
| 376 | struct nvdimm *nvdimm = to_nvdimm(dev); | 376 | struct nvdimm *nvdimm = to_nvdimm(dev); |
diff --git a/tools/testing/nvdimm/Kbuild b/tools/testing/nvdimm/Kbuild index 33ea40777205..10ddf223055b 100644 --- a/tools/testing/nvdimm/Kbuild +++ b/tools/testing/nvdimm/Kbuild | |||
| @@ -81,6 +81,7 @@ libnvdimm-$(CONFIG_BTT) += $(NVDIMM_SRC)/btt_devs.o | |||
| 81 | libnvdimm-$(CONFIG_NVDIMM_PFN) += $(NVDIMM_SRC)/pfn_devs.o | 81 | libnvdimm-$(CONFIG_NVDIMM_PFN) += $(NVDIMM_SRC)/pfn_devs.o |
| 82 | libnvdimm-$(CONFIG_NVDIMM_DAX) += $(NVDIMM_SRC)/dax_devs.o | 82 | libnvdimm-$(CONFIG_NVDIMM_DAX) += $(NVDIMM_SRC)/dax_devs.o |
| 83 | libnvdimm-$(CONFIG_NVDIMM_KEYS) += $(NVDIMM_SRC)/security.o | 83 | libnvdimm-$(CONFIG_NVDIMM_KEYS) += $(NVDIMM_SRC)/security.o |
| 84 | libnvdimm-y += dimm_devs.o | ||
| 84 | libnvdimm-y += libnvdimm_test.o | 85 | libnvdimm-y += libnvdimm_test.o |
| 85 | libnvdimm-y += config_check.o | 86 | libnvdimm-y += config_check.o |
| 86 | 87 | ||
diff --git a/tools/testing/nvdimm/dimm_devs.c b/tools/testing/nvdimm/dimm_devs.c new file mode 100644 index 000000000000..e75238404555 --- /dev/null +++ b/tools/testing/nvdimm/dimm_devs.c | |||
| @@ -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 | |||
diff --git a/tools/testing/nvdimm/test/nfit.c b/tools/testing/nvdimm/test/nfit.c index 01ec04bf91b5..30f89fd740d9 100644 --- a/tools/testing/nvdimm/test/nfit.c +++ b/tools/testing/nvdimm/test/nfit.c | |||
| @@ -142,6 +142,10 @@ static u32 handle[] = { | |||
| 142 | 142 | ||
| 143 | static unsigned long dimm_fail_cmd_flags[ARRAY_SIZE(handle)]; | 143 | static unsigned long dimm_fail_cmd_flags[ARRAY_SIZE(handle)]; |
| 144 | static int dimm_fail_cmd_code[ARRAY_SIZE(handle)]; | 144 | 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]; | ||
| 145 | 149 | ||
| 146 | static const struct nd_intel_smart smart_def = { | 150 | static const struct nd_intel_smart smart_def = { |
| 147 | .flags = ND_INTEL_SMART_HEALTH_VALID | 151 | .flags = ND_INTEL_SMART_HEALTH_VALID |
| @@ -933,6 +937,138 @@ static int override_return_code(int dimm, unsigned int func, int rc) | |||
| 933 | return rc; | 937 | return rc; |
| 934 | } | 938 | } |
| 935 | 939 | ||
| 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 | |||
