summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/usr/isteps/nvdimm/nvdimm.C179
1 files changed, 179 insertions, 0 deletions
diff --git a/src/usr/isteps/nvdimm/nvdimm.C b/src/usr/isteps/nvdimm/nvdimm.C
index d66a7f797..b4bded78d 100644
--- a/src/usr/isteps/nvdimm/nvdimm.C
+++ b/src/usr/isteps/nvdimm/nvdimm.C
@@ -42,6 +42,7 @@
#include <isteps/nvdimm/nvdimmreasoncodes.H>
#include <isteps/nvdimm/nvdimm.H>
#include <vpd/spdenums.H>
+#include <secureboot/trustedbootif.H>
using namespace TARGETING;
using namespace DeviceFW;
@@ -84,6 +85,9 @@ constexpr ops_timeoutInfo_t timeoutInfoTable[] =
{"CHARGE", {ES_CHARGE_TIMEOUT1, ES_CHARGE_TIMEOUT0}, CHARGE , MODULE_HEALTH_STATUS1, CHARGE_IN_PROGRESS},
};
+const size_t NUM_KEYS_IN_ATTR = 3;
+const size_t MAX_KEY_SIZE = 32;
+
/**
* @brief Wrapper to call deviceOp to read the NV controller via I2C
*
@@ -1452,6 +1456,181 @@ void nvdimm_restore(TargetHandleList &i_nvdimmList)
}
/**
+ * @brief Entry function to NVDIMM generate keys
+ * Generate encryption keys if required and set the FW key attribute
+ */
+void nvdimm_gen_keys(TargetHandleList &i_nvdimmList)
+{
+ TRACUCOMP(g_trac_nvdimm, ENTER_MRK"nvdimm_gen_keys()");
+ errlHndl_t l_err = nullptr;
+
+ do
+ {
+ // Determine if key generation required
+ Target* l_sys = nullptr;
+ targetService().getTopLevelTarget( l_sys );
+ assert(l_sys, "nvdimm_gen_keys: no TopLevelTarget");
+
+ // Exit if encryption is not enabled via the attribute
+ if (!l_sys->getAttr<ATTR_NVDIMM_ENCRYPTION_ENABLE>())
+ {
+ break;
+ }
+
+ // Get the FW attribute
+ ATTR_NVDIMM_ENCRYPTION_KEYS_FW_type l_attrKeysFw = {0};
+ assert(l_sys->tryGetAttr
+ <ATTR_NVDIMM_ENCRYPTION_KEYS_FW>(l_attrKeysFw),
+ "nvdimm_gen_keys() Failed getting ATTR_NVDIMM_ENCRYPTION_KEYS_FW");
+
+ // FW attribute checks
+ size_t l_attrSizeFw = sizeof(ATTR_NVDIMM_ENCRYPTION_KEYS_FW_type);
+ // Attribute size must be a multiple of the key size
+ assert((l_attrSizeFw % NUM_KEYS_IN_ATTR) == 0,
+ "nvdimm_gen_keys() Size of ATTR_NVDIMM_ENCRYPTION_KEYS_FW is not a multiple of the key size");
+ // Attribute key size must not exceed max size
+ assert((l_attrSizeFw / NUM_KEYS_IN_ATTR) <= MAX_KEY_SIZE,
+ "nvdimm_gen_keys() Size of keys in ATTR_NVDIMM_ENCRYPTION_KEYS_FW is greater than MAX_KEY_SIZE");
+
+ // Check for FW attribute = zero
+ ATTR_NVDIMM_ENCRYPTION_KEYS_FW_type l_fwCompare = {0};
+ bool l_attrIsZeroFw = memcmp(l_attrKeysFw, l_fwCompare, l_attrSizeFw) == 0;
+
+ // Get the anchor attribute
+ ATTR_NVDIMM_ENCRYPTION_KEYS_ANCHOR_type l_attrKeysAnchor = {0};
+ assert(l_sys->tryGetAttr
+ <ATTR_NVDIMM_ENCRYPTION_KEYS_ANCHOR>(l_attrKeysAnchor),
+ "nvdimm_gen_keys() Failed getting ATTR_NVDIMM_ENCRYPTION_KEYS_ANCHOR");
+
+ // Anchor attribute checks
+ size_t l_attrSizeAnchor = sizeof(ATTR_NVDIMM_ENCRYPTION_KEYS_ANCHOR_type);
+ // Attribute size must be a multiple of the key size
+ assert((l_attrSizeAnchor % NUM_KEYS_IN_ATTR) == 0,
+ "nvdimm_gen_keys() Size of ATTR_NVDIMM_ENCRYPTION_KEYS_ANCHOR is not a multiple of the key size");
+ // Attribute key size must not exceed max size
+ assert((l_attrSizeAnchor / NUM_KEYS_IN_ATTR) <= MAX_KEY_SIZE,
+ "nvdimm_gen_keys() Size of keys in ATTR_NVDIMM_ENCRYPTION_KEYS_ANCHOR is greater than MAX_KEY_SIZE");
+
+ // Check for Anchor attribute = zero
+ ATTR_NVDIMM_ENCRYPTION_KEYS_ANCHOR_type l_anchorCompare = {0};
+ bool l_attrIsZeroAnchor = memcmp(l_attrKeysAnchor, l_anchorCompare, l_attrSizeAnchor) == 0;
+
+ // Compare the attribute values
+ if (!l_attrIsZeroFw && !l_attrIsZeroAnchor)
+ {
+ if (memcmp(l_attrKeysFw,l_attrKeysAnchor,l_attrSizeFw) == 0)
+ {
+ TRACFCOMP(g_trac_nvdimm, "nvdimm_gen_keys() ATTR_NVDIMM_ENCRYPTION_KEYS_FW = ATTR_NVDIMM_ENCRYPTION_KEYS_ANCHOR");
+ }
+ if (memcmp(l_attrKeysFw,l_attrKeysAnchor,l_attrSizeFw) != 0)
+ {
+ TRACFCOMP(g_trac_nvdimm, "nvdimm_gen_keys() ATTR_NVDIMM_ENCRYPTION_KEYS_FW != ATTR_NVDIMM_ENCRYPTION_KEYS_ANCHOR");
+ }
+ break;
+ }
+ if (!l_attrIsZeroFw && l_attrIsZeroAnchor)
+ {
+ TRACFCOMP(g_trac_nvdimm, "nvdimm_gen_keys() ATTR_NVDIMM_ENCRYPTION_KEYS_FW != 0 and ATTR_NVDIMM_ENCRYPTION_KEYS_ANCHOR = 0");
+ break;
+ }
+ if (l_attrIsZeroFw && !l_attrIsZeroAnchor)
+ {
+ // Set FW attr = Anchor attr
+ TRACFCOMP(g_trac_nvdimm, "nvdimm_gen_keys() Setting ATTR_NVDIMM_ENCRYPTION_KEYS_FW = ATTR_NVDIMM_ENCRYPTION_KEYS_ANCHOR");
+ l_sys->setAttr<ATTR_NVDIMM_ENCRYPTION_KEYS_FW>(l_attrKeysAnchor);
+ break;
+ }
+
+ // Both key attributes are zero
+ // Generate random keys using the TPM hardware
+ TargetHandleList l_tpmList;
+ TRUSTEDBOOT::getTPMs(l_tpmList,
+ TRUSTEDBOOT::TPM_FILTER::ALL_FUNCTIONAL);
+ if (l_tpmList.size() == 0)
+ {
+ TRACFCOMP(g_trac_nvdimm,ERR_MRK"No functional TPM found, encryption keys not generated.");
+
+ /*@
+ *@errortype
+ *@reasoncode NVDIMM_TPM_NOT_FOUND
+ *@severity ERRORLOG_SEV_PREDICTIVE
+ *@moduleid NVDIMM_GEN_KEYS
+ *@userdata1 <UNUSED>
+ *@userdata2 <UNUSED>
+ *@devdesc Encountered error generating NVDIMM encryption keys
+ *@custdesc NVDIMM error generating encryption keys
+ */
+ l_err = new ERRORLOG::ErrlEntry(
+ ERRORLOG::ERRL_SEV_PREDICTIVE,
+ NVDIMM_GEN_KEYS,
+ NVDIMM_TPM_NOT_FOUND,
+ 0x0,
+ 0x0,
+ ERRORLOG::ErrlEntry::NO_SW_CALLOUT );
+
+ l_err->collectTrace(NVDIMM_COMP_NAME, 1024 );
+
+ // Get all TPMs
+ TRUSTEDBOOT::getTPMs(l_tpmList,
+ TRUSTEDBOOT::TPM_FILTER::ALL_IN_BLUEPRINT);
+ if (l_tpmList.size() == 0)
+ {
+ // No TPMs, we probably have nvdimms enabled
+ // when they should not be
+ l_err->addProcedureCallout(
+ HWAS::EPUB_PRC_HB_CODE,
+ HWAS::SRCI_PRIORITY_HIGH);
+ }
+ else
+ {
+ // If a TPM exists it must be deconfigured,
+ // add callouts accordingly
+ l_err->addProcedureCallout(
+ HWAS::EPUB_PRC_FIND_DECONFIGURED_PART,
+ HWAS::SRCI_PRIORITY_HIGH);
+ l_err->addProcedureCallout(
+ HWAS::EPUB_PRC_HB_CODE,
+ HWAS::SRCI_PRIORITY_MED);
+ }
+
+ errlCommit( l_err, NVDIMM_COMP_ID );
+
+ // Set the status flag for all nvdimms
+ for (const auto & l_nvdimm : i_nvdimmList)
+ {
+ nvdimmSetStatusFlag(l_nvdimm, NSTD_ERR_NOBKUP);
+ }
+
+ break;
+ }
+
+
+ // TPM can only generate up to 34 bytes so gen 1 key at a time
+ size_t l_genSize = l_attrSizeFw / NUM_KEYS_IN_ATTR;
+ uint8_t l_genData[l_genSize] = {0};
+ for (uint32_t l_key=0; l_key<NUM_KEYS_IN_ATTR; l_key++)
+ {
+ l_err = TRUSTEDBOOT::GetRandom(l_tpmList[0], l_genSize, l_genData);
+ if (l_err)
+ {
+ TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimm_gen_keys() Failing Trustedboot::GetRandom()");
+ errlCommit( l_err, NVDIMM_COMP_ID );
+ }
+ memcpy(
+ reinterpret_cast<uint8_t*>(l_attrKeysFw) + (l_key*l_genSize),
+ l_genData,
+ l_genSize );
+ }
+
+ // Set the FW attribute
+ l_sys->setAttr<ATTR_NVDIMM_ENCRYPTION_KEYS_FW>(l_attrKeysFw);
+
+ }while(0);
+
+ TRACUCOMP(g_trac_nvdimm, EXIT_MRK"nvdimm_gen_keys()");
+}
+
+/**
* @brief NVDIMM initialization
* - Checks for ready state
* - Gathers timeout values
OpenPOWER on IntegriCloud