aboutsummaryrefslogtreecommitdiffstats
path: root/tpm2d
diff options
context:
space:
mode:
authorJames Bottomley via Gnupg-devel <[email protected]>2021-03-09 21:50:32 +0000
committerWerner Koch <[email protected]>2021-03-11 07:49:45 +0000
commitb9c560e3a400da83073b232ee12fae090b21d20c (patch)
treeffb97091a148dfe8fd3335ddb3503ad4db47e729 /tpm2d
parenttpmd2: Add copyright blurbs. (diff)
downloadgnupg-b9c560e3a400da83073b232ee12fae090b21d20c.tar.gz
gnupg-b9c560e3a400da83073b232ee12fae090b21d20c.zip
tpmd2: Add Support for the Intel TSS
* configure.ac: Check for Intel TSS. * tpm2d/intel-tss.h: New. * tpm2d/tpm2.h (HAVE_INTEL_TSS): Use the Intel code. -- 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 <[email protected]> - Add header blurb; see previous patch. - Add new file to the Makefile Signed-off-by: Werner Koch <[email protected]>
Diffstat (limited to 'tpm2d')
-rw-r--r--tpm2d/Makefile.am2
-rw-r--r--tpm2d/intel-tss.h684
-rw-r--r--tpm2d/tpm2.h4
3 files changed, 689 insertions, 1 deletions
diff --git a/tpm2d/Makefile.am b/tpm2d/Makefile.am
index bf5acd452..ef9487139 100644
--- a/tpm2d/Makefile.am
+++ b/tpm2d/Makefile.am
@@ -30,7 +30,7 @@ tpm2daemon_SOURCES = \
command.c \
tpm2daemon.c \
tpm2.c tpm2.h \
- tpm2daemon.h ibm-tss.h
+ tpm2daemon.h ibm-tss.h intel-tss.h
tpm2daemon_LDADD = $(libcommonpth) \
$(LIBGCRYPT_LIBS) $(KSBA_LIBS) $(LIBASSUAN_LIBS) $(NPTH_LIBS) \
diff --git a/tpm2d/intel-tss.h b/tpm2d/intel-tss.h
new file mode 100644
index 000000000..615f81e2f
--- /dev/null
+++ b/tpm2d/intel-tss.h
@@ -0,0 +1,684 @@
+/* intel-tss.h - Supporting TPM routines for the Intel TSS
+ * Copyright (C) 2021 James Bottomley <[email protected]>
+ *
+ * Some portions of the TSS routines are
+ * (c) Copyright IBM Corporation 2015 - 2019
+ *
+ * This file is part of GnuPG.
+ *
+ * GnuPG is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GnuPG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses/>.
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#ifndef _GNUPG_TPM2_INTEL_TSS_H
+#define _GNUPG_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 f2fa89ed9..db79ade64 100644
--- a/tpm2d/tpm2.h
+++ b/tpm2d/tpm2.h
@@ -22,7 +22,11 @@
#define _GNUPG_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);