@@ -100,7 +100,8 @@ vmlinux-objs-$(CONFIG_SECURE_LAUNCH) += $(obj)/early_sha1.o
vmlinux-objs-$(CONFIG_SECURE_LAUNCH_SHA256) += $(obj)/early_sha256.o
vmlinux-objs-$(CONFIG_SECURE_LAUNCH_SHA512) += $(obj)/early_sha512.o
vmlinux-objs-$(CONFIG_SECURE_LAUNCH) += $(obj)/tpm/tpmio.o $(obj)/tpm/tpm_buff.o \
- $(obj)/tpm/tis.o $(obj)/tpm/crb.o
+ $(obj)/tpm/tis.o $(obj)/tpm/crb.o $(obj)/tpm/tpm1_cmds.o \
+ $(obj)/tpm/tpm2_cmds.o $(obj)/tpm/tpm2_auth.o
# The compressed kernel is built with -fPIC/-fPIE so that a boot loader
# can place it anywhere in memory and it will still run. However, since
new file mode 100644
@@ -0,0 +1,112 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2020 Apertus Solutions, LLC
+ *
+ * Author(s):
+ * Daniel P. Smith <dpsmith@apertussolutions.com>
+ *
+ * The definitions in this header are extracted from the Trusted Computing
+ * Group's "TPM Main Specification", Parts 1-3.
+ *
+ */
+
+#ifndef _TPM1_H
+#define _TPM1_H
+
+#include "tpm.h"
+
+/* Section 2.2.3 */
+#define TPM_AUTH_DATA_USAGE u8
+#define TPM_PAYLOAD_TYPE u8
+#define TPM_VERSION_BYTE u8
+#define TPM_TAG u16
+#define TPM_PROTOCOL_ID u16
+#define TPM_STARTUP_TYPE u16
+#define TPM_ENC_SCHEME u16
+#define TPM_SIG_SCHEME u16
+#define TPM_MIGRATE_SCHEME u16
+#define TPM_PHYSICAL_PRESENCE u16
+#define TPM_ENTITY_TYPE u16
+#define TPM_KEY_USAGE u16
+#define TPM_EK_TYPE u16
+#define TPM_STRUCTURE_TAG u16
+#define TPM_PLATFORM_SPECIFIC u16
+#define TPM_COMMAND_CODE u32
+#define TPM_CAPABILITY_AREA u32
+#define TPM_KEY_FLAGS u32
+#define TPM_ALGORITHM_ID u32
+#define TPM_MODIFIER_INDICATOR u32
+#define TPM_ACTUAL_COUNT u32
+#define TPM_TRANSPORT_ATTRIBUTES u32
+#define TPM_AUTHHANDLE u32
+#define TPM_DIRINDEX u32
+#define TPM_KEY_HANDLE u32
+#define TPM_PCRINDEX u32
+#define TPM_RESULT u32
+#define TPM_RESOURCE_TYPE u32
+#define TPM_KEY_CONTROL u32
+#define TPM_NV_INDEX u32 The
+#define TPM_FAMILY_ID u32
+#define TPM_FAMILY_VERIFICATION u32
+#define TPM_STARTUP_EFFECTS u32
+#define TPM_SYM_MODE u32
+#define TPM_FAMILY_FLAGS u32
+#define TPM_DELEGATE_INDEX u32
+#define TPM_CMK_DELEGATE u32
+#define TPM_COUNT_ID u32
+#define TPM_REDIT_COMMAND u32
+#define TPM_TRANSHANDLE u32
+#define TPM_HANDLE u32
+#define TPM_FAMILY_OPERATION u32
+
+/* Section 6 */
+#define TPM_TAG_RQU_COMMAND 0x00C1
+#define TPM_TAG_RQU_AUTH1_COMMAND 0x00C2
+#define TPM_TAG_RQU_AUTH2_COMMAND 0x00C3
+#define TPM_TAG_RSP_COMMAND 0x00C4
+#define TPM_TAG_RSP_AUTH1_COMMAND 0x00C5
+#define TPM_TAG_RSP_AUTH2_COMMAND 0x00C6
+
+/* Section 16 */
+#define TPM_SUCCESS 0x0
+
+/* Section 17 */
+#define TPM_ORD_EXTEND 0x00000014
+
+#define SHA1_DIGEST_SIZE 20
+
+/* Section 5.4 */
+struct tpm_sha1_digest {
+ u8 digest[SHA1_DIGEST_SIZE];
+};
+struct tpm_digest {
+ TPM_PCRINDEX pcr;
+ union {
+ struct tpm_sha1_digest sha1;
+ } digest;
+};
+
+#define TPM_DIGEST struct tpm_sha1_digest
+#define TPM_CHOSENID_HASH TPM_DIGEST
+#define TPM_COMPOSITE_HASH TPM_DIGEST
+#define TPM_DIRVALUE TPM_DIGEST
+#define TPM_HMAC TPM_DIGEST
+#define TPM_PCRVALUE TPM_DIGEST
+#define TPM_AUDITDIGEST TPM_DIGEST
+#define TPM_DAA_TPM_SEED TPM_DIGEST
+#define TPM_DAA_CONTEXT_SEED TPM_DIGEST
+
+struct tpm_extend_cmd {
+ TPM_PCRINDEX pcr_num;
+ TPM_DIGEST digest;
+};
+
+struct tpm_extend_resp {
+ TPM_COMMAND_CODE ordinal;
+ TPM_PCRVALUE digest;
+};
+
+/* TPM Commands */
+int tpm1_pcr_extend(struct tpm *t, struct tpm_digest *d);
+
+#endif
new file mode 100644
@@ -0,0 +1,99 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2020 Apertus Solutions, LLC
+ *
+ * Author(s):
+ * Daniel P. Smith <dpsmith@apertussolutions.com>
+ *
+ * The code in this file is based on the article "Writing a TPM Device Driver"
+ * published on http://ptgmedia.pearsoncmg.com.
+ *
+ */
+
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/byteorder.h>
+#include "tpm.h"
+#include "tpmbuff.h"
+#include "tis.h"
+#include "tpm_common.h"
+#include "tpm1.h"
+
+int tpm1_pcr_extend(struct tpm *t, struct tpm_digest *d)
+{
+ int ret = 0;
+ struct tpmbuff *b = t->buff;
+ struct tpm_header *hdr;
+ struct tpm_extend_cmd *cmd;
+ size_t size;
+
+ if (b == NULL) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ /* ensure buffer is free for use */
+ tpmb_free(b);
+
+ hdr = (struct tpm_header *)tpmb_reserve(b);
+ if (!hdr) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+
+ hdr->tag = cpu_to_be16(TPM_TAG_RQU_COMMAND);
+ hdr->code = cpu_to_be32(TPM_ORD_EXTEND);
+
+ cmd = (struct tpm_extend_cmd *)
+ tpmb_put(b, sizeof(struct tpm_extend_cmd));
+ if (cmd == NULL) {
+ ret = -ENOMEM;
+ goto free;
+ }
+
+ cmd->pcr_num = cpu_to_be32(d->pcr);
+ memcpy(&(cmd->digest), &(d->digest), sizeof(TPM_DIGEST));
+
+ hdr->size = cpu_to_be32(tpmb_size(b));
+
+ if (be32_to_cpu(hdr->size) != t->ops.send(b)) {
+ ret = -EAGAIN;
+ goto free;
+ }
+
+ /* Reset buffer for receive */
+ tpmb_trim(b, tpmb_size(b));
+
+ hdr = (struct tpm_header *)b->head;
+ tpmb_put(b, sizeof(struct tpm_header));
+
+ /*
+ * The extend receive operation returns a struct tpm_extend_resp
+ * but the current implementation ignores the returned PCR value.
+ */
+
+ /* recv() will increase the buffer size */
+ size = t->ops.recv(t->family, b);
+ if (tpmb_size(b) != size) {
+ ret = -EAGAIN;
+ goto free;
+ }
+
+ /*
+ * On return, the code field is used for the return code out. Though
+ * the commands specifications section 16.1 implies there is an
+ * ordinal field, the return size and values point to this being
+ * incorrect.
+ *
+ * Also tis_recv() converts the header back to CPU endianness.
+ */
+ if (hdr->code != TPM_SUCCESS)
+ ret = -EAGAIN;
+
+free:
+ tpmb_free(b);
+out:
+ return ret;
+}
new file mode 100644
@@ -0,0 +1,89 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2020 Apertus Solutions, LLC
+ *
+ * Author(s):
+ * Daniel P. Smith <dpsmith@apertussolutions.com>
+ *
+ * The definitions in this header are extracted and/or dervied from the
+ * Trusted Computing Group's TPM 2.0 Library Specification Parts 1&2.
+ *
+ */
+
+#ifndef _TPM2_H
+#define _TPM2_H
+
+#include "tpm_common.h"
+#include "tpm2_constants.h"
+
+
+/* Table 192 Definition of TPM2B_TEMPLATE Structure:
+ * Using this as the base structure similar to the spec
+ */
+struct tpm2b {
+ u16 size;
+ u8 buffer[0];
+};
+
+// Table 32 Definition of TPMA_SESSION Bits < IN/OUT>
+struct tpma_session {
+ u8 continue_session : 1;
+ u8 audit_exclusive : 1;
+ u8 audit_reset : 1;
+ u8 reserved3_4 : 2;
+ u8 decrypt : 1;
+ u8 encrypt : 1;
+ u8 audit : 1;
+};
+
+
+// Table 72 Definition of TPMT_HA Structure < IN/OUT>
+struct tpmt_ha {
+ u16 alg; /* TPMI_ALG_HASH */
+ u8 digest[0]; /* TPMU_HA */
+};
+
+// Table 100 Definition of TPML_DIGEST_VALUES Structure
+struct tpml_digest_values {
+ u32 count;
+ struct tpmt_ha digests[0];
+};
+
+
+// Table 124 Definition of TPMS_AUTH_COMMAND Structure < IN>
+struct tpms_auth_cmd {
+ u32 *handle;
+ struct tpm2b *nonce;
+ struct tpma_session *attributes;
+ struct tpm2b *hmac;
+};
+
+// Table 125 Definition of TPMS_AUTH_RESPONSE Structure < OUT>
+struct tpms_auth_resp {
+ struct tpm2b *nonce;
+ struct tpma_session *attributes;
+ struct tpm2b *hmac;
+};
+
+struct tpm2_cmd {
+ struct tpm_header *header;
+ u32 *handles; /* TPM Handles array */
+ u32 *auth_size; /* Size of Auth Area */
+ u8 *auth; /* Authorization Area */
+ u8 *params; /* Parameters */
+ u8 *raw; /* internal raw buffer */
+};
+
+struct tpm2_resp {
+ struct tpm_header *header;
+ u32 *handles; /* TPM Handles array */
+ u32 *param_size; /* Size of Parameters */
+ struct tpm2b *params; /* Parameters */
+ u8 *auth; /* Authorization Area */
+ u8 *raw; /* internal raw buffer */
+};
+
+int tpm2_extend_pcr(struct tpm *t, u32 pcr,
+ struct tpml_digest_values *digests);
+
+#endif
new file mode 100644
@@ -0,0 +1,44 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2020 Apertus Solutions, LLC
+ *
+ * Author(s):
+ * Daniel P. Smith <dpsmith@apertussolutions.com>
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/const.h>
+#include <linux/string.h>
+#include <asm/byteorder.h>
+#include "tpm.h"
+#include "tpmbuff.h"
+#include "tpm2.h"
+#include "tpm2_constants.h"
+
+#define NULL_AUTH_SIZE 9
+
+u32 tpm2_null_auth_size(void)
+{
+ return NULL_AUTH_SIZE;
+}
+
+u8 *tpm2_null_auth(struct tpmbuff *b)
+{
+ u32 *handle;
+ u8 *auth = (u8 *)tpmb_put(b, NULL_AUTH_SIZE);
+
+ if (!auth)
+ return NULL;
+
+ memset(auth, 0, NULL_AUTH_SIZE);
+
+ /*
+ * The handle, the first element, is the
+ * only non-zero value in a NULL auth
+ */
+ handle = (u32 *)auth;
+ *handle = cpu_to_be32(TPM_RS_PW);
+
+ return auth;
+}
new file mode 100644
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2020 Apertus Solutions, LLC
+ *
+ * Author(s):
+ * Daniel P. Smith <dpsmith@apertussolutions.com>
+ *
+ * The definitions in this header are extracted and/or dervied from the
+ * Trusted Computing Group's TPM 2.0 Library Specification Parts 1&2.
+ *
+ */
+
+#ifndef _TPM2_AUTH_H
+#define _TPM2_AUTH_H
+
+#include "tpm2.h"
+
+u32 tpm2_null_auth_size(void);
+u8 *tpm2_null_auth(struct tpmbuff *b);
+
+#endif
new file mode 100644
@@ -0,0 +1,145 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2020 Apertus Solutions, LLC
+ *
+ * Author(s):
+ * Daniel P. Smith <dpsmith@apertussolutions.com>
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/const.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <asm/byteorder.h>
+#include "tpm.h"
+#include "tpmbuff.h"
+#include "tpm_common.h"
+#include "tpm2.h"
+#include "tpm2_auth.h"
+#include "tis.h"
+#include "crb.h"
+
+static int tpm2_alloc_cmd(struct tpmbuff *b, struct tpm2_cmd *c, u16 tag,
+ u32 code)
+{
+ /* ensure buffer is free for use */
+ tpmb_free(b);
+
+ c->header = (struct tpm_header *)tpmb_reserve(b);
+ if (!c->header)
+ return -ENOMEM;
+
+ c->header->tag = cpu_to_be16(tag);
+ c->header->code = cpu_to_be32(code);
+
+ return 0;
+}
+
+static u16 convert_digest_list(struct tpml_digest_values *digests)
+{
+ int i;
+ u16 size = sizeof(digests->count);
+ struct tpmt_ha *h = digests->digests;
+
+ for (i = 0; i < digests->count; i++) {
+ switch (h->alg) {
+ case TPM_ALG_SHA1:
+ h->alg = cpu_to_be16(h->alg);
+ h = (struct tpmt_ha *)((u8 *)h + SHA1_SIZE);
+ size += sizeof(u16) + SHA1_SIZE;
+ break;
+ case TPM_ALG_SHA256:
+ h->alg = cpu_to_be16(h->alg);
+ h = (struct tpmt_ha *)((u8 *)h + SHA256_SIZE);
+ size += sizeof(u16) + SHA256_SIZE;
+ break;
+ case TPM_ALG_SHA384:
+ h->alg = cpu_to_be16(h->alg);
+ h = (struct tpmt_ha *)((u8 *)h + SHA384_SIZE);
+ size += sizeof(u16) + SHA384_SIZE;
+ break;
+ case TPM_ALG_SHA512:
+ h->alg = cpu_to_be16(h->alg);
+ h = (struct tpmt_ha *)((u8 *)h + SHA512_SIZE);
+ size += sizeof(u16) + SHA512_SIZE;
+ break;
+ case TPM_ALG_SM3_256:
+ h->alg = cpu_to_be16(h->alg);
+ h = (struct tpmt_ha *)((u8 *)h + SM3256_SIZE);
+ size += sizeof(u16) + SHA1_SIZE;
+ break;
+ default:
+ return 0;
+ }
+ }
+
+ digests->count = cpu_to_be32(digests->count);
+
+ return size;
+}
+
+int tpm2_extend_pcr(struct tpm *t, u32 pcr,
+ struct tpml_digest_values *digests)
+{
+ struct tpmbuff *b = t->buff;
+ struct tpm2_cmd cmd;
+ u16 size;
+ int ret = 0;
+
+ if (b == NULL) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ ret = tpm2_alloc_cmd(b, &cmd, TPM_ST_SESSIONS, TPM_CC_PCR_EXTEND);
+ if (ret < 0)
+ goto out;
+
+ cmd.handles = (u32 *)tpmb_put(b, sizeof(u32));
+ if (cmd.handles == NULL) {
+ ret = -ENOMEM;
+ goto free;
+ }
+
+ cmd.handles[0] = cpu_to_be32(pcr);
+
+ cmd.auth_size = (u32 *)tpmb_put(b, sizeof(u32));
+ if (cmd.auth_size == NULL) {
+ ret = -ENOMEM;
+ goto free;
+ }
+
+ cmd.auth = tpm2_null_auth(b);
+ if (cmd.auth == NULL) {
+ ret = -ENOMEM;
+ goto free;
+ }
+
+ *cmd.auth_size = cpu_to_be32(tpm2_null_auth_size());
+
+ size = convert_digest_list(digests);
+ if (size == 0) {
+ ret = -ENOMEM;
+ goto free;
+ }
+
+ cmd.params = (u8 *)tpmb_put(b, size);
+ if (cmd.params == NULL) {
+ ret = -ENOMEM;
+ goto free;
+ }
+
+ memcpy(cmd.params, digests, size);
+
+ cmd.header->size = cpu_to_be32(tpmb_size(b));
+
+ size = t->ops.send(b);
+ if (tpmb_size(b) != size)
+ ret = -EAGAIN;
+
+free:
+ tpmb_free(b);
+out:
+ return ret;
+}
new file mode 100644
@@ -0,0 +1,66 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2020 Apertus Solutions, LLC
+ *
+ * Author(s):
+ * Daniel P. Smith <dpsmith@apertussolutions.com>
+ *
+ * The definitions in this header are extracted and/or dervied from the
+ * Trusted Computing Group's TPM 2.0 Library Specification Parts 1&2.
+ *
+ */
+
+#ifndef _TPM2_CONSTANTS_H
+#define _TPM2_CONSTANTS_H
+
+/* Table 9 Definition of (UINT16) TPM_ALG_ID Constants <IN/OUT, S> */
+#define TPM_ALG_ERROR _AT(u16, 0x0000)
+#define TPM_ALG_RSA _AT(u16, 0x0001)
+#define TPM_ALG_SHA _AT(u16, 0x0004)
+#define TPM_ALG_SHA1 _AT(u16, 0x0004)
+#define TPM_ALG_HMAC _AT(u16, 0x0005)
+#define TPM_ALG_AES _AT(u16, 0x0006)
+#define TPM_ALG_MGF1 _AT(u16, 0x0007)
+#define TPM_ALG_KEYEDHASH _AT(u16, 0x0008)
+#define TPM_ALG_XOR _AT(u16, 0x000A)
+#define TPM_ALG_SHA256 _AT(u16, 0x000B)
+#define TPM_ALG_SHA384 _AT(u16, 0x000C)
+#define TPM_ALG_SHA512 _AT(u16, 0x000D)
+#define TPM_ALG_NULL _AT(u16, 0x0010)
+#define TPM_ALG_SM3_256 _AT(u16, 0x0012)
+#define TPM_ALG_SM4 _AT(u16, 0x0013)
+#define TPM_ALG_RSASSA _AT(u16, 0x0014)
+#define TPM_ALG_RSAES _AT(u16, 0x0015)
+#define TPM_ALG_RSAPSS _AT(u16, 0x0016)
+#define TPM_ALG_OAEP _AT(u16, 0x0017)
+#define TPM_ALG_ECDSA _AT(u16, 0x0018)
+#define TPM_ALG_ECDH _AT(u16, 0x0019)
+#define TPM_ALG_ECDAA _AT(u16, 0x001A)
+#define TPM_ALG_SM2 _AT(u16, 0x001B)
+#define TPM_ALG_ECSCHNORR _AT(u16, 0x001C)
+#define TPM_ALG_ECMQV _AT(u16, 0x001D)
+#define TPM_ALG_KDF1_SP800_56A _AT(u16, 0x0020)
+#define TPM_ALG_KDF2 _AT(u16, 0x0021)
+#define TPM_ALG_KDF1_SP800_108 _AT(u16, 0x0022)
+#define TPM_ALG_ECC _AT(u16, 0x0023)
+#define TPM_ALG_SYMCIPHER _AT(u16, 0x0025)
+#define TPM_ALG_CAMELLIA _AT(u16, 0x0026)
+#define TPM_ALG_CTR _AT(u16, 0x0040)
+#define TPM_ALG_OFB _AT(u16, 0x0041)
+#define TPM_ALG_CBC _AT(u16, 0x0042)
+#define TPM_ALG_CFB _AT(u16, 0x0043)
+#define TPM_ALG_ECB _AT(u16, 0x0044)
+#define TPM_ALG_FIRST _AT(u16, 0x0001)
+#define TPM_ALG_LAST _AT(u16, 0x0044)
+
+/* Table 12 Definition of (UINT32) TPM_CC Constants (Numeric Order) <IN/OUT, S> */
+#define TPM_CC_PCR_EXTEND _AT(u32, 0x00000182)
+
+/* Table 19 Definition of (UINT16) TPM_ST Constants <IN/OUT, S> */
+#define TPM_ST_NO_SESSIONS _AT(u16, 0x8001)
+#define TPM_ST_SESSIONS _AT(u16, 0x8002)
+
+/* Table 28 Definition of (TPM_HANDLE) TPM_RH Constants <S> */
+#define TPM_RS_PW _AT(u32, 0x40000009)
+
+#endif