[PATCH v3 5/5] Add Support for the Intel TSS

James Bottomley James.Bottomley at HansenPartnership.com
Tue Mar 9 22:50:32 CET 2021


The Intel TSS is somewhat of a moving target, so this wraps support
for this TSS into tpm2daemon.  Unfortunately this wrapper uses some
APIs that are only present in a relatively recent Intel TSS, so it
looks like it will only work with version 2.4.0 or higher.

Signed-off-by: James Bottomley <James.Bottomley at HansenPartnership.com>
---
 configure.ac      |  29 +-
 tpm2d/intel-tss.h | 667 ++++++++++++++++++++++++++++++++++++++++++++++
 tpm2d/tpm2.h      |   4 +
 3 files changed, 694 insertions(+), 6 deletions(-)
 create mode 100644 tpm2d/intel-tss.h

diff --git a/configure.ac b/configure.ac
index a7e891e5e..72abbc032 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1596,8 +1596,9 @@ AC_SUBST(W32SOCKLIBS)
 _save_libs="$LIBS"
 _save_cflags="$CFLAGS"
 LIBS=""
-AC_SEARCH_LIBS([TSS_Create], [tss ibmtss],have_libtss=yes,)
-if test "$have_libtss" = yes; then
+AC_SEARCH_LIBS([TSS_Create], [tss ibmtss],have_libtss=IBM,
+    AC_SEARCH_LIBS([Esys_Initialize], [tss2-esys],have_libtss=Intel))
+if test "$have_libtss" = IBM; then
     LIBTSS_CFLAGS="-DTPM_POSIX"
     CFLAGS="$CFLAGS ${LIBTSS_CFLAGS}"
     AC_CHECK_HEADER([tss2/tss.h],[AC_DEFINE(TSS_INCLUDE,tss2, [tss2 include location])], [
@@ -1607,18 +1608,34 @@ if test "$have_libtss" = yes; then
 	])
     ])
     LIBTSS_LIBS=$LIBS
-    AC_DEFINE(HAVE_LIBTSS, 1, [Defined if we have TPM2 support library])
     AC_SUBST(TSS_INCLUDE)
+elif test "$have_libtss" = Intel; then
+    ##
+    # Intel TSS has an API issue: Esys_TR_GetTpmHandle wasn't introduced
+    # until version 2.4.0.
+    #
+    # Note: the missing API is fairly serious and is also easily backportable
+    # so keep the check below as is intead of going by library version number.
+    ##
+    AC_CHECK_LIB(tss2-esys, Esys_TR_GetTpmHandle, [], [
+	AC_MSG_WARN([Need Esys_TR_GetTpmHandle API (usually requires Intel TSS 2.4.0 or later, disabling TPM support)])
+	have_libtss=no
+    ])
+    LIBTSS_LIBS="$LIBS -ltss2-mu -ltss2-rc -ltss2-tctildr"
+    AC_DEFINE(HAVE_INTEL_TSS, 1, [Defined if we have the Intel TSS])
+fi
+LIBS="$_save_libs"
+CFLAGS="$_save_cflags"
+if test "$have_libtss" != no; then
+    AC_DEFINE(HAVE_LIBTSS, 1, [Defined if we have TPM2 support library])
     # look for a TPM emulator for testing
     AC_PATH_PROG(TPMSERVER, tpm_server,,/bin:/usr/bin:/usr/lib/ibmtss:/usr/libexec/ibmtss)
     AC_PATH_PROG(SWTPM, swtpm,,/bin:/usr/bin:/usr/lib/ibmtss:/usr/libexec/ibmtss)
     AC_PATH_PROG(SWTPM_IOCTL, swtpm_ioctl,,/bin:/usr/bin:/usr/lib/ibmtss:/usr/libexec/ibmtss)
 fi
-LIBS="$_save_libs"
-CFLAGS="$_save_cflags"
 AC_SUBST(LIBTSS_LIBS)
 AC_SUBST(LIBTSS_CFLAGS)
-AM_CONDITIONAL(HAVE_LIBTSS, test "$have_libtss" = yes)
+AM_CONDITIONAL(HAVE_LIBTSS, test "$have_libtss" != no)
 AM_CONDITIONAL(TEST_LIBTSS, test -n "$TPMSERVER" -o -n "$SWTPM")
 AC_SUBST(HAVE_LIBTSS)
 
diff --git a/tpm2d/intel-tss.h b/tpm2d/intel-tss.h
new file mode 100644
index 000000000..6e0d0a040
--- /dev/null
+++ b/tpm2d/intel-tss.h
@@ -0,0 +1,667 @@
+/*
+ * Copyright (C) 2021 James Bottomley <James.Bottomley at HansenPartnership.com>
+ *
+ * Some portions of the TSS routines are
+ * (c) Copyright IBM Corporation 2015 - 2019
+ */
+#ifndef _TPM2_INTEL_TSS_H
+#define _TPM2_INTEL_TSS_H
+
+#include <tss2/tss2_esys.h>
+#include <tss2/tss2_mu.h>
+#include <tss2/tss2_rc.h>
+#include <tss2/tss2_tcti.h>
+#include <tss2/tss2_tctildr.h>
+
+#define EXT_TPM_RH_OWNER	TPM2_RH_OWNER
+#define EXT_TPM_RH_PLATFORM	TPM2_RH_PLATFORM
+#define EXT_TPM_RH_ENDORSEMENT	TPM2_RH_ENDORSEMENT
+#define EXT_TPM_RH_NULL		TPM2_RH_NULL
+#define INT_TPM_RH_NULL		ESYS_TR_RH_NULL
+
+#define TSS_CONTEXT		ESYS_CONTEXT
+
+#define MAX_RESPONSE_SIZE	TPM2_MAX_RESPONSE_SIZE
+#define MAX_RSA_KEY_BYTES	TPM2_MAX_RSA_KEY_BYTES
+#define MAX_ECC_CURVES		TPM2_MAX_ECC_CURVES
+#define MAX_ECC_KEY_BYTES	TPM2_MAX_ECC_KEY_BYTES
+#define MAX_SYM_DATA		TPM2_MAX_SYM_DATA
+
+#define AES_128_BLOCK_SIZE_BYTES	16
+
+/*
+ * The TCG defines all begin TPM_ but for some unknown reason Intel
+ * ignored this and all its defines begin TPM2_
+ */
+
+#define TPM_RC_SUCCESS		TPM2_RC_SUCCESS
+#define TPM_RC_SYMMETRIC	TPM2_RC_SYMMETRIC
+#define TPM_RC_ASYMMETRIC	TPM2_RC_ASYMMETRIC
+#define TPM_RC_CURVE		TPM2_RC_CURVE
+#define TPM_RC_KEY_SIZE		TPM2_RC_KEY_SIZE
+#define TPM_RC_KEY		TPM2_RC_KEY
+#define TPM_RC_VALUE		TPM2_RC_VALUE
+#define TPM_RC_POLICY		TPM2_RC_POLICY
+#define TPM_RC_FAILURE		TPM2_RC_FAILURE
+#define TPM_RC_AUTH_FAIL	TPM2_RC_AUTH_FAIL
+#define TPM_RC_BAD_AUTH		TPM2_RC_BAD_AUTH
+
+#define RC_VER1			TPM2_RC_VER1
+#define RC_FMT1			TPM2_RC_FMT1
+
+#define TPM_EO_EQ		TPM2_EO_EQ
+#define TPM_EO_NEQ		TPM2_EO_NEQ
+#define TPM_EO_SIGNED_GT	TPM2_EO_SIGNED_GT
+#define TPM_EO_UNSIGNED_GT	TPM2_EO_UNSIGNED_GT
+#define TPM_EO_SIGNED_LT	TPM2_EO_SIGNED_LT
+#define TPM_EO_UNSIGNED_LT	TPM2_EO_UNSIGNED_LT
+#define TPM_EO_SIGNED_GE	TPM2_EO_SIGNED_GE
+#define TPM_EO_UNSIGNED_GE	TPM2_EO_UNSIGNED_GE
+#define TPM_EO_SIGNED_LE	TPM2_EO_SIGNED_LE
+#define TPM_EO_UNSIGNED_LE	TPM2_EO_UNSIGNED_LE
+#define TPM_EO_BITSET		TPM2_EO_BITSET
+#define TPM_EO_BITCLEAR		TPM2_EO_BITCLEAR
+
+#define TPM_CC_PolicyPCR	TPM2_CC_PolicyPCR
+#define TPM_CC_PolicyAuthValue	TPM2_CC_PolicyAuthValue
+#define TPM_CC_PolicyCounterTimer	TPM2_CC_PolicyCounterTimer
+
+#define TPM_ST_HASHCHECK	TPM2_ST_HASHCHECK
+
+#define TPM_RH_OWNER		ESYS_TR_RH_OWNER
+#define TPM_RH_PLATFORM		ESYS_TR_RH_PLATFORM
+#define TPM_RH_ENDORSEMENT	ESYS_TR_RH_ENDORSEMENT
+#define TPM_RH_NULL		ESYS_TR_NONE
+#define TPM_RS_PW		ESYS_TR_PASSWORD
+
+#define TPM_HT_PERMANENT	TPM2_HT_PERMANENT
+#define TPM_HT_TRANSIENT	TPM2_HT_TRANSIENT
+#define TPM_HT_PERSISTENT	TPM2_HT_PERSISTENT
+
+#define TPM_HANDLE		ESYS_TR
+#define TPM_RC			TPM2_RC
+#define TPM_CC			TPM2_CC
+
+#define TPM_ALG_ID		TPM2_ALG_ID
+#define TPM_SE			TPM2_SE
+#define TPM_SE_HMAC		TPM2_SE_HMAC
+#define TPM_SE_POLICY		TPM2_SE_POLICY
+#define TPM_CAP			TPM2_CAP
+#define TPM_CAP_ECC_CURVES	TPM2_CAP_ECC_CURVES
+#define TPM_EO			TPM2_EO
+
+#define TPM_ECC_NONE		TPM2_ECC_NONE
+#define TPM_ECC_NIST_P192	TPM2_ECC_NIST_P192
+#define TPM_ECC_NIST_P224	TPM2_ECC_NIST_P224
+#define TPM_ECC_NIST_P256	TPM2_ECC_NIST_P256
+#define TPM_ECC_NIST_P384	TPM2_ECC_NIST_P384
+#define TPM_ECC_NIST_P521	TPM2_ECC_NIST_P521
+#define TPM_ECC_BN_P256		TPM2_ECC_BN_P256
+#define TPM_ECC_BN_P638		TPM2_ECC_BN_P638
+#define TPM_ECC_SM2_P256	TPM2_ECC_SM2_P256
+
+#define TPM_ALG_NULL		TPM2_ALG_NULL
+#define TPM_ALG_SHA1		TPM2_ALG_SHA1
+#define TPM_ALG_SHA256		TPM2_ALG_SHA256
+#define TPM_ALG_SHA384		TPM2_ALG_SHA384
+#define TPM_ALG_SHA512		TPM2_ALG_SHA512
+#define TPM_ALG_AES		TPM2_ALG_AES
+#define TPM_ALG_CFB		TPM2_ALG_CFB
+#define TPM_ALG_RSA		TPM2_ALG_RSA
+#define TPM_ALG_RSASSA		TPM2_ALG_RSASSA
+#define TPM_ALG_ECC		TPM2_ALG_ECC
+#define TPM_ALG_KEYEDHASH	TPM2_ALG_KEYEDHASH
+#define TPM_ALG_RSAES		TPM2_ALG_RSAES
+#define TPM_ALG_OAEP		TPM2_ALG_OAEP
+#define TPM_ALG_ECDSA		TPM2_ALG_ECDSA
+
+/* the odd TPMA_OBJECT_  type is wrong too */
+
+#define TPMA_OBJECT_SIGN	TPMA_OBJECT_SIGN_ENCRYPT
+
+/* Intel and IBM have slightly different names for all the 2B structures */
+
+#define NAME_2B			TPM2B_NAME
+#define DATA_2B			TPM2B_DATA
+#define PRIVATE_2B		TPM2B_PRIVATE
+#define ENCRYPTED_SECRET_2B	TPM2B_ENCRYPTED_SECRET
+#define KEY_2B			TPM2B_KEY
+#define TPM2B_KEY		TPM2B_DATA
+#define DIGEST_2B		TPM2B_DIGEST
+#define ECC_PARAMETER_2B	TPM2B_ECC_PARAMETER
+#define SENSITIVE_DATA_2B	TPM2B_SENSITIVE_DATA
+#define PUBLIC_KEY_RSA_2B	TPM2B_PUBLIC_KEY_RSA
+
+#define FALSE			0
+#define TRUE			1
+
+typedef struct {
+	uint16_t size;
+	BYTE buffer[];
+} TPM2B;
+
+#define TSS_CONVERT_MARSHAL(TYPE, PTR)				\
+static inline TPM_RC						\
+TSS_##TYPE##_Marshal(const TYPE *source, UINT16 *written,	\
+		     BYTE **buffer, INT32 *size)		\
+{								\
+  size_t offset = 0;						\
+  TPM_RC rc;							\
+								\
+  rc = Tss2_MU_##TYPE##_Marshal(PTR source, *buffer, *size, &offset); \
+								\
+  *buffer += offset;						\
+  *size -= offset;						\
+  *written = offset;						\
+								\
+  return rc;							\
+}
+#define TSS_CONVERT_UNMARSHAL(TYPE, ARG)			\
+static inline TPM_RC						\
+TYPE##_Unmarshal##ARG(TYPE *dest,				\
+		 BYTE **buffer, INT32 *size)			\
+{								\
+  size_t offset = 0;						\
+  TPM_RC rc;							\
+								\
+  memset(dest, 0, sizeof(TYPE));				\
+  rc = Tss2_MU_##TYPE##_Unmarshal(*buffer, *size, &offset, dest);	\
+								\
+  *buffer += offset;						\
+  *size -= offset;						\
+								\
+  return rc;							\
+}
+
+TSS_CONVERT_MARSHAL(TPMT_PUBLIC, )
+TSS_CONVERT_MARSHAL(UINT16, *)
+TSS_CONVERT_MARSHAL(TPMT_SENSITIVE, )
+TSS_CONVERT_MARSHAL(TPM2B_ECC_POINT, )
+TSS_CONVERT_MARSHAL(TPM2B_DIGEST, )
+TSS_CONVERT_MARSHAL(TPM2B_PUBLIC, )
+TSS_CONVERT_MARSHAL(TPM2B_PRIVATE, )
+
+TSS_CONVERT_UNMARSHAL(TPML_PCR_SELECTION, )
+TSS_CONVERT_UNMARSHAL(TPM2B_PRIVATE, )
+TSS_CONVERT_UNMARSHAL(TPM2B_PUBLIC, X)
+TSS_CONVERT_UNMARSHAL(TPM2B_ENCRYPTED_SECRET, )
+TSS_CONVERT_UNMARSHAL(UINT16, )
+TSS_CONVERT_UNMARSHAL(UINT32, )
+
+#define ARRAY_SIZE(A) (sizeof(A)/sizeof(A[0]))
+
+#define TPM2B_PUBLIC_Unmarshal(A, B, C, D) TPM2B_PUBLIC_UnmarshalX(A, B, C)
+#define TPM_EO_Unmarshal	UINT16_Unmarshal
+#define TPM_CC_Unmarshal	UINT32_Unmarshal
+
+#define VAL(X) X
+#define VAL_2B(X, MEMBER) X.MEMBER
+#define VAL_2B_P(X, MEMBER) X->MEMBER
+
+static const struct {
+  TPM_ALG_ID alg;
+  int gcrypt_algo;
+  int size;
+} TSS_Hashes[] = {
+  { TPM_ALG_SHA1,   GCRY_MD_SHA1,     20 },
+  { TPM_ALG_SHA256, GCRY_MD_SHA256,   32 },
+  { TPM_ALG_SHA384, GCRY_MD_SHA3_384, 48 },
+  { TPM_ALG_SHA512, GCRY_MD_SHA3_512, 64 }
+};
+
+static inline void
+intel_auth_helper(TSS_CONTEXT *tssContext, TPM_HANDLE auth, const char *authVal)
+{
+  TPM2B_AUTH authVal2B;
+
+  if (authVal)
+    {
+      authVal2B.size = strlen(authVal);
+      memcpy(authVal2B.buffer, authVal, authVal2B.size);
+    }
+  else
+    {
+      authVal2B.size = 0;
+    }
+  Esys_TR_SetAuth(tssContext, auth, &authVal2B);
+}
+
+static inline void
+intel_sess_helper(TSS_CONTEXT *tssContext, TPM_HANDLE auth, TPMA_SESSION flags)
+{
+  Esys_TRSess_SetAttributes(tssContext, auth, flags,
+			    TPMA_SESSION_CONTINUESESSION | flags);
+}
+
+static inline TPM_HANDLE
+intel_handle(TPM_HANDLE h)
+{
+  if (h == 0)
+    return ESYS_TR_NONE;
+  return h;
+}
+
+static inline void
+TSS_Delete(TSS_CONTEXT *tssContext)
+{
+  TSS2_TCTI_CONTEXT *tcti_ctx;
+  TPM_RC rc;
+
+  rc = Esys_GetTcti(tssContext, &tcti_ctx);
+  Esys_Finalize(&tssContext);
+  if (rc == TPM_RC_SUCCESS)
+    Tss2_TctiLdr_Finalize(&tcti_ctx);
+}
+
+static inline TPM_RC
+TSS_Create(TSS_CONTEXT **tssContext)
+{
+  TPM_RC rc;
+  TSS2_TCTI_CONTEXT *tcti_ctx = NULL;
+  char *intType;
+  char *tctildr = NULL;
+
+  intType = getenv("TPM_INTERFACE_TYPE");
+  /*
+   * FIXME: This should be way more sophisticated, but it's
+   * enough to get the simulator tests running
+   */
+  if (intType)
+    {
+      if (strcmp("socsim", intType) == 0) {
+	tctildr = "mssim";
+      }
+      else if (strcmp("dev", intType) == 0)
+	{
+	  tctildr = "device";
+	}
+      else
+	{
+	  fprintf(stderr, "Unknown TPM_INTERFACE_TYPE %s\n", intType);
+	}
+    }
+
+  rc = Tss2_TctiLdr_Initialize(tctildr, &tcti_ctx);
+  if (rc)
+    return rc;
+
+  rc =  Esys_Initialize(tssContext, tcti_ctx, NULL);
+
+  return rc;
+}
+
+static inline int
+TSS_GetDigestSize(TPM_ALG_ID alg) {
+  int i;
+
+  for (i = 0; i < ARRAY_SIZE(TSS_Hashes); i++)
+    if (TSS_Hashes[i].alg == alg)
+      return TSS_Hashes[i].size;
+  return -1;
+}
+
+static inline int
+TSS_Hash_GetMd(int *algo, TPM_ALG_ID alg) {
+  int i;
+
+  for (i = 0; i < ARRAY_SIZE(TSS_Hashes); i++)
+    if (TSS_Hashes[i].alg == alg)
+      {
+	*algo = TSS_Hashes[i].gcrypt_algo;
+	return 0;
+      }
+  return TPM_RC_FAILURE;
+}
+
+/* copied with modifications from the IBM TSS tsscrypto.c */
+static inline TPM_RC
+TSS_Hash_Generate(TPMT_HA *digest, ...)
+{
+  TPM_RC rc = 0;
+  int length;
+  uint8_t *buffer;
+  int algo;
+  gcry_md_hd_t md;
+  va_list ap;
+
+  va_start(ap, digest);
+
+  rc = TSS_Hash_GetMd(&algo, digest->hashAlg);
+  if (rc)
+    {
+      fprintf(stderr, "TSS_HASH_GENERATE: Unknown hash %d\n",
+	      digest->hashAlg);
+      goto out;
+    }
+
+  rc = gcry_md_open (&md, algo, 0);
+  if (rc != 0)
+    {
+      fprintf(stderr, "TSS_Hash_Generate: EVP_MD_CTX_create failed\n");
+      rc = TPM_RC_FAILURE;
+      goto out;
+    }
+
+  rc = TPM_RC_FAILURE;
+  for (;;)
+    {
+      length = va_arg(ap, int);		/* first vararg is the length */
+      buffer = va_arg(ap, unsigned char *);	/* second vararg is the array */
+      if (buffer == NULL)			/* loop until a NULL buffer terminates */
+	break;
+      if (length < 0)
+	{
+	  fprintf(stderr, "TSS_Hash_Generate: Length is negative\n");
+	  goto out_free;
+	}
+      if (length != 0)
+	gcry_md_write (md, buffer, length);
+    }
+
+  memcpy (&digest->digest, gcry_md_read (md, algo),
+	  TSS_GetDigestSize(digest->hashAlg));
+  rc = TPM_RC_SUCCESS;
+ out_free:
+  gcry_md_close (md);
+ out:
+  va_end(ap);
+  return rc;
+}
+
+static inline TPM_RC
+TSS_TPM2B_Create(TPM2B *target, uint8_t *buffer, uint16_t size,
+		 uint16_t targetSize)
+{
+  if (size > targetSize)
+    return TSS2_MU_RC_INSUFFICIENT_BUFFER;
+  target->size = size;
+  if (size)
+    memmove(target->buffer, buffer, size);
+  return TPM_RC_SUCCESS;
+}
+
+static inline void
+tpm2_error(TPM_RC rc, const char *reason)
+{
+  const char *msg;
+
+  fprintf(stderr, "%s failed with %d\n", reason, rc);
+  msg = Tss2_RC_Decode(rc);
+  fprintf(stderr, "%s\n", msg);
+}
+
+static inline int
+TSS_start (TSS_CONTEXT **tssc)
+{
+  TPM_RC rc;
+
+  rc = TSS_Create (tssc);
+  if (rc)
+    {
+      tpm2_error(rc, "TSS_Create");
+      return GPG_ERR_CARD;
+    }
+
+  return 0;
+}
+
+static inline TPM_RC
+tpm2_Import(TSS_CONTEXT *tssContext, TPM_HANDLE parentHandle,
+	    DATA_2B *encryptionKey, TPM2B_PUBLIC *objectPublic,
+	    PRIVATE_2B *duplicate, ENCRYPTED_SECRET_2B *inSymSeed,
+	    TPMT_SYM_DEF_OBJECT *symmetricAlg, PRIVATE_2B *outPrivate,
+	    TPM_HANDLE auth, const char *authVal)
+{
+  PRIVATE_2B *out;
+  TPM_RC rc;
+
+  intel_auth_helper(tssContext, parentHandle, authVal);
+  intel_sess_helper(tssContext, auth, TPMA_SESSION_DECRYPT);
+  rc = Esys_Import(tssContext, parentHandle, auth, ESYS_TR_NONE,
+		   ESYS_TR_NONE, encryptionKey, objectPublic,
+		   duplicate, inSymSeed, symmetricAlg, &out);
+  if (rc)
+    return rc;
+
+  *outPrivate = *out;
+  free(out);
+
+  return rc;
+}
+
+static inline TPM_RC
+tpm2_Create(TSS_CONTEXT *tssContext, TPM_HANDLE parentHandle,
+	    TPM2B_SENSITIVE_CREATE *inSensitive, TPM2B_PUBLIC *inPublic,
+	    PRIVATE_2B *outPrivate, TPM2B_PUBLIC *outPublic,
+	    TPM_HANDLE auth, const char *authVal)
+{
+  TPM_RC rc;
+  PRIVATE_2B *opriv;
+  TPM2B_PUBLIC *opub;
+  DATA_2B outsideInfo;
+  TPML_PCR_SELECTION creationPCR;
+
+  outsideInfo.size = 0;
+  creationPCR.count = 0;
+
+  intel_auth_helper(tssContext, parentHandle, authVal);
+  intel_sess_helper(tssContext, auth, TPMA_SESSION_DECRYPT);
+  rc = Esys_Create(tssContext, parentHandle, auth,
+		   ESYS_TR_NONE, ESYS_TR_NONE, inSensitive,
+		   inPublic, &outsideInfo, &creationPCR, &opriv,
+		   &opub, NULL, NULL, NULL);
+
+  if (rc)
+    return rc;
+
+  *outPublic = *opub;
+  free(opub);
+  *outPrivate = *opriv;
+  free(opriv);
+
+  return rc;
+}
+
+static inline TPM_RC
+tpm2_ReadPublic(TSS_CONTEXT *tssContext, TPM_HANDLE objectHandle,
+		TPMT_PUBLIC *pub, TPM_HANDLE auth)
+{
+  TPM2B_PUBLIC *out;
+  TPM_RC rc;
+
+  if (auth != TPM_RH_NULL)
+    intel_sess_helper(tssContext, auth, TPMA_SESSION_ENCRYPT);
+
+  rc = Esys_ReadPublic(tssContext, objectHandle, auth, ESYS_TR_NONE,
+			     ESYS_TR_NONE, &out, NULL, NULL);
+  if (rc)
+    return rc;
+
+  if (pub)
+    *pub = out->publicArea;
+  free(out);
+
+  return rc;
+}
+
+static inline TPM_RC
+tpm2_RSA_Decrypt(TSS_CONTEXT *tssContext, TPM_HANDLE keyHandle,
+		 PUBLIC_KEY_RSA_2B *cipherText, TPMT_RSA_DECRYPT *inScheme,
+		 PUBLIC_KEY_RSA_2B *message,
+		 TPM_HANDLE auth, const char *authVal, int flags)
+{
+  PUBLIC_KEY_RSA_2B *out;
+  DATA_2B label;
+  TPM_RC rc;
+
+  label.size = 0;
+
+  intel_auth_helper(tssContext, keyHandle, authVal);
+  intel_sess_helper(tssContext, auth, flags);
+  rc = Esys_RSA_Decrypt(tssContext, keyHandle, auth, ESYS_TR_NONE,
+			ESYS_TR_NONE, cipherText,
+			inScheme, &label, &out);
+
+  if (rc)
+    return rc;
+
+  *message = *out;
+  free(out);
+
+  return rc;
+}
+
+static inline TPM_RC
+tpm2_Sign(TSS_CONTEXT *tssContext, TPM_HANDLE keyHandle, DIGEST_2B *digest,
+	  TPMT_SIG_SCHEME *inScheme, TPMT_SIGNATURE *signature,
+	  TPM_HANDLE auth, const char *authVal)
+{
+  TPM_RC rc;
+  TPMT_TK_HASHCHECK validation;
+  TPMT_SIGNATURE *out;
+
+  validation.tag = TPM_ST_HASHCHECK;
+  validation.hierarchy = EXT_TPM_RH_NULL;
+  validation.digest.size = 0;
+
+  intel_auth_helper(tssContext, keyHandle, authVal);
+  intel_sess_helper(tssContext, auth, 0);
+  rc = Esys_Sign(tssContext, keyHandle, auth, ESYS_TR_NONE,
+		 ESYS_TR_NONE, digest, inScheme, &validation, &out);
+
+  if (rc)
+    return rc;
+
+  *signature = *out;
+  free(out);
+
+  return rc;
+}
+
+static inline TPM_RC
+tpm2_ECDH_ZGen(TSS_CONTEXT *tssContext, TPM_HANDLE keyHandle,
+	       TPM2B_ECC_POINT *inPoint, TPM2B_ECC_POINT *outPoint,
+	       TPM_HANDLE auth, const char *authVal)
+{
+  TPM2B_ECC_POINT *out;
+  TPM_RC rc;
+
+  intel_auth_helper(tssContext, keyHandle, authVal);
+  intel_sess_helper(tssContext, auth, TPMA_SESSION_ENCRYPT);
+  rc = Esys_ECDH_ZGen(tssContext, keyHandle, auth, ESYS_TR_NONE,
+		      ESYS_TR_NONE, inPoint, &out);
+
+  if (rc)
+    return rc;
+
+  *outPoint = *out;
+  free(out);
+
+  return rc;
+}
+
+static inline TPM_RC
+tpm2_CreatePrimary(TSS_CONTEXT *tssContext, TPM_HANDLE primaryHandle,
+		   TPM2B_SENSITIVE_CREATE *inSensitive,
+		   TPM2B_PUBLIC *inPublic, TPM_HANDLE *objectHandle)
+{
+  TPM2B_DATA outsideInfo;
+  TPML_PCR_SELECTION creationPcr;
+  TPM_RC rc;
+
+  /* FIXME will generate wrong value for NULL hierarchy */
+  primaryHandle = intel_handle(primaryHandle);
+
+  outsideInfo.size = 0;
+  creationPcr.count = 0;
+
+  rc = Esys_CreatePrimary(tssContext, primaryHandle, ESYS_TR_PASSWORD, ESYS_TR_NONE,
+			  ESYS_TR_NONE, inSensitive, inPublic,
+			  &outsideInfo, &creationPcr, objectHandle,
+			  NULL, NULL, NULL, NULL);
+
+  return rc;
+}
+
+static inline TPM_RC
+tpm2_FlushContext(TSS_CONTEXT *tssContext, TPM_HANDLE flushHandle)
+{
+  return Esys_FlushContext(tssContext, flushHandle);
+}
+
+static inline TPM_RC
+tpm2_StartAuthSession(TSS_CONTEXT *tssContext, TPM_HANDLE tpmKey,
+		      TPM_HANDLE bind, TPM_SE sessionType,
+		      TPMT_SYM_DEF *symmetric, TPMI_ALG_HASH authHash,
+		      TPM_HANDLE *sessionHandle,
+		      const char *bindPassword)
+{
+  bind = intel_handle(bind);
+  tpmKey = intel_handle(tpmKey);
+  if (bind != ESYS_TR_NONE)
+    intel_auth_helper(tssContext, bind, bindPassword);
+
+  return Esys_StartAuthSession(tssContext, tpmKey, bind, ESYS_TR_NONE,
+			       ESYS_TR_NONE, ESYS_TR_NONE, NULL,
+			       sessionType, symmetric, authHash,
+			       sessionHandle);
+}
+
+static inline TPM_RC
+tpm2_Load(TSS_CONTEXT *tssContext, TPM_HANDLE parentHandle,
+	  PRIVATE_2B *inPrivate, TPM2B_PUBLIC *inPublic,
+	  TPM_HANDLE *objectHandle,
+	  TPM_HANDLE auth, const char *authVal)
+{
+  intel_auth_helper(tssContext, parentHandle, authVal);
+  intel_sess_helper(tssContext, auth, 0);
+  return Esys_Load(tssContext, parentHandle, auth, ESYS_TR_NONE,
+		   ESYS_TR_NONE, inPrivate, inPublic, objectHandle);
+}
+
+static inline TPM_HANDLE
+tpm2_handle_ext(TSS_CONTEXT *tssContext, TPM_HANDLE esysh)
+{
+  TPM2_HANDLE realh = 0;
+
+  Esys_TR_GetTpmHandle(tssContext, esysh, &realh);
+
+  return realh;
+}
+
+static inline TPM_HANDLE
+tpm2_handle_int(TSS_CONTEXT *tssContext, TPM_HANDLE realh)
+{
+  TPM_HANDLE esysh = 0;
+
+  /* ***ing thing doesn't transform permanent handles */
+  if ((realh >> 24) == TPM_HT_PERMANENT)
+    {
+      switch (realh)
+	{
+	case TPM2_RH_OWNER:
+	  return TPM_RH_OWNER;
+	case TPM2_RH_PLATFORM:
+	  return TPM_RH_PLATFORM;
+	case TPM2_RH_ENDORSEMENT:
+	  return TPM_RH_ENDORSEMENT;
+	case TPM2_RH_NULL:
+	  return ESYS_TR_RH_NULL;
+	default:
+	  return 0;
+	}
+    }
+
+  Esys_TR_FromTPMPublic(tssContext, realh, ESYS_TR_NONE,
+			ESYS_TR_NONE, ESYS_TR_NONE, &esysh);
+
+  return esysh;
+}
+
+static inline int
+tpm2_handle_mso(TSS_CONTEXT *tssContext, TPM_HANDLE esysh, UINT32 mso)
+{
+  return (tpm2_handle_ext(tssContext, esysh) >> 24) == mso;
+}
+
+#endif
diff --git a/tpm2d/tpm2.h b/tpm2d/tpm2.h
index a2d3745ea..0926d8014 100644
--- a/tpm2d/tpm2.h
+++ b/tpm2d/tpm2.h
@@ -2,7 +2,11 @@
 #define _TPM2_H
 
 #include "../common/util.h"
+#ifdef HAVE_INTEL_TSS
+#include "intel-tss.h"
+#else
 #include "ibm-tss.h"
+#endif
 
 int tpm2_start (TSS_CONTEXT **tssc);
 void tpm2_end (TSS_CONTEXT *tssc);
-- 
2.26.2




More information about the Gnupg-devel mailing list