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 memcpy(nd_cmd.cmd.old_pass, old_data->data, 126 sizeof(nd_cmd.cmd.old_pass)); 127 memcpy(nd_cmd.cmd.new_pass, new_data->data, 128 sizeof(nd_cmd.cmd.new_pass)); 129 rc = nvdimm_ctl(nvdimm, ND_CMD_CALL, &nd_cmd, sizeof(nd_cmd), NULL); 130 if (rc < 0) 131 return rc; 132 133 switch (nd_cmd.cmd.status) { 134 case 0: 135 return 0; 136 case ND_INTEL_STATUS_INVALID_PASS: 137 return -EINVAL; 138 case ND_INTEL_STATUS_NOT_SUPPORTED: 139 return -EOPNOTSUPP; 140 case ND_INTEL_STATUS_INVALID_STATE: 141 default: 142 return -EIO; 143 } 144 } 145 146 static void nvdimm_invalidate_cache(void); 147 148 static int __maybe_unused intel_security_unlock(struct nvdimm *nvdimm, 149 const struct nvdimm_key_data *key_data) 150 { 151 struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm); 152 struct { 153 struct nd_cmd_pkg pkg; 154 struct nd_intel_unlock_unit cmd; 155 } nd_cmd = { 156 .pkg = { 157 .nd_command = NVDIMM_INTEL_UNLOCK_UNIT, 158 .nd_family = NVDIMM_FAMILY_INTEL, 159 .nd_size_in = ND_INTEL_PASSPHRASE_SIZE, 160 .nd_size_out = ND_INTEL_STATUS_SIZE, 161 .nd_fw_size = ND_INTEL_STATUS_SIZE, 162 }, 163 }; 164 int rc; 165 166 if (!test_bit(NVDIMM_INTEL_UNLOCK_UNIT, &nfit_mem->dsm_mask)) 167 return -ENOTTY; 168 169 memcpy(nd_cmd.cmd.passphrase, key_data->data, 170 sizeof(nd_cmd.cmd.passphrase)); 171 rc = nvdimm_ctl(nvdimm, ND_CMD_CALL, &nd_cmd, sizeof(nd_cmd), NULL); 172 if (rc < 0) 173 return rc; 174 switch (nd_cmd.cmd.status) { 175 case 0: 176 break; 177 case ND_INTEL_STATUS_INVALID_PASS: 178 return -EINVAL; 179 default: 180 return -EIO; 181 } 182 183 /* DIMM unlocked, invalidate all CPU caches before we read it */ 184 nvdimm_invalidate_cache(); 185 186 return 0; 187 } 188 189 static int intel_security_disable(struct nvdimm *nvdimm, 190 const struct nvdimm_key_data *key_data) 191 { 192 int rc; 193 struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm); 194 struct { 195 struct nd_cmd_pkg pkg; 196 struct nd_intel_disable_passphrase cmd; 197 } nd_cmd = { 198 .pkg = { 199 .nd_command = NVDIMM_INTEL_DISABLE_PASSPHRASE, 200 .nd_family = NVDIMM_FAMILY_INTEL, 201 .nd_size_in = ND_INTEL_PASSPHRASE_SIZE, 202 .nd_size_out = ND_INTEL_STATUS_SIZE, 203 .nd_fw_size = ND_INTEL_STATUS_SIZE, 204 }, 205 }; 206 207 if (!test_bit(NVDIMM_INTEL_DISABLE_PASSPHRASE, &nfit_mem->dsm_mask)) 208 return -ENOTTY; 209 210 memcpy(nd_cmd.cmd.passphrase, key_data->data, 211 sizeof(nd_cmd.cmd.passphrase)); 212 rc = nvdimm_ctl(nvdimm, ND_CMD_CALL, &nd_cmd, sizeof(nd_cmd), NULL); 213 if (rc < 0) 214 return rc; 215 216 switch (nd_cmd.cmd.status) { 217 case 0: 218 break; 219 case ND_INTEL_STATUS_INVALID_PASS: 220 return -EINVAL; 221 case ND_INTEL_STATUS_INVALID_STATE: 222 default: 223 return -ENXIO; 224 } 225 226 return 0; 227 } 228 229 static int __maybe_unused intel_security_erase(struct nvdimm *nvdimm, 230 const struct nvdimm_key_data *key, 231 enum nvdimm_passphrase_type ptype) 232 { 233 int rc; 234 struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm); 235 unsigned int cmd = ptype == NVDIMM_MASTER ? 236 NVDIMM_INTEL_MASTER_SECURE_ERASE : NVDIMM_INTEL_SECURE_ERASE; 237 struct { 238 struct nd_cmd_pkg pkg; 239 struct nd_intel_secure_erase cmd; 240 } nd_cmd = { 241 .pkg = { 242 .nd_family = NVDIMM_FAMILY_INTEL, 243 .nd_size_in = ND_INTEL_PASSPHRASE_SIZE, 244 .nd_size_out = ND_INTEL_STATUS_SIZE, 245 .nd_fw_size = ND_INTEL_STATUS_SIZE, 246 .nd_command = cmd, 247 }, 248 }; 249 250 if (!test_bit(cmd, &nfit_mem->dsm_mask)) 251 return -ENOTTY; 252 253 /* flush all cache before we erase DIMM */ 254 nvdimm_invalidate_cache(); 255 memcpy(nd_cmd.cmd.passphrase, key->data, 256 sizeof(nd_cmd.cmd.passphrase)); 257 rc = nvdimm_ctl(nvdimm, ND_CMD_CALL, &nd_cmd, sizeof(nd_cmd), NULL); 258 if (rc < 0) 259 return rc; 260 261 switch (nd_cmd.cmd.status) { 262 case 0: 263 break; 264 case ND_INTEL_STATUS_NOT_SUPPORTED: 265 return -EOPNOTSUPP; 266 case ND_INTEL_STATUS_INVALID_PASS: 267 return -EINVAL; 268 case ND_INTEL_STATUS_INVALID_STATE: 269 default: 270 return -ENXIO; 271 } 272 273 /* DIMM erased, invalidate all CPU caches before we read it */ 274 nvdimm_invalidate_cache(); 275 return 0; 276 } 277 278 static int __maybe_unused intel_security_query_overwrite(struct nvdimm *nvdimm) 279 { 280 int rc; 281 struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm); 282 struct { 283 struct nd_cmd_pkg pkg; 284 struct nd_intel_query_overwrite cmd; 285 } nd_cmd = { 286 .pkg = { 287 .nd_command = NVDIMM_INTEL_QUERY_OVERWRITE, 288 .nd_family = NVDIMM_FAMILY_INTEL, 289 .nd_size_out = ND_INTEL_STATUS_SIZE, 290 .nd_fw_size = ND_INTEL_STATUS_SIZE, 291 }, 292 }; 293 294 if (!test_bit(NVDIMM_INTEL_QUERY_OVERWRITE, &nfit_mem->dsm_mask)) 295 return -ENOTTY; 296 297 rc = nvdimm_ctl(nvdimm, ND_CMD_CALL, &nd_cmd, sizeof(nd_cmd), NULL); 298 if (rc < 0) 299 return rc; 300 301 switch (nd_cmd.cmd.status) { 302 case 0: 303 break; 304 case ND_INTEL_STATUS_OQUERY_INPROGRESS: 305 return -EBUSY; 306 default: 307 return -ENXIO; 308 } 309 310 /* flush all cache before we make the nvdimms available */ 311 nvdimm_invalidate_cache(); 312 return 0; 313 } 314 315 static int __maybe_unused intel_security_overwrite(struct nvdimm *nvdimm, 316 const struct nvdimm_key_data *nkey) 317 { 318 int rc; 319 struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm); 320 struct { 321 struct nd_cmd_pkg pkg; 322 struct nd_intel_overwrite cmd; 323 } nd_cmd = { 324 .pkg = { 325 .nd_command = NVDIMM_INTEL_OVERWRITE, 326 .nd_family = NVDIMM_FAMILY_INTEL, 327 .nd_size_in = ND_INTEL_PASSPHRASE_SIZE, 328 .nd_size_out = ND_INTEL_STATUS_SIZE, 329 .nd_fw_size = ND_INTEL_STATUS_SIZE, 330 }, 331 }; 332 333 if (!test_bit(NVDIMM_INTEL_OVERWRITE, &nfit_mem->dsm_mask)) 334 return -ENOTTY; 335 336 /* flush all cache before we erase DIMM */ 337 nvdimm_invalidate_cache(); 338 memcpy(nd_cmd.cmd.passphrase, nkey->data, 339 sizeof(nd_cmd.cmd.passphrase)); 340 rc = nvdimm_ctl(nvdimm, ND_CMD_CALL, &nd_cmd, sizeof(nd_cmd), NULL); 341 if (rc < 0) 342 return rc; 343 344 switch (nd_cmd.cmd.status) { 345 case 0: 346 return 0; 347 case ND_INTEL_STATUS_OVERWRITE_UNSUPPORTED: 348 return -ENOTSUPP; 349 case ND_INTEL_STATUS_INVALID_PASS: 350 return -EINVAL; 351 case ND_INTEL_STATUS_INVALID_STATE: 352 default: 353 return -ENXIO; 354 } 355 } 356 357 /* 358 * TODO: define a cross arch wbinvd equivalent when/if 359 * NVDIMM_FAMILY_INTEL command support arrives on another arch. 360 */ 361 #ifdef CONFIG_X86 362 static void nvdimm_invalidate_cache(void) 363 { 364 wbinvd_on_all_cpus(); 365 } 366 #else 367 static void nvdimm_invalidate_cache(void) 368 { 369 WARN_ON_ONCE("cache invalidation required after unlock\n"); 370 } 371 #endif 372 373 static const struct nvdimm_security_ops __intel_security_ops = { 374 .state = intel_security_state, 375 .freeze = intel_security_freeze, 376 .change_key = intel_security_change_key, 377 .disable = intel_security_disable, 378 #ifdef CONFIG_X86 379 .unlock = intel_security_unlock, 380 .erase = intel_security_erase, 381 .overwrite = intel_security_overwrite, 382 .query_overwrite = intel_security_query_overwrite, 383 #endif 384 }; 385 386 const struct nvdimm_security_ops *intel_security_ops = &__intel_security_ops; 387