root/drivers/acpi/nfit/intel.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. intel_security_flags
  2. intel_security_freeze
  3. intel_security_change_key
  4. intel_security_unlock
  5. intel_security_disable
  6. intel_security_erase
  7. intel_security_query_overwrite
  8. intel_security_overwrite
  9. nvdimm_invalidate_cache
  10. nvdimm_invalidate_cache

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

/* [<][>][^][v][top][bottom][index][help] */