security.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /* Copyright(c) 2022 Intel Corporation. All rights reserved. */
  3. #include <linux/libnvdimm.h>
  4. #include <linux/unaligned.h>
  5. #include <linux/module.h>
  6. #include <linux/async.h>
  7. #include <linux/slab.h>
  8. #include <linux/memregion.h>
  9. #include "cxlmem.h"
  10. #include "cxl.h"
  11. static unsigned long cxl_pmem_get_security_flags(struct nvdimm *nvdimm,
  12. enum nvdimm_passphrase_type ptype)
  13. {
  14. struct cxl_nvdimm *cxl_nvd = nvdimm_provider_data(nvdimm);
  15. struct cxl_memdev *cxlmd = cxl_nvd->cxlmd;
  16. struct cxl_mailbox *cxl_mbox = &cxlmd->cxlds->cxl_mbox;
  17. struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds);
  18. unsigned long security_flags = 0;
  19. struct cxl_get_security_output {
  20. __le32 flags;
  21. } out;
  22. struct cxl_mbox_cmd mbox_cmd;
  23. u32 sec_out;
  24. int rc;
  25. mbox_cmd = (struct cxl_mbox_cmd) {
  26. .opcode = CXL_MBOX_OP_GET_SECURITY_STATE,
  27. .size_out = sizeof(out),
  28. .payload_out = &out,
  29. };
  30. rc = cxl_internal_send_cmd(cxl_mbox, &mbox_cmd);
  31. if (rc < 0)
  32. return 0;
  33. sec_out = le32_to_cpu(out.flags);
  34. /* cache security state */
  35. mds->security.state = sec_out;
  36. if (ptype == NVDIMM_MASTER) {
  37. if (sec_out & CXL_PMEM_SEC_STATE_MASTER_PASS_SET)
  38. set_bit(NVDIMM_SECURITY_UNLOCKED, &security_flags);
  39. else
  40. set_bit(NVDIMM_SECURITY_DISABLED, &security_flags);
  41. if (sec_out & CXL_PMEM_SEC_STATE_MASTER_PLIMIT)
  42. set_bit(NVDIMM_SECURITY_FROZEN, &security_flags);
  43. return security_flags;
  44. }
  45. if (sec_out & CXL_PMEM_SEC_STATE_USER_PASS_SET) {
  46. if (sec_out & CXL_PMEM_SEC_STATE_FROZEN ||
  47. sec_out & CXL_PMEM_SEC_STATE_USER_PLIMIT)
  48. set_bit(NVDIMM_SECURITY_FROZEN, &security_flags);
  49. if (sec_out & CXL_PMEM_SEC_STATE_LOCKED)
  50. set_bit(NVDIMM_SECURITY_LOCKED, &security_flags);
  51. else
  52. set_bit(NVDIMM_SECURITY_UNLOCKED, &security_flags);
  53. } else {
  54. set_bit(NVDIMM_SECURITY_DISABLED, &security_flags);
  55. }
  56. return security_flags;
  57. }
  58. static int cxl_pmem_security_change_key(struct nvdimm *nvdimm,
  59. const struct nvdimm_key_data *old_data,
  60. const struct nvdimm_key_data *new_data,
  61. enum nvdimm_passphrase_type ptype)
  62. {
  63. struct cxl_nvdimm *cxl_nvd = nvdimm_provider_data(nvdimm);
  64. struct cxl_memdev *cxlmd = cxl_nvd->cxlmd;
  65. struct cxl_mailbox *cxl_mbox = &cxlmd->cxlds->cxl_mbox;
  66. struct cxl_mbox_cmd mbox_cmd;
  67. struct cxl_set_pass set_pass;
  68. set_pass = (struct cxl_set_pass) {
  69. .type = ptype == NVDIMM_MASTER ? CXL_PMEM_SEC_PASS_MASTER :
  70. CXL_PMEM_SEC_PASS_USER,
  71. };
  72. memcpy(set_pass.old_pass, old_data->data, NVDIMM_PASSPHRASE_LEN);
  73. memcpy(set_pass.new_pass, new_data->data, NVDIMM_PASSPHRASE_LEN);
  74. mbox_cmd = (struct cxl_mbox_cmd) {
  75. .opcode = CXL_MBOX_OP_SET_PASSPHRASE,
  76. .size_in = sizeof(set_pass),
  77. .payload_in = &set_pass,
  78. };
  79. return cxl_internal_send_cmd(cxl_mbox, &mbox_cmd);
  80. }
  81. static int __cxl_pmem_security_disable(struct nvdimm *nvdimm,
  82. const struct nvdimm_key_data *key_data,
  83. enum nvdimm_passphrase_type ptype)
  84. {
  85. struct cxl_nvdimm *cxl_nvd = nvdimm_provider_data(nvdimm);
  86. struct cxl_memdev *cxlmd = cxl_nvd->cxlmd;
  87. struct cxl_mailbox *cxl_mbox = &cxlmd->cxlds->cxl_mbox;
  88. struct cxl_disable_pass dis_pass;
  89. struct cxl_mbox_cmd mbox_cmd;
  90. dis_pass = (struct cxl_disable_pass) {
  91. .type = ptype == NVDIMM_MASTER ? CXL_PMEM_SEC_PASS_MASTER :
  92. CXL_PMEM_SEC_PASS_USER,
  93. };
  94. memcpy(dis_pass.pass, key_data->data, NVDIMM_PASSPHRASE_LEN);
  95. mbox_cmd = (struct cxl_mbox_cmd) {
  96. .opcode = CXL_MBOX_OP_DISABLE_PASSPHRASE,
  97. .size_in = sizeof(dis_pass),
  98. .payload_in = &dis_pass,
  99. };
  100. return cxl_internal_send_cmd(cxl_mbox, &mbox_cmd);
  101. }
  102. static int cxl_pmem_security_disable(struct nvdimm *nvdimm,
  103. const struct nvdimm_key_data *key_data)
  104. {
  105. return __cxl_pmem_security_disable(nvdimm, key_data, NVDIMM_USER);
  106. }
  107. static int cxl_pmem_security_disable_master(struct nvdimm *nvdimm,
  108. const struct nvdimm_key_data *key_data)
  109. {
  110. return __cxl_pmem_security_disable(nvdimm, key_data, NVDIMM_MASTER);
  111. }
  112. static int cxl_pmem_security_freeze(struct nvdimm *nvdimm)
  113. {
  114. struct cxl_nvdimm *cxl_nvd = nvdimm_provider_data(nvdimm);
  115. struct cxl_memdev *cxlmd = cxl_nvd->cxlmd;
  116. struct cxl_mailbox *cxl_mbox = &cxlmd->cxlds->cxl_mbox;
  117. struct cxl_mbox_cmd mbox_cmd = {
  118. .opcode = CXL_MBOX_OP_FREEZE_SECURITY,
  119. };
  120. return cxl_internal_send_cmd(cxl_mbox, &mbox_cmd);
  121. }
  122. static int cxl_pmem_security_unlock(struct nvdimm *nvdimm,
  123. const struct nvdimm_key_data *key_data)
  124. {
  125. struct cxl_nvdimm *cxl_nvd = nvdimm_provider_data(nvdimm);
  126. struct cxl_memdev *cxlmd = cxl_nvd->cxlmd;
  127. struct cxl_mailbox *cxl_mbox = &cxlmd->cxlds->cxl_mbox;
  128. u8 pass[NVDIMM_PASSPHRASE_LEN];
  129. struct cxl_mbox_cmd mbox_cmd;
  130. int rc;
  131. memcpy(pass, key_data->data, NVDIMM_PASSPHRASE_LEN);
  132. mbox_cmd = (struct cxl_mbox_cmd) {
  133. .opcode = CXL_MBOX_OP_UNLOCK,
  134. .size_in = NVDIMM_PASSPHRASE_LEN,
  135. .payload_in = pass,
  136. };
  137. rc = cxl_internal_send_cmd(cxl_mbox, &mbox_cmd);
  138. if (rc < 0)
  139. return rc;
  140. return 0;
  141. }
  142. static int cxl_pmem_security_passphrase_erase(struct nvdimm *nvdimm,
  143. const struct nvdimm_key_data *key,
  144. enum nvdimm_passphrase_type ptype)
  145. {
  146. struct cxl_nvdimm *cxl_nvd = nvdimm_provider_data(nvdimm);
  147. struct cxl_memdev *cxlmd = cxl_nvd->cxlmd;
  148. struct cxl_mailbox *cxl_mbox = &cxlmd->cxlds->cxl_mbox;
  149. struct cxl_mbox_cmd mbox_cmd;
  150. struct cxl_pass_erase erase;
  151. int rc;
  152. erase = (struct cxl_pass_erase) {
  153. .type = ptype == NVDIMM_MASTER ? CXL_PMEM_SEC_PASS_MASTER :
  154. CXL_PMEM_SEC_PASS_USER,
  155. };
  156. memcpy(erase.pass, key->data, NVDIMM_PASSPHRASE_LEN);
  157. mbox_cmd = (struct cxl_mbox_cmd) {
  158. .opcode = CXL_MBOX_OP_PASSPHRASE_SECURE_ERASE,
  159. .size_in = sizeof(erase),
  160. .payload_in = &erase,
  161. };
  162. rc = cxl_internal_send_cmd(cxl_mbox, &mbox_cmd);
  163. if (rc < 0)
  164. return rc;
  165. return 0;
  166. }
  167. static const struct nvdimm_security_ops __cxl_security_ops = {
  168. .get_flags = cxl_pmem_get_security_flags,
  169. .change_key = cxl_pmem_security_change_key,
  170. .disable = cxl_pmem_security_disable,
  171. .freeze = cxl_pmem_security_freeze,
  172. .unlock = cxl_pmem_security_unlock,
  173. .erase = cxl_pmem_security_passphrase_erase,
  174. .disable_master = cxl_pmem_security_disable_master,
  175. };
  176. const struct nvdimm_security_ops *cxl_security_ops = &__cxl_security_ops;