aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMauro S. M. Rodrigues <maurosr@linux.vnet.ibm.com>2020-06-01 17:34:35 -0300
committerOliver O'Halloran <oohall@gmail.com>2020-10-01 13:42:40 +1000
commitf0f29cbe8c208f0e1e9f723476a6435524fc4c73 (patch)
tree9d8fd281e09455b2e64656fb3672aca898af72e3
parent86660b06d12baf04588c79fe4fefde9ca554abdd (diff)
downloadskiboot-f0f29cbe8c208f0e1e9f723476a6435524fc4c73.zip
skiboot-f0f29cbe8c208f0e1e9f723476a6435524fc4c73.tar.gz
skiboot-f0f29cbe8c208f0e1e9f723476a6435524fc4c73.tar.bz2
libstb/tss2: Add TSS wrapping functions
In this commit we add some fundamental TSS operations: - tss_nv_read_public - tss_nv_read - tss_nv_write - tss_nv_write_lock - tss_nv_define_space - tss_nv_undefine_space - tss_get_defined_nv_indices - tss_pcr_extend - tss_pcr_read - tss_get_random_number - tss_set_platform_auth Co-authored-by: Eric Richter <erichte@linux.ibm.com> Co-authored-by: Ryan Grimm <grimm@linux.ibm.com> Signed-off-by: Mauro S. M. Rodrigues <maurosr@linux.vnet.ibm.com> Signed-off-by: Mauro S. M. Rodrigues <maurosr@linux.vnet.ibm.com> Signed-off-by: Oliver O'Halloran <oohall@gmail.com>
-rw-r--r--libstb/tss2/tssskiboot.c727
-rw-r--r--libstb/tss2/tssskiboot.h26
2 files changed, 753 insertions, 0 deletions
diff --git a/libstb/tss2/tssskiboot.c b/libstb/tss2/tssskiboot.c
new file mode 100644
index 0000000..5f6d761
--- /dev/null
+++ b/libstb/tss2/tssskiboot.c
@@ -0,0 +1,727 @@
+// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+/* Copyright 2020 IBM Corp. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <skiboot.h>
+#include <opal-api.h>
+#include <tssskiboot.h>
+#include <tpm_chip.h>
+#include <ibmtss/tssfile.h>
+#include <ibmtss/TPM_Types.h>
+#include <ibmtss/tssmarshal.h>
+#include <ibmtss/tssresponsecode.h>
+
+/*
+ * Helper to string-fy TSS error response codes.
+ */
+static void tss_error_trace(const char *function, TPM_RC rc)
+{
+ const char *msg;
+ const char *submsg;
+ const char *num;
+ prlog(PR_ERR, "%s: failed, rc %08x\n", function, rc);
+ TSS_ResponseCode_toString(&msg, &submsg, &num, rc);
+ prlog(PR_ERR, "%s%s%s\n", msg, submsg, num);
+}
+
+/*
+ * @brief Reads the public and name area of a NV Index.
+ * @param nv_index The target NV index to read public info from.
+ * @param nv_public buffer to save public are read from nv index
+ * @param nv_name buffer to save nv index name.
+ */
+int tss_nv_read_public(TPMI_RH_NV_INDEX nv_index, TPMS_NV_PUBLIC *nv_public,
+ TPM2B_NAME *nv_name)
+{
+ NV_ReadPublic_Out *out = NULL;
+ NV_ReadPublic_In *in = NULL;
+ TSS_CONTEXT *context = NULL;
+ TPM_RC rc = OPAL_SUCCESS;
+
+ if (!nv_public || !nv_name) {
+ rc = OPAL_PARAMETER;
+ goto cleanup;
+ }
+
+ in = zalloc(sizeof(NV_ReadPublic_In));
+ if (!in) {
+ rc = OPAL_NO_MEM;
+ goto cleanup;
+ }
+
+ out = zalloc(sizeof(NV_ReadPublic_Out));
+ if (!out) {
+ rc = OPAL_NO_MEM;
+ goto cleanup;
+ }
+
+ rc = TSS_Create(&context);
+ if (rc) {
+ tss_error_trace("tss_nv_read_public", rc);
+ rc = OPAL_NO_MEM;
+ goto cleanup;
+ }
+
+ in->nvIndex = nv_index;
+ rc = TSS_Execute(context,
+ (RESPONSE_PARAMETERS *) out,
+ (COMMAND_PARAMETERS *) in,
+ NULL,
+ TPM_CC_NV_ReadPublic,
+ TPM_RH_NULL, NULL, 0);
+ if (!rc) {
+ memcpy(nv_public, &out->nvPublic, sizeof(TPMS_NV_PUBLIC));
+ memcpy(nv_name, &out->nvName, sizeof(TPM2B_NAME));
+ }
+ else
+ tss_error_trace("tss_nv_read_public", rc);
+cleanup:
+ free(in);
+ free(out);
+ TSS_Delete(context);
+ return rc;
+}
+
+/* @brief This command reads a value from an area previously defined using
+ * nv_define_space
+ * @param nv_index The target NV index to read from.
+ * @param buffer buffer to save the data read.
+ * @param buffer_size size of the buffer, to avoid overflow.
+ * @param offset position where to start the nv read operation.
+ */
+int tss_nv_read(TPMI_RH_NV_INDEX nv_index, void *buffer,
+ size_t buffer_size, uint16_t offset)
+{
+ TSS_CONTEXT *context = NULL;
+ NV_Read_Out *out = NULL;
+ NV_Read_In *in = NULL;
+ TPM_RC rc = OPAL_SUCCESS;
+
+ if (!buffer) {
+ rc = OPAL_PARAMETER;
+ goto cleanup;
+ }
+
+ in = zalloc(sizeof(NV_Read_In));
+ if (!in) {
+ rc = OPAL_NO_MEM;
+ goto cleanup;
+ }
+
+ out = zalloc(sizeof(NV_Read_Out));
+ if (!out) {
+ rc = OPAL_NO_MEM;
+ goto cleanup;
+ }
+
+ rc = TSS_Create(&context);
+ if (rc) {
+ tss_error_trace("tss_nv_read", rc);
+ rc = OPAL_NO_MEM;
+ goto cleanup;
+ }
+
+ in->nvIndex = nv_index;
+ in->authHandle = nv_index;
+ in->offset = offset;
+ in->size = buffer_size;
+
+ rc = TSS_Execute(context,
+ (RESPONSE_PARAMETERS *) out,
+ (COMMAND_PARAMETERS *) in,
+ NULL,
+ TPM_CC_NV_Read,
+ TPM_RS_PW, NULL, 0,
+ TPM_RH_NULL, NULL, 0);
+
+ if (!rc)
+ memcpy(buffer, out->data.b.buffer, buffer_size);
+ else
+ tss_error_trace("tss_nv_read", rc);
+
+cleanup:
+ TSS_Delete(context);
+ free(in);
+ free(out);
+ return rc;
+}
+
+/* @brief This command writes a value in an area previously defined using
+ * nv_define_space
+ * @param nv_index The target NV index to write to.
+ * @param buffer buffer containing the data write.
+ * @param buffer_size size of the buffer to write.
+ * @param offset position where to start the nv write operation.
+ */
+int tss_nv_write(TPMI_RH_NV_INDEX nv_index, void *buffer,
+ size_t buffer_size, uint16_t offset)
+{
+ TSS_CONTEXT *context = NULL;
+ NV_Write_In *in = NULL;
+ TPM_RC rc = OPAL_SUCCESS;
+
+ if (!buffer) {
+ rc = OPAL_PARAMETER;
+ goto cleanup;
+ }
+
+ in = zalloc(sizeof(NV_Write_In));
+ if (!in) {
+ rc = OPAL_NO_MEM;
+ goto cleanup;
+ }
+
+ rc = TSS_Create(&context);
+ if (rc) {
+ tss_error_trace("tss_nv_write", rc);
+ rc = OPAL_NO_MEM;
+ goto cleanup;
+ }
+
+ in->nvIndex = nv_index;
+ in->authHandle = TPM_RH_PLATFORM;
+ in->offset = offset;
+ rc = TSS_TPM2B_Create(&in->data.b, buffer, buffer_size,
+ sizeof(in->data.t.buffer));
+ if (rc) {
+ tss_error_trace("tss_nv_write", rc);
+ goto cleanup;
+ }
+
+ rc = TSS_Execute(context,
+ NULL,
+ (COMMAND_PARAMETERS *) in,
+ NULL,
+ TPM_CC_NV_Write,
+ TPM_RS_PW, NULL, 0,
+ TPM_RH_NULL, NULL, 0);
+ if (rc)
+ tss_error_trace("tss_nv_write", rc);
+cleanup:
+ TSS_Delete(context);
+ free(in);
+ return rc;
+}
+
+/*
+ * @brief This command locks an area, pointed by the index and previously
+ * defined using nv_define_space, preventing further writing operations on it.
+ * @param nv_index The target NV index to lock.
+ */
+int tss_nv_write_lock(TPMI_RH_NV_INDEX nv_index)
+{
+ TSS_CONTEXT *context = NULL;
+ NV_WriteLock_In *in = NULL;
+ TPM_RC rc = OPAL_SUCCESS;
+
+ in = zalloc(sizeof(NV_WriteLock_In));
+ if (!in) {
+ rc = OPAL_NO_MEM;
+ goto cleanup;
+ }
+
+ rc = TSS_Create(&context);
+ if (rc) {
+ rc = OPAL_NO_MEM;
+ goto cleanup;
+ }
+
+ in->authHandle = TPM_RH_PLATFORM;
+ in->nvIndex = nv_index;
+ rc = TSS_Execute(context,
+ NULL,
+ (COMMAND_PARAMETERS *) in,
+ NULL,
+ TPM_CC_NV_WriteLock,
+ TPM_RS_PW, NULL, 0,
+ TPM_RH_NULL, NULL, 0);
+ if (rc)
+ tss_error_trace("tss_nv_write_lock", rc);
+cleanup:
+ TSS_Delete(context);
+ free(in);
+ return rc;
+}
+
+ /*
+ * @brief This command defines the area pointed by nv index and its attributes.
+ * @param nv_index The target NV index to define.
+ * @param data_size size of the area to be defined.
+ */
+int tss_nv_define_space(TPMI_RH_NV_INDEX nv_index, uint16_t data_size)
+{
+ NV_DefineSpace_In *in = NULL;
+ TSS_CONTEXT *context = NULL;
+ TPM_RC rc = OPAL_SUCCESS;
+
+ in = zalloc(sizeof(NV_DefineSpace_In));
+ if (!in) {
+ rc = OPAL_NO_MEM;
+ goto cleanup;
+ }
+
+ rc = TSS_Create(&context);
+ if (rc) {
+ rc = OPAL_NO_MEM;
+ goto cleanup;
+ }
+
+ in->authHandle = TPM_RH_PLATFORM;
+
+ in->publicInfo.nvPublic.nvIndex = nv_index;
+ in->publicInfo.nvPublic.dataSize = data_size;
+ /* password is NULL so b.size is 0 */
+ in->auth.b.size = 0;
+ /* Empty policy, so size is 0 */
+ in->publicInfo.nvPublic.authPolicy.t.size = 0;
+ /* Used algorithm is SHA256 */
+ in->publicInfo.nvPublic.nameAlg = TPM_ALG_SHA256;
+ /*
+ * This carries the flags set according to default settings, excepting
+ * for what is set by this function parameters. Further customization
+ * will require a different setup for nvAttribute flags as is done in
+ * TSS's code.
+ */
+ in->publicInfo.nvPublic.attributes.val = (TPMA_NVA_PPWRITE |
+ TPMA_NVA_ORDINARY |
+ TPMA_NVA_WRITE_STCLEAR |
+ TPMA_NVA_AUTHREAD |
+ TPMA_NVA_PLATFORMCREATE |
+ TPMA_NVA_NO_DA);
+
+ rc = TSS_Execute(context,
+ NULL,
+ (COMMAND_PARAMETERS *)in,
+ NULL,
+ TPM_CC_NV_DefineSpace,
+ TPM_RS_PW, NULL, 0,
+ TPM_RH_NULL, NULL, 0);
+ if (rc) {
+ tss_error_trace("tss_nv_define_space", rc);
+ switch(rc) {
+ case TPM_RC_NV_DEFINED:
+ rc = OPAL_WRONG_STATE;
+ break;
+ default:
+ break;
+ }
+ }
+cleanup:
+ TSS_Delete(context);
+ free(in);
+ return rc;
+}
+
+/*
+ * @brief Extends a PCR using the given hashes and digest
+ * @param pcr_handle The PCR to be extended
+ * @param alg_hashes A pointer to an array of hash algorithms, each
+ * one used to extend its respective PCR bank.
+ * @param alg_hash_count The number of elements in alg_hashes array
+ * @param digests The digest data.
+ */
+int tss_pcr_extend(TPMI_DH_PCR pcr_handle, TPMI_ALG_HASH *alg_hashes,
+ uint8_t alg_hash_count, const uint8_t **digests)
+{
+ TSS_CONTEXT *context = NULL;
+ uint32_t rc = OPAL_SUCCESS;
+ PCR_Extend_In *in = NULL;
+ uint16_t digest_size;
+
+ if (!alg_hashes || !digests || pcr_handle >= IMPLEMENTATION_PCR) {
+ rc = OPAL_PARAMETER;
+ goto cleanup;
+ }
+
+ in = zalloc(sizeof(PCR_Extend_In));
+ if (!in) {
+ rc = OPAL_NO_MEM;
+ goto cleanup;
+ }
+
+ rc = TSS_Create(&context);
+ if (rc) {
+ tss_error_trace("tss_pcr_extend", rc);
+ rc = OPAL_NO_MEM;
+ goto cleanup;
+ }
+
+ if (alg_hash_count >= HASH_COUNT) {
+ rc = OPAL_PARAMETER;
+ goto cleanup;
+ }
+
+ in->digests.count = alg_hash_count;
+ in->pcrHandle = pcr_handle;
+ for (uint8_t i=0; i < alg_hash_count; i++) {
+ in->digests.digests[i].hashAlg = alg_hashes[i];
+ /* memset zeroes first to assure the digest data is zero
+ * padded.*/
+ memset((uint8_t*) &in->digests.digests[i].digest, 0,
+ sizeof(TPMU_HA));
+
+ digest_size = 0;
+ /* Marshal the digest in order to obtain its size. This is a
+ * commonly used pattern in TSS.
+ */
+ rc = TSS_TPMU_HA_Marshalu((const TPMU_HA *)digests[i],
+ &digest_size, NULL, NULL ,
+ alg_hashes[i]);
+ if (rc)
+ goto cleanup;
+ memcpy((uint8_t*) &in->digests.digests[i].digest, digests[i],
+ digest_size);
+ }
+ rc = TSS_Execute(context,
+ NULL,
+ (COMMAND_PARAMETERS *) in,
+ NULL,
+ TPM_CC_PCR_Extend,
+ TPM_RS_PW, NULL, 0,
+ TPM_RH_NULL, NULL, 0);
+ if (rc)
+ tss_error_trace("tss_pcr_extend", rc);
+cleanup:
+ TSS_Delete(context);
+ free(in);
+ return rc;
+}
+
+/*
+ * @brief reads pcr values of a given pcr handle.
+ * @param pcr_handle The PCR to be extended
+ * @param alg_hashes A pointer to an array of hash algorithms, each
+ * one used to extend its respective PCR bank.
+ * @param alg_hash_count The length of alg hashes array
+ */
+int tss_pcr_read(TPMI_DH_PCR pcr_handle, TPMI_ALG_HASH *alg_hashes,
+ uint8_t alg_hash_count)
+{
+ TSS_CONTEXT *context = NULL;
+ PCR_Read_Out *out = NULL;
+ PCR_Read_In *in = NULL;
+ uint32_t rc = OPAL_SUCCESS;
+
+ if (!alg_hashes) {
+ rc = OPAL_PARAMETER;
+ goto cleanup;
+ }
+
+ in = zalloc(sizeof(PCR_Read_In));
+ if (!in) {
+ rc = OPAL_NO_MEM;
+ goto cleanup;
+ }
+
+ out = zalloc(sizeof(PCR_Read_Out));
+ if (!out) {
+ rc = OPAL_NO_MEM;
+ goto cleanup;
+ }
+
+ rc = TSS_Create(&context);
+ if (!rc) {
+ tss_error_trace("tss_pcr_read", rc);
+ rc = OPAL_NO_MEM;
+ goto cleanup;
+ }
+
+ in->pcrSelectionIn.count = alg_hash_count;
+ for (int i=0; i < alg_hash_count; i++) {
+ in->pcrSelectionIn.pcrSelections[i].hash = alg_hashes[i];
+ in->pcrSelectionIn.pcrSelections[i].sizeofSelect = 3;
+ in->pcrSelectionIn.pcrSelections[i].pcrSelect[0] = 0;
+ in->pcrSelectionIn.pcrSelections[i].pcrSelect[1] = 0;
+ in->pcrSelectionIn.pcrSelections[i].pcrSelect[2] = 0;
+ in->pcrSelectionIn.pcrSelections[i].pcrSelect[pcr_handle/8] = 1 << (pcr_handle % 8);
+ }
+
+ rc = TSS_Execute(context,
+ (RESPONSE_PARAMETERS *) out,
+ (COMMAND_PARAMETERS *) in,
+ NULL,
+ TPM_CC_PCR_Read,
+ TPM_RH_NULL, NULL, 0);
+ if (rc)
+ tss_error_trace("tss_pcr_read", rc);
+cleanup:
+ TSS_Delete(context);
+ free(in);
+ free(out);
+ return rc;
+}
+
+/*
+ * @brief returns next bytes_requested bytes from the TPM RNG
+ * @param buffer Buffer to save the generated numbers.
+ * @param bytes_requested How many random bytes are requested.
+ */
+int tss_get_random_number(void *buffer, uint16_t bytes_requested)
+{
+ TSS_CONTEXT *context = NULL;
+ GetRandom_Out *out = NULL;
+ TPM_RC rc = OPAL_SUCCESS;
+ GetRandom_In *in = NULL;
+ void *p_buffer = buffer;
+
+ if (!buffer) {
+ rc = OPAL_PARAMETER;
+ goto cleanup;
+ }
+
+ in = zalloc(sizeof(GetRandom_In));
+ if (!in) {
+ rc = OPAL_NO_MEM;
+ goto cleanup;
+ }
+
+ out = zalloc(sizeof(GetRandom_Out));
+ if (!out) {
+ rc = OPAL_NO_MEM;
+ goto cleanup;
+ }
+
+ rc = TSS_Create(&context);
+ if (rc) {
+ tss_error_trace("tss_get_random_number", rc);
+ rc = OPAL_NO_MEM;
+ goto cleanup;
+ }
+
+ /*
+ * Even though we request a specific number of bytes, there is no
+ * guarantee that TPM will return that number of bytes, so we ask again
+ * until we reach the desired total of bytes or rng function fails
+ */
+ for (uint16_t bytes_copied = 0; bytes_copied < bytes_requested; ) {
+ in->bytesRequested = bytes_requested - bytes_copied;
+ rc = TSS_Execute(context,
+ (RESPONSE_PARAMETERS *)out,
+ (COMMAND_PARAMETERS *)in,
+ NULL, TPM_CC_GetRandom,
+ TPM_RH_NULL, NULL, 0);
+ if (!rc){
+ memcpy(p_buffer, out->randomBytes.t.buffer,
+ out->randomBytes.t.size);
+ bytes_copied += out->randomBytes.t.size;
+ p_buffer += bytes_copied;
+ /* explicitly clean up output's buffer from memory on
+ * every iteration, since the size will vary, to avoid
+ * some kind of exploitation.
+ */
+ memset(out->randomBytes.t.buffer, 0,
+ out->randomBytes.t.size);
+
+ }
+ else {
+ tss_error_trace("tss_get_random_number", rc);
+ break;
+ }
+ }
+
+cleanup:
+ TSS_Delete(context);
+ free(in);
+ free(out);
+ return rc;
+}
+
+/* local helper to generate random password without zeroes */
+static int generate_random_passwd(char *passwd, uint16_t passwd_len)
+{
+ TPM_RC rc = OPAL_SUCCESS;
+ char *buffer = NULL;
+ int bytes_copied;
+ int i;
+
+ buffer = zalloc(passwd_len);
+ if (!buffer) {
+ rc = OPAL_NO_MEM;
+ goto cleanup;
+ }
+
+ bytes_copied = 0;
+ while ((rc == 0) && (bytes_copied < passwd_len)) {
+ rc = tss_get_random_number(buffer, passwd_len);
+ if (rc)
+ goto cleanup;
+
+ /* Copy as many bytes as were received or until bytes requested */
+ for (i = 0; (i < passwd_len) &&
+ (bytes_copied < passwd_len); i++) {
+
+ /* Skip zero bytes */
+ if (buffer[i] == 0)
+ continue;
+ passwd[bytes_copied] = buffer[i];
+ bytes_copied++;
+ }
+ }
+cleanup:
+ free(buffer);
+ return rc;
+}
+
+/*
+ * @brief This command allows the authorization secret for a hierarchy to be
+ * changed.
+ */
+int tss_set_platform_auth(void)
+{
+ HierarchyChangeAuth_In *in = NULL;
+ TSS_CONTEXT *context = NULL;
+ TPM_RC rc = OPAL_SUCCESS;
+ char *key_passwd = NULL;
+
+ in = zalloc(sizeof(HierarchyChangeAuth_In));
+ if (!in) {
+ rc = OPAL_NO_MEM;
+ goto cleanup;
+ }
+
+ key_passwd = zalloc(TSS_AUTH_PASSWD_LEN + 1);
+ if (!key_passwd) {
+ rc = OPAL_NO_MEM;
+ goto cleanup;
+ }
+
+ rc = TSS_Create(&context);
+ if (rc) {
+ tss_error_trace("tss_set_platform_auth", rc);
+ rc = OPAL_NO_MEM;
+ goto cleanup;
+ }
+
+ rc = generate_random_passwd(key_passwd, TSS_AUTH_PASSWD_LEN);
+ if (rc) {
+ tss_error_trace("Failed to generate the auth password", rc);
+ goto cleanup;
+ }
+ key_passwd[TSS_AUTH_PASSWD_LEN] = 0;
+
+ in->authHandle = TPM_RH_PLATFORM;
+ rc = TSS_TPM2B_StringCopy(&in->newAuth.b, key_passwd,
+ sizeof(in->newAuth.t.buffer));
+ if (rc) {
+ tss_error_trace("tss_set_platform_auth", rc);
+ goto cleanup;
+ }
+
+ rc = TSS_Execute(context,
+ NULL,
+ (COMMAND_PARAMETERS *)in,
+ NULL,
+ TPM_CC_HierarchyChangeAuth,
+ TPM_RS_PW, NULL, 0,
+ TPM_RH_NULL, NULL, 0);
+ if (rc)
+ tss_error_trace("tss_set_platform_auth", rc);
+
+cleanup:
+ TSS_Delete(context);
+ free(in);
+ /* explicitly clean up password from memory to avoid some kind of
+ * exploitation.
+ */
+ memset(key_passwd, 0, TSS_AUTH_PASSWD_LEN + 1);
+ free(key_passwd);
+ return rc;
+}
+
+/*
+ * @brief returns a list of defined NV indices
+ * @param pcr_handle The PCR to be extended
+ * @param alg_hashes A pointer to an array of hash algorithms, each
+ * one used to extend its respective PCR bank.
+ * @param alg_hash_count The length of alg hashes array
+ */
+int tss_get_defined_nv_indices(TPMI_RH_NV_INDEX **indices, size_t *count)
+{
+ TSS_CONTEXT *context = NULL;
+ GetCapability_In *in = NULL;
+ GetCapability_Out *out = NULL;
+ uint32_t rc = OPAL_SUCCESS;
+ TPML_HANDLE *handles;
+
+ in = zalloc(sizeof(GetCapability_In));
+ if (!in) {
+ rc = OPAL_NO_MEM;
+ goto cleanup;
+ }
+
+ out = zalloc(sizeof(GetCapability_Out));
+ if (!out) {
+ rc = OPAL_NO_MEM;
+ goto cleanup;
+ }
+
+ rc = TSS_Create(&context);
+ if (rc) {
+ tss_error_trace("tss_check_nv_index", rc);
+ rc = OPAL_NO_MEM;
+ goto cleanup;
+ }
+
+ in->capability = 1;
+ in->property = 0x01000000;
+ in->propertyCount = 64;
+
+ rc = TSS_Execute(context,
+ (RESPONSE_PARAMETERS *) out,
+ (COMMAND_PARAMETERS *) in,
+ NULL,
+ TPM_CC_GetCapability,
+ TPM_RH_NULL, NULL, 0);
+ if (rc) {
+ tss_error_trace("tss_check_nv_index", rc);
+ goto cleanup;
+ }
+
+ handles = (TPML_HANDLE *) &out->capabilityData.data;
+ *count = handles->count;
+ *indices = malloc(*count * sizeof(TPMI_RH_NV_INDEX));
+ if (!indices) {
+ rc = OPAL_NO_MEM;
+ goto cleanup;
+ }
+
+ memcpy(*indices, handles->handle, *count * sizeof(TPMI_RH_NV_INDEX));
+
+cleanup:
+ TSS_Delete(context);
+ free(in);
+ free(out);
+ return rc;
+}
+
+
+int tss_nv_undefine_space(TPMI_RH_NV_INDEX nv_index)
+{
+ int rc;
+ TSS_CONTEXT *context = NULL;
+ NV_UndefineSpace_In in;
+
+ rc = TSS_Create(&context);
+ if (rc) {
+ tss_error_trace("tss_check_nv_undefine_index", rc);
+ rc = OPAL_NO_MEM;
+ return rc;
+ }
+
+ in.authHandle = TPM_RH_PLATFORM;
+ in.nvIndex = nv_index;
+
+ rc = TSS_Execute(context, NULL,
+ (COMMAND_PARAMETERS *) &in,
+ NULL,
+ TPM_CC_NV_UndefineSpace,
+ TPM_RS_PW, NULL, 0,
+ TPM_RH_NULL, NULL, 0);
+ if (rc)
+ tss_error_trace("tss_check_nv_index", rc);
+
+ TSS_Delete(context);
+ return rc;
+}
diff --git a/libstb/tss2/tssskiboot.h b/libstb/tss2/tssskiboot.h
new file mode 100644
index 0000000..0b8cb74
--- /dev/null
+++ b/libstb/tss2/tssskiboot.h
@@ -0,0 +1,26 @@
+// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+/* Copyright 2020 IBM Corp. */
+
+#ifndef TSSSKIBOOT_H
+#define TSSSKIBOOT_H
+
+#include <ibmtss/tss.h>
+
+#define TSS_AUTH_PASSWD_LEN 32
+int tss_nv_read_public(TPMI_RH_NV_INDEX nv_index, TPMS_NV_PUBLIC *nv_public,
+ TPM2B_NAME *nv_name);
+int tss_nv_read(TPMI_RH_NV_INDEX nv_index, void *buffer, size_t buffer_size,
+ uint16_t offset);
+int tss_nv_write(TPMI_RH_NV_INDEX nv_index, void *buffer, size_t buffer_size,
+ uint16_t offset);
+int tss_nv_write_lock(TPMI_RH_NV_INDEX nv_index);
+int tss_nv_define_space(TPMI_RH_NV_INDEX nv_index, uint16_t data_size);
+int tss_pcr_extend(TPMI_DH_PCR pcr_handle, TPMI_ALG_HASH *alg_hashes,
+ uint8_t hashes_count, const uint8_t **digests);
+int tss_pcr_read(TPMI_DH_PCR pcr_handle, TPMI_ALG_HASH *alg_hashes,
+ uint8_t hashes_count);
+int tss_get_random_number(void *buffer, uint16_t bytes_requested);
+int tss_set_platform_auth(void);
+int tss_get_defined_nv_indices(TPMI_RH_NV_INDEX **indices, size_t *count);
+int tss_nv_undefine_space(TPMI_RH_NV_INDEX nv_index);
+#endif /* TSSSKIBOOT_H */