From 1206b684282e5e221b07c86607e8f644410d4331 Mon Sep 17 00:00:00 2001 From: Roee Kasher Date: Tue, 24 Feb 2026 18:15:06 +0200 Subject: [PATCH] Adding Rust support to TSS.MSR --- .gitignore | 3 + README.md | 7 +- TSS.CPP/Src/TpmExtensions.cpp.snips | 2 +- TSS.CPP/include/TpmTypes.h | 2 +- TSS.JS/src/TpmBase.ts | 2 +- TSS.Java/pom.xml | 12 +- TSS.NET/TSS.Net/X_TpmDefs.cs | 118 +- TSS.Rust/Cargo.lock | 601 + TSS.Rust/Cargo.toml | 35 + TSS.Rust/README.md | 64 + TSS.Rust/clippy.toml | 17 + TSS.Rust/examples/README.md | 72 + TSS.Rust/examples/tpm_samples.rs | 2851 ++ TSS.Rust/src/auth_session.rs | 288 + TSS.Rust/src/crypto.rs | 272 + TSS.Rust/src/device.rs | 967 + TSS.Rust/src/error.rs | 105 + TSS.Rust/src/lib.rs | 12 + TSS.Rust/src/policy.rs | 656 + TSS.Rust/src/tpm2.rs | 7642 ++++++ TSS.Rust/src/tpm2_helpers.rs | 55 + TSS.Rust/src/tpm2_impl.rs | 1309 + TSS.Rust/src/tpm_buffer.rs | 373 + TSS.Rust/src/tpm_extensions.rs.snips | 13 + TSS.Rust/src/tpm_structure.rs | 109 + TSS.Rust/src/tpm_type_extensions.rs | 450 + TSS.Rust/src/tpm_types.rs | 34775 +++++++++++++++++++++++++ TssCodeGen/README.md | 10 +- TssCodeGen/src/CGenJava.cs | 2 +- TssCodeGen/src/CGenRust.cs | 1064 + TssCodeGen/src/CodeGenBase.cs | 126 +- TssCodeGen/src/Expression.cs | 26 +- TssCodeGen/src/TargetLang.cs | 102 +- TssCodeGen/src/TpmTranslations.cs | 23 +- TssCodeGen/src/TpmTypes.cs | 10 +- 35 files changed, 52059 insertions(+), 116 deletions(-) create mode 100644 TSS.Rust/Cargo.lock create mode 100644 TSS.Rust/Cargo.toml create mode 100644 TSS.Rust/README.md create mode 100644 TSS.Rust/clippy.toml create mode 100644 TSS.Rust/examples/README.md create mode 100644 TSS.Rust/examples/tpm_samples.rs create mode 100644 TSS.Rust/src/auth_session.rs create mode 100644 TSS.Rust/src/crypto.rs create mode 100644 TSS.Rust/src/device.rs create mode 100644 TSS.Rust/src/error.rs create mode 100644 TSS.Rust/src/lib.rs create mode 100644 TSS.Rust/src/policy.rs create mode 100644 TSS.Rust/src/tpm2.rs create mode 100644 TSS.Rust/src/tpm2_helpers.rs create mode 100644 TSS.Rust/src/tpm2_impl.rs create mode 100644 TSS.Rust/src/tpm_buffer.rs create mode 100644 TSS.Rust/src/tpm_extensions.rs.snips create mode 100644 TSS.Rust/src/tpm_structure.rs create mode 100644 TSS.Rust/src/tpm_type_extensions.rs create mode 100644 TSS.Rust/src/tpm_types.rs create mode 100644 TssCodeGen/src/CGenRust.cs diff --git a/.gitignore b/.gitignore index 78ccd411..ac400dbe 100644 --- a/.gitignore +++ b/.gitignore @@ -229,3 +229,6 @@ FakesAssemblies/ /Tpm2Tester/TestSuite/Properties/launchSettings.json *.map *.json + +# Rust +target/ diff --git a/README.md b/README.md index 407b25fb..75bd38e3 100644 --- a/README.md +++ b/README.md @@ -20,9 +20,9 @@ All flavors of TPM 2.0 devices mentioned in the previous section communicate wit In order to facilitate the development of applications and services using TPM 2.0, Microsoft has developed a series of TSS implementations for different programming languages. All these implementations provide complete representation of the TPM 2.0 API (commands, data structures, enumerations, unions) using the means of the corresponding languages, and some of them - additional functionality that greatly simplifies communications with TPM 2.0. All TSS.MSR implementations provide abstraction for Windows/Linux/Simulator TPM 2.0 devices. -### [TSS.Net] and [TSS.CPP] +### [TSS.Net], [TSS.CPP] and [TSS.Rust] -TSS.Net and TSS.CPP are written in C# and C++ correspondingly, and are the richest TSS implementations in this collection. Besides complete abstraction of the TPM 2.0 interface, they implement additional functionality, such as: +TSS.Net, TSS.CPP and TSS.Rust are written in C#, C++ and Rust correspondingly, and are the richest TSS implementations in this collection. Besides complete abstraction of the TPM 2.0 interface, they implement additional functionality, such as: * automatic handling of HMAC and policy sessions; * expected audit, policy and cpHashes computation; @@ -48,6 +48,8 @@ Along with it comes a [sample test suite][TestSuite] that not only demonstrates TSS.Net is a cross-platform .NET Standard library and requires Visual Studio 2017 or above to build it. It can target one of the following .NET framework flavors: .NET 4.7.2, .NET Core 2.1 (for both Windows and Linux), .NET Standard 2.0, and .NET UWP 10.0. You can download the latest versions of the .NET Framework [here](https://www.microsoft.com/net/download/windows). +TSS.Rust requires Rust 1.70 or above and uses Cargo as its build system. + TSS.Java uses Java SE 8 or above, TSS.JS requires Node.js 4.8.4 or higher, and TSS.Py supports Python 2.7 and 3.5+. ## Platform Crypto Provider Toolkit @@ -70,6 +72,7 @@ For private feedback please use tssdotnet@microsoft.com (for all managed languag [TSS.Net]: ./TSS.NET [TSS.CPP]: ./TSS.CPP +[TSS.Rust]: ./TSS.Rust [TSS.Java]: ./TSS.Java [TSS.JS]: ./TSS.JS [TSS.Py]: ./TSS.Py diff --git a/TSS.CPP/Src/TpmExtensions.cpp.snips b/TSS.CPP/Src/TpmExtensions.cpp.snips index a1f1331a..b235c709 100644 --- a/TSS.CPP/Src/TpmExtensions.cpp.snips +++ b/TSS.CPP/Src/TpmExtensions.cpp.snips @@ -193,7 +193,7 @@ static vector GetSelectionArray(TPM_ALG_ID hashAlg, UINT32 p /// Is the PCR with index _pcr selected in this TPMS_PCR_SELECTION. bool PcrIsSelected(UINT32 pcr) { - return pcrSelect[pcr / 8] = (1 << (pcr % 8)) != 0; + return (pcrSelect[pcr / 8] >> (pcr % 8)) & 1; } /// Return the current PCR-selection as a UINT32 array. diff --git a/TSS.CPP/include/TpmTypes.h b/TSS.CPP/include/TpmTypes.h index c10d14d9..7b7b8af1 100644 --- a/TSS.CPP/include/TpmTypes.h +++ b/TSS.CPP/include/TpmTypes.h @@ -3653,7 +3653,7 @@ class _DLLEXP_ TPMS_PCR_SELECTION : public TpmStructure /// Is the PCR with index _pcr selected in this TPMS_PCR_SELECTION. bool PcrIsSelected(UINT32 pcr) { - return pcrSelect[pcr / 8] = (1 << (pcr % 8)) != 0; + return (pcrSelect[pcr / 8] >> (pcr % 8)) & 1; } /// Return the current PCR-selection as a UINT32 array. diff --git a/TSS.JS/src/TpmBase.ts b/TSS.JS/src/TpmBase.ts index 66361a54..9abfc160 100644 --- a/TSS.JS/src/TpmBase.ts +++ b/TSS.JS/src/TpmBase.ts @@ -205,7 +205,7 @@ export class TpmBase { // If the caller has not provided a session for a handle that requires authorization, // a password session is automatically created. - if (this.sessions == null) + if (this.sessions == null) this.sessions = new Array(numAuthHandles); else if (this.sessions.length < numAuthHandles) this.sessions = this.sessions.concat(new Array(numAuthHandles - this.sessions.length)); diff --git a/TSS.Java/pom.xml b/TSS.Java/pom.xml index f4b832e4..cabff8e6 100644 --- a/TSS.Java/pom.xml +++ b/TSS.Java/pom.xml @@ -31,13 +31,13 @@ org.bouncycastle - bcprov-jdk15on - 1.67 + bcprov-jdk18on + 1.78 net.java.dev.jna jna - 4.4.0 + 5.14.0 @@ -53,7 +53,7 @@ maven-compiler-plugin - 3.6.1 + 3.12.1 1.8 1.8 @@ -95,11 +95,11 @@ org.apache.maven.plugins maven-javadoc-plugin - 3.0.0-M1 + 3.6.3 8 - -Xdoclint:none + all,-missing diff --git a/TSS.NET/TSS.Net/X_TpmDefs.cs b/TSS.NET/TSS.Net/X_TpmDefs.cs index 658a55fa..26af3b57 100644 --- a/TSS.NET/TSS.Net/X_TpmDefs.cs +++ b/TSS.NET/TSS.Net/X_TpmDefs.cs @@ -3815,38 +3815,45 @@ public enum AlgorithmAttr : uint /// SET (1): an asymmetric algorithm with public and private portions /// CLEAR (0): not an asymmetric algorithm [EnumMember] + [SpecTypeName("Asymmetric")] Asymmetric = 0x1, /// SET (1): a symmetric block cipher /// CLEAR (0): not a symmetric block cipher [EnumMember] + [SpecTypeName("Symmetric")] Symmetric = 0x2, /// SET (1): a hash algorithm /// CLEAR (0): not a hash algorithm [EnumMember] + [SpecTypeName("Hash")] Hash = 0x4, /// SET (1): an algorithm that may be used as an object type /// CLEAR (0): an algorithm that is not used as an object type [EnumMember] + [SpecTypeName("Object")] Object = 0x8, /// SET (1): a signing algorithm. The setting of asymmetric, symmetric, and hash /// will indicate the type of signing algorithm. /// CLEAR (0): not a signing algorithm [EnumMember] + [SpecTypeName("Signing")] Signing = 0x100, /// SET (1): an encryption/decryption algorithm. The setting of asymmetric, /// symmetric, and hash will indicate the type of encryption/decryption algorithm. /// CLEAR (0): not an encryption/decryption algorithm [EnumMember] + [SpecTypeName("Encrypting")] Encrypting = 0x200, /// SET (1): a method such as a key derivative function (KDF) /// CLEAR (0): not a method [EnumMember] + [SpecTypeName("Method")] Method = 0x400 } @@ -3866,6 +3873,7 @@ public enum ObjectAttr : uint /// NOTE fixedTPM does not indicate that key material resides on a single TPM (see /// sensitiveDataOrigin). [EnumMember] + [SpecTypeName("FixedTPM")] FixedTPM = 0x2, /// SET (1): Previously saved contexts of this object may not be loaded after @@ -3873,12 +3881,14 @@ public enum ObjectAttr : uint /// CLEAR (0): Saved contexts of this object may be used after a Shutdown(STATE) and /// subsequent Startup(). [EnumMember] + [SpecTypeName("StClear")] StClear = 0x4, /// SET (1): The parent of the object may not change. /// CLEAR (0): The parent of the object may change as the result of a TPM2_Duplicate() of /// the object. [EnumMember] + [SpecTypeName("FixedParent")] FixedParent = 0x10, /// SET (1): Indicates that, when the object was created with TPM2_Create() or @@ -3886,6 +3896,7 @@ public enum ObjectAttr : uint /// CLEAR (0): A portion of the sensitive data, other than the authValue, was provided by /// the caller. [EnumMember] + [SpecTypeName("SensitiveDataOrigin")] SensitiveDataOrigin = 0x20, /// SET (1): Approval of USER role actions with this object may be with an HMAC @@ -3893,6 +3904,7 @@ public enum ObjectAttr : uint /// CLEAR (0): Approval of USER role actions with this object may only be done with a /// policy session. [EnumMember] + [SpecTypeName("UserWithAuth")] UserWithAuth = 0x40, /// SET (1): Approval of ADMIN role actions with this object may only be done @@ -3900,11 +3912,13 @@ public enum ObjectAttr : uint /// CLEAR (0): Approval of ADMIN role actions with this object may be with an HMAC session /// or with a password using the authValue of the object or a policy session. [EnumMember] + [SpecTypeName("AdminWithPolicy")] AdminWithPolicy = 0x80, /// SET (1): The object is not subject to dictionary attack protections. /// CLEAR (0): The object is subject to dictionary attack protections. [EnumMember] + [SpecTypeName("NoDA")] NoDA = 0x400, /// SET (1): If the object is duplicated, then symmetricAlg shall not be @@ -3912,33 +3926,39 @@ public enum ObjectAttr : uint /// CLEAR (0): The object may be duplicated without an inner wrapper on the private /// portion of the object and the new parent may be TPM_RH_NULL. [EnumMember] + [SpecTypeName("EncryptedDuplication")] EncryptedDuplication = 0x800, /// SET (1): Key usage is restricted to manipulate structures of known format; /// the parent of this key shall have restricted SET. /// CLEAR (0): Key usage is not restricted to use on special formats. [EnumMember] + [SpecTypeName("Restricted")] Restricted = 0x10000, /// SET (1): The private portion of the key may be used to decrypt. /// CLEAR (0): The private portion of the key may not be used to decrypt. [EnumMember] + [SpecTypeName("Decrypt")] Decrypt = 0x20000, /// SET (1): For a symmetric cipher object, the private portion of the key may /// be used to encrypt. For other objects, the private portion of the key may be used to sign. /// CLEAR (0): The private portion of the key may not be used to sign or encrypt. [EnumMember] + [SpecTypeName("Sign")] Sign = 0x40000, /// Alias to the sign value. [EnumMember] + [SpecTypeName("Encrypt")] Encrypt = 0x40000, /// SET (1): An asymmetric key that may not be used to sign with TPM2_Sign() /// CLEAR (0): A key that may be used with TPM2_Sign() if sign is SET /// NOTE: This attribute only has significance if sign is SET. [EnumMember] + [SpecTypeName("X509sign")] X509sign = 0x80000 } @@ -3967,6 +3987,7 @@ public enum SessionAttr : byte /// same handle but logically is not the same session. /// This attribute has no effect if the command does not complete successfully. [EnumMember] + [SpecTypeName("ContinueSession")] ContinueSession = 0x1, /// SET (1): In a command, this setting indicates that the command should only @@ -3976,6 +3997,7 @@ public enum SessionAttr : byte /// CLEAR (0): In a command, indicates that the session need not be exclusive at the start /// of the command. In a response, indicates that the session is not exclusive. [EnumMember] + [SpecTypeName("AuditExclusive")] AuditExclusive = 0x2, /// SET (1): In a command, this setting indicates that the audit digest of the @@ -3984,6 +4006,7 @@ public enum SessionAttr : byte /// CLEAR (0): In a command, indicates that the audit digest should not be initialized. /// This bit is always CLEAR in a response. [EnumMember] + [SpecTypeName("AuditReset")] AuditReset = 0x4, /// SET (1): In a command, this setting indicates that the first parameter in @@ -3997,6 +4020,7 @@ public enum SessionAttr : byte /// Such a session is provided for purposes of encrypting a parameter and not for authorization. /// This attribute may be SET in combination with any other session attributes. [EnumMember] + [SpecTypeName("Decrypt")] Decrypt = 0x20, /// SET (1): In a command, this setting indicates that the TPM should use this @@ -4010,6 +4034,7 @@ public enum SessionAttr : byte /// Such a session is provided for purposes of encrypting a parameter and not for /// authorization. [EnumMember] + [SpecTypeName("Encrypt")] Encrypt = 0x40, /// SET (1): In a command or response, this setting indicates that the session @@ -4019,6 +4044,7 @@ public enum SessionAttr : byte /// CLEAR (0): Session is not used for audit. /// If SET in the command, then this attribute will be SET in the response. [EnumMember] + [SpecTypeName("Audit")] Audit = 0x80 } @@ -4033,47 +4059,58 @@ public enum LocalityAttr : byte None = 0, [EnumMember] + [SpecTypeName("LocZero")] LocZero = 0x1, [Obsolete("Use LocalityAttr.LocZero instead")] TpmLocZero = 0x1, [EnumMember] + [SpecTypeName("LocOne")] LocOne = 0x2, [Obsolete("Use LocalityAttr.LocOne instead")] TpmLocOne = 0x2, [EnumMember] + [SpecTypeName("LocTwo")] LocTwo = 0x4, [Obsolete("Use LocalityAttr.LocTwo instead")] TpmLocTwo = 0x4, [EnumMember] + [SpecTypeName("LocThree")] LocThree = 0x8, [Obsolete("Use LocalityAttr.LocThree instead")] TpmLocThree = 0x8, [EnumMember] + [SpecTypeName("LocFour")] LocFour = 0x10, [Obsolete("Use LocalityAttr.LocFour instead")] TpmLocFour = 0x10, /// If any of these bits is set, an extended locality is indicated [EnumMember] + [SpecTypeName("")] ExtendedBitMask = 0xE0, [EnumMember] + [SpecTypeName("")] ExtendedBitOffset = 5, [EnumMember] + [SpecTypeName("")] ExtendedBitLength = 3, [EnumMember] + [SpecTypeName("")] ExtendedBit0 = 0x20, [EnumMember] + [SpecTypeName("")] ExtendedBit1 = 0x40, [EnumMember] + [SpecTypeName("")] ExtendedBit2 = 0x80 } @@ -4093,34 +4130,40 @@ public enum PermanentAttr : uint /// the last TPM2_Clear(). /// CLEAR (0): ownerAuth has not been changed since TPM2_Clear(). [EnumMember] + [SpecTypeName("OwnerAuthSet")] OwnerAuthSet = 0x1, /// SET (1): TPM2_HierarchyChangeAuth() with endorsementAuth has been executed /// since the last TPM2_Clear(). /// CLEAR (0): endorsementAuth has not been changed since TPM2_Clear(). [EnumMember] + [SpecTypeName("EndorsementAuthSet")] EndorsementAuthSet = 0x2, /// SET (1): TPM2_HierarchyChangeAuth() with lockoutAuth has been executed since /// the last TPM2_Clear(). /// CLEAR (0): lockoutAuth has not been changed since TPM2_Clear(). [EnumMember] + [SpecTypeName("LockoutAuthSet")] LockoutAuthSet = 0x4, /// SET (1): TPM2_Clear() is disabled. /// CLEAR (0): TPM2_Clear() is enabled. /// NOTE See TPM2_ClearControl in TPM 2.0 Part 3 for details on changing this attribute. [EnumMember] + [SpecTypeName("DisableClear")] DisableClear = 0x100, /// SET (1): The TPM is in lockout, when failedTries is equal to maxTries. [EnumMember] + [SpecTypeName("InLockout")] InLockout = 0x200, /// SET (1): The EPS was created by the TPM. /// CLEAR (0): The EPS was created outside of the TPM using a manufacturer-specific /// process. [EnumMember] + [SpecTypeName("TpmGeneratedEPS")] TpmGeneratedEPS = 0x400 } @@ -4140,6 +4183,7 @@ public enum StartupClearAttr : uint /// NOTE See TPM2_HierarchyControl in TPM 2.0 Part 3 for details on changing this /// attribute. [EnumMember] + [SpecTypeName("PhEnable")] PhEnable = 0x1, /// SET (1): The Storage hierarchy is enabled and ownerAuth or ownerPolicy may @@ -4150,6 +4194,7 @@ public enum StartupClearAttr : uint /// NOTE See TPM2_HierarchyControl in TPM 2.0 Part 3 for details on changing this /// attribute. [EnumMember] + [SpecTypeName("ShEnable")] ShEnable = 0x2, /// SET (1): The EPS hierarchy is enabled and Endorsement Authorization may be @@ -4159,6 +4204,7 @@ public enum StartupClearAttr : uint /// NOTE See TPM2_HierarchyControl in TPM 2.0 Part 3 for details on changing this /// attribute. [EnumMember] + [SpecTypeName("EhEnable")] EhEnable = 0x4, /// SET (1): NV indices that have TPMA_NV_PLATFORMCREATE SET may be read or @@ -4175,6 +4221,7 @@ public enum StartupClearAttr : uint /// does not exist, it also returns this error code if the index is disabled. Otherwise, /// the TPM would leak the existence of an index even when disabled. [EnumMember] + [SpecTypeName("PhEnableNV")] PhEnableNV = 0x8, /// SET (1): The TPM received a TPM2_Shutdown() and a matching TPM2_Startup(). @@ -4183,6 +4230,7 @@ public enum StartupClearAttr : uint /// by a TPM2_Startup() of any type. However, the TPM will return an error if /// TPM2_Startup(TPM_SU_STATE) was not preceded by TPM2_Shutdown(TPM_SU_STATE). [EnumMember] + [SpecTypeName("Orderly")] Orderly = 0x80000000 } @@ -4202,6 +4250,7 @@ public enum MemoryAttr : uint /// CLEAR (0): indicates that the memory used for authorization sessions is not shared /// with memory used for transient objects [EnumMember] + [SpecTypeName("SharedRAM")] SharedRAM = 0x1, /// SET (1): indicates that the NV memory used for persistent objects is shared @@ -4209,6 +4258,7 @@ public enum MemoryAttr : uint /// CLEAR (0): indicates that the persistent objects and NV Index values are allocated /// from separate sections of NV [EnumMember] + [SpecTypeName("SharedNV")] SharedNV = 0x2, /// SET (1): indicates that the TPM copies persistent objects to a @@ -4217,6 +4267,7 @@ public enum MemoryAttr : uint /// CLEAR (0): indicates that the TPM does not use transient-object slots when persistent /// objects are referenced [EnumMember] + [SpecTypeName("ObjectCopiedToRam")] ObjectCopiedToRam = 0x4 } @@ -4233,57 +4284,71 @@ public enum CcAttr : uint /// Indicates the command being selected [EnumMember] + [SpecTypeName("")] commandIndexBitMask = 0xFFFF, [EnumMember] + [SpecTypeName("")] commandIndexBitOffset = 0, [EnumMember] + [SpecTypeName("")] commandIndexBitLength = 16, /// SET (1): indicates that the command may write to NV /// CLEAR (0): indicates that the command does not write to NV [EnumMember] + [SpecTypeName("Nv")] Nv = 0x400000, /// SET (1): This command could flush any number of loaded contexts. /// CLEAR (0): no additional changes other than indicated by the flushed attribute [EnumMember] + [SpecTypeName("Extensive")] Extensive = 0x800000, /// SET (1): The context associated with any transient handle in the command /// will be flushed when this command completes. /// CLEAR (0): No context is flushed as a side effect of this command. [EnumMember] + [SpecTypeName("Flushed")] Flushed = 0x1000000, /// Indicates the number of the handles in the handle area for this command [EnumMember] + [SpecTypeName("")] cHandlesBitMask = 0xE000000, [EnumMember] + [SpecTypeName("")] cHandlesBitOffset = 25, [EnumMember] + [SpecTypeName("")] cHandlesBitLength = 3, /// SET (1): indicates the presence of the handle area in the response [EnumMember] + [SpecTypeName("RHandle")] RHandle = 0x10000000, /// SET (1): indicates that the command is vendor-specific /// CLEAR (0): indicates that the command is defined in a version of this specification [EnumMember] + [SpecTypeName("V")] V = 0x20000000, /// Allocated for software; shall be zero [EnumMember] - ResBitMask = 0xC0000000, + [SpecTypeName("")] + ResBitMask = unchecked ((uint)(0xC0000000)), [EnumMember] + [SpecTypeName("")] ResBitOffset = 30, [EnumMember] + [SpecTypeName("")] ResBitLength = 2 } @@ -4300,6 +4365,7 @@ public enum ModesAttr : uint /// SET (1): indicates that the TPM is designed to comply with all of the FIPS /// 140-2 requirements at Level 1 or higher. [EnumMember] + [SpecTypeName("Fips1402")] Fips1402 = 0x1 } @@ -4317,43 +4383,53 @@ public enum X509KeyUsageAttr : uint /// Attributes.Decrypt SET [EnumMember] + [SpecTypeName("DecipherOnly")] DecipherOnly = 0x800000, /// Attributes.Decrypt SET [EnumMember] + [SpecTypeName("EncipherOnly")] EncipherOnly = 0x1000000, /// Attributes.sign SET [EnumMember] + [SpecTypeName("CRLSign")] CRLSign = 0x2000000, /// Attributes.sign SET [EnumMember] + [SpecTypeName("KeyCertSign")] KeyCertSign = 0x4000000, /// Attributes.Decrypt SET [EnumMember] + [SpecTypeName("KeyAgreement")] KeyAgreement = 0x8000000, /// Attributes.Decrypt SET [EnumMember] + [SpecTypeName("DataEncipherment")] DataEncipherment = 0x10000000, /// Asymmetric key with decrypt and restricted SET key has the attributes of a /// parent key [EnumMember] + [SpecTypeName("KeyEncipherment")] KeyEncipherment = 0x20000000, /// FixedTPM SET in Subject Key (objectHandle) [EnumMember] + [SpecTypeName("Nonrepudiation")] Nonrepudiation = 0x40000000, /// Alias to the nonrepudiation value. [EnumMember] + [SpecTypeName("ContentCommitment")] ContentCommitment = 0x40000000, /// Sign SET in Subject Key (objectHandle) [EnumMember] + [SpecTypeName("DigitalSignature")] DigitalSignature = 0x80000000 } @@ -4372,10 +4448,12 @@ public enum ActAttr : uint /// SET (1): The ACT has signaled /// CLEAR (0): The ACT has not signaled [EnumMember] + [SpecTypeName("Signaled")] Signaled = 0x1, /// Preserves the state of signaled, depending on the power cycle [EnumMember] + [SpecTypeName("PreserveSignaled")] PreserveSignaled = 0x2 } @@ -4392,22 +4470,28 @@ public enum NvIndex : uint /// The Index of the NV location [EnumMember] + [SpecTypeName("")] indexBitMask = 0xFFFFFF, [EnumMember] + [SpecTypeName("")] indexBitOffset = 0, [EnumMember] + [SpecTypeName("")] indexBitLength = 24, /// Constant value of TPM_HT_NV_INDEX indicating the NV Index range [EnumMember] - RhNvBitMask = 0xFF000000, + [SpecTypeName("")] + RhNvBitMask = unchecked ((uint)(0xFF000000)), [EnumMember] + [SpecTypeName("")] RhNvBitOffset = 24, [EnumMember] + [SpecTypeName("")] RhNvBitLength = 8 } @@ -4424,11 +4508,13 @@ public enum NvAttr : uint /// CLEAR (0): Writing of the Index data cannot be authorized with Platform Authorization. /// [EnumMember] + [SpecTypeName("Ppwrite")] Ppwrite = 0x1, /// SET (1): The Index data can be written if Owner Authorization is provided. /// CLEAR (0): Writing of the Index data cannot be authorized with Owner Authorization. [EnumMember] + [SpecTypeName("Ownerwrite")] Ownerwrite = 0x2, /// SET (1): Authorizations to change the Index contents that require USER role @@ -4436,6 +4522,7 @@ public enum NvAttr : uint /// CLEAR (0): Authorizations to change the Index contents that require USER role may not /// be provided with an HMAC session or password. [EnumMember] + [SpecTypeName("Authwrite")] Authwrite = 0x4, /// SET (1): Authorizations to change the Index contents that require USER role @@ -4445,47 +4532,57 @@ public enum NvAttr : uint /// NOTE TPM2_NV_ChangeAuth() always requires that authorization be provided in a policy /// session. [EnumMember] + [SpecTypeName("Policywrite")] Policywrite = 0x8, /// Ordinary contains data that is opaque to the TPM that can only be modified /// using TPM2_NV_Write(). [EnumMember] + [SpecTypeName("Ordinary")] Ordinary = 0x0, /// Counter contains an 8-octet value that is to be used as a counter and can /// only be modified with TPM2_NV_Increment() [EnumMember] + [SpecTypeName("Counter")] Counter = 0x10, /// Bit Field contains an 8-octet value to be used as a bit field and can only /// be modified with TPM2_NV_SetBits(). [EnumMember] + [SpecTypeName("Bits")] Bits = 0x20, /// Extend contains a digest-sized value used like a PCR. The Index can only be /// modified using TPM2_NV_Extend(). The extend will use the nameAlg of the Index. [EnumMember] + [SpecTypeName("Extend")] Extend = 0x40, /// PIN Fail - contains pinCount that increments on a PIN authorization failure /// and a pinLimit [EnumMember] + [SpecTypeName("PinFail")] PinFail = 0x80, /// PIN Pass - contains pinCount that increments on a PIN authorization success /// and a pinLimit [EnumMember] + [SpecTypeName("PinPass")] PinPass = 0x90, /// The type of the index. /// NOTE A TPM is not required to support all TPM_NT values [EnumMember] + [SpecTypeName("")] TpmNtBitMask = 0xF0, [EnumMember] + [SpecTypeName("")] TpmNtBitOffset = 4, [EnumMember] + [SpecTypeName("")] TpmNtBitLength = 4, /// SET (1): Index may not be deleted unless the authPolicy is satisfied using @@ -4495,11 +4592,13 @@ public enum NvAttr : uint /// NOTE An Index with this attribute and a policy that cannot be satisfied (e.g., an /// Empty Policy) cannot be deleted. [EnumMember] + [SpecTypeName("PolicyDelete")] PolicyDelete = 0x400, /// SET (1): Index cannot be written. /// CLEAR (0): Index can be written. [EnumMember] + [SpecTypeName("Writelocked")] Writelocked = 0x800, /// SET (1): A partial write of the Index data is not allowed. The write size @@ -4507,12 +4606,14 @@ public enum NvAttr : uint /// CLEAR (0): Partial writes are allowed. This setting is required if the .dataSize of /// the Index is larger than NV_MAX_BUFFER_SIZE for the implementation. [EnumMember] + [SpecTypeName("Writeall")] Writeall = 0x1000, /// SET (1): TPM2_NV_WriteLock() may be used to prevent further writes to this location. /// CLEAR (0): TPM2_NV_WriteLock() does not block subsequent writes if /// TPMA_NV_WRITE_STCLEAR is also CLEAR. [EnumMember] + [SpecTypeName("Writedefine")] Writedefine = 0x2000, /// SET (1): TPM2_NV_WriteLock() may be used to prevent further writes to this @@ -4520,33 +4621,39 @@ public enum NvAttr : uint /// CLEAR (0): TPM2_NV_WriteLock() does not block subsequent writes if TPMA_NV_WRITEDEFINE /// is also CLEAR. [EnumMember] + [SpecTypeName("WriteStclear")] WriteStclear = 0x4000, /// SET (1): If TPM2_NV_GlobalWriteLock() is successful, TPMA_NV_WRITELOCKED is set. /// CLEAR (0): TPM2_NV_GlobalWriteLock() has no effect on the writing of the data at this /// Index. [EnumMember] + [SpecTypeName("Globallock")] Globallock = 0x8000, /// SET (1): The Index data can be read if Platform Authorization is provided. /// CLEAR (0): Reading of the Index data cannot be authorized with Platform Authorization. /// [EnumMember] + [SpecTypeName("Ppread")] Ppread = 0x10000, /// SET (1): The Index data can be read if Owner Authorization is provided. /// CLEAR (0): Reading of the Index data cannot be authorized with Owner Authorization. [EnumMember] + [SpecTypeName("Ownerread")] Ownerread = 0x20000, /// SET (1): The Index data may be read if the authValue is provided. /// CLEAR (0): Reading of the Index data cannot be authorized with the Index authValue. [EnumMember] + [SpecTypeName("Authread")] Authread = 0x40000, /// SET (1): The Index data may be read if the authPolicy is satisfied. /// CLEAR (0): Reading of the Index data cannot be authorized with the Index authPolicy. [EnumMember] + [SpecTypeName("Policyread")] Policyread = 0x80000, /// SET (1): Authorization failures of the Index do not affect the DA logic and @@ -4555,6 +4662,7 @@ public enum NvAttr : uint /// failure counter and authorizations of this Index are not allowed when the TPM is in /// Lockout mode. [EnumMember] + [SpecTypeName("NoDa")] NoDa = 0x2000000, /// SET (1): NV Index state is only required to be saved when the TPM performs @@ -4563,22 +4671,26 @@ public enum NvAttr : uint /// Index completes successfully (that is, the NV update is synchronous with the update /// command). [EnumMember] + [SpecTypeName("Orderly")] Orderly = 0x4000000, /// SET (1): TPMA_NV_WRITTEN for the Index is CLEAR by TPM Reset or TPM Restart. /// CLEAR (0): TPMA_NV_WRITTEN is not changed by TPM Restart. /// NOTE This attribute may only be SET if TPM_NT is not TPM_NT_COUNTER. [EnumMember] + [SpecTypeName("ClearStclear")] ClearStclear = 0x8000000, /// SET (1): Reads of the Index are blocked until the next TPM Reset or TPM Restart. /// CLEAR (0): Reads of the Index are allowed if proper authorization is provided. [EnumMember] + [SpecTypeName("Readlocked")] Readlocked = 0x10000000, /// SET (1): Index has been written. /// CLEAR (0): Index has not been written. [EnumMember] + [SpecTypeName("Written")] Written = 0x20000000, /// SET (1): This Index may be undefined with Platform Authorization but not @@ -4589,11 +4701,13 @@ public enum NvAttr : uint /// Platform Authorization and will validate that this attribute is CLEAR when the Index /// is defined using Owner Authorization. [EnumMember] + [SpecTypeName("Platformcreate")] Platformcreate = 0x40000000, /// SET (1): TPM2_NV_ReadLock() may be used to SET TPMA_NV_READLOCKED for this Index. /// CLEAR (0): TPM2_NV_ReadLock() has no effect on this Index. [EnumMember] + [SpecTypeName("ReadStclear")] ReadStclear = 0x80000000 } diff --git a/TSS.Rust/Cargo.lock b/TSS.Rust/Cargo.lock new file mode 100644 index 00000000..0077bd87 --- /dev/null +++ b/TSS.Rust/Cargo.lock @@ -0,0 +1,601 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "aes" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures", +] + +[[package]] +name = "autocfg" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" + +[[package]] +name = "base64ct" +version = "1.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89e25b6adfb930f02d1981565a6e5d9c547ac15a96606256d3b59040e5cd4ca3" + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "block-padding" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8894febbff9f758034a5b8e12d87918f56dfc64a8e1fe757d65e29041538d93" +dependencies = [ + "generic-array", +] + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "cipher" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" +dependencies = [ + "crypto-common", + "inout", +] + +[[package]] +name = "const-oid" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" + +[[package]] +name = "cpufeatures" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +dependencies = [ + "libc", +] + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "der" +version = "0.7.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" +dependencies = [ + "const-oid", + "pem-rfc7468", + "zeroize", +] + +[[package]] +name = "derivative" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "const-oid", + "crypto-common", + "subtle", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest", +] + +[[package]] +name = "inout" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01" +dependencies = [ + "block-padding", + "generic-array", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" +dependencies = [ + "spin", +] + +[[package]] +name = "libc" +version = "0.2.171" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6" + +[[package]] +name = "libm" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa" + +[[package]] +name = "num-bigint-dig" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc84195820f291c7697304f3cbdadd1cb7199c0efc917ff5eafd71225c136151" +dependencies = [ + "byteorder", + "lazy_static", + "libm", + "num-integer", + "num-iter", + "num-traits", + "rand", + "smallvec", + "zeroize", +] + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-iter" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", + "libm", +] + +[[package]] +name = "pem-rfc7468" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412" +dependencies = [ + "base64ct", +] + +[[package]] +name = "pkcs1" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f" +dependencies = [ + "der", + "pkcs8", + "spki", +] + +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der", + "spki", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "proc-macro2" +version = "1.0.94" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rsa" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78928ac1ed176a5ca1d17e578a1825f3d81ca54cf41053a592584b020cfd691b" +dependencies = [ + "const-oid", + "digest", + "num-bigint-dig", + "num-integer", + "num-traits", + "pkcs1", + "pkcs8", + "rand_core", + "signature", + "spki", + "subtle", + "zeroize", +] + +[[package]] +name = "sha1" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "signature" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" +dependencies = [ + "digest", + "rand_core", +] + +[[package]] +name = "sm3" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebb9a3b702d0a7e33bc4d85a14456633d2b165c2ad839c5fd9a8417c1ab15860" +dependencies = [ + "digest", +] + +[[package]] +name = "smallvec" +version = "1.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fcf8323ef1faaee30a44a340193b1ac6814fd9b7b4e88e9d4519a3e4abe1cfd" + +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" + +[[package]] +name = "spki" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" +dependencies = [ + "base64ct", + "der", +] + +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tss-rust" +version = "0.1.0" +dependencies = [ + "aes", + "cipher", + "derivative", + "hmac", + "lazy_static", + "libc", + "rand", + "rsa", + "sha1", + "sha2", + "sm3", + "windows", + "zeroize", +] + +[[package]] +name = "typenum" +version = "1.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" + +[[package]] +name = "unicode-ident" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "windows" +version = "0.61.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5ee8f3d025738cb02bad7868bbb5f8a6327501e870bf51f1b455b0a2454a419" +dependencies = [ + "windows-collections", + "windows-core", + "windows-future", + "windows-link", + "windows-numerics", +] + +[[package]] +name = "windows-collections" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3beeceb5e5cfd9eb1d76b381630e82c4241ccd0d27f1a39ed41b2760b255c5e8" +dependencies = [ + "windows-core", +] + +[[package]] +name = "windows-core" +version = "0.61.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4763c1de310c86d75a878046489e2e5ba02c649d185f21c67d4cf8a56d098980" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-link", + "windows-result", + "windows-strings", +] + +[[package]] +name = "windows-future" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a1d6bbefcb7b60acd19828e1bc965da6fcf18a7e39490c5f8be71e54a19ba32" +dependencies = [ + "windows-core", + "windows-link", +] + +[[package]] +name = "windows-implement" +version = "0.60.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.100", +] + +[[package]] +name = "windows-interface" +version = "0.59.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.100", +] + +[[package]] +name = "windows-link" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76840935b766e1b0a05c0066835fb9ec80071d4c09a16f6bd5f7e655e3c14c38" + +[[package]] +name = "windows-numerics" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9150af68066c4c5c07ddc0ce30421554771e528bde427614c61038bc2c92c2b1" +dependencies = [ + "windows-core", + "windows-link", +] + +[[package]] +name = "windows-result" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c64fd11a4fd95df68efcfee5f44a294fe71b8bc6a91993e2791938abcc712252" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-strings" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a2ba9642430ee452d5a7aa78d72907ebe8cfda358e8cb7918a2050581322f97" +dependencies = [ + "windows-link", +] + +[[package]] +name = "zerocopy" +version = "0.8.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2586fea28e186957ef732a5f8b3be2da217d65c5969d4b1e17f973ebbe876879" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a996a8f63c5c4448cd959ac1bab0aaa3306ccfd060472f85943ee0750f0169be" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.100", +] + +[[package]] +name = "zeroize" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" diff --git a/TSS.Rust/Cargo.toml b/TSS.Rust/Cargo.toml new file mode 100644 index 00000000..fabcb17c --- /dev/null +++ b/TSS.Rust/Cargo.toml @@ -0,0 +1,35 @@ +[package] +name = "tss-rust" +version = "0.1.0" +edition = "2021" + +[lints.rust] +non_camel_case_types = "allow" +unused-parens = "allow" + +[lib] +crate-type = ["cdylib", "lib"] + +[dependencies] +derivative = "2.2.0" +hmac = "0.12.1" +lazy_static = "1.5.0" +rsa = { version = "0.9.8" } +sm3 = "0.4.2" +windows = "0.61.1" +sha1 = { version = "0.10.6", features = ["oid"] } +sha2 = { version = "0.10.8", features = ["oid"] } +rand = "0.8" +aes = "0.8" +cipher = { version = "0.4", features = ["block-padding"] } +zeroize = "1.8" + +[target.'cfg(windows)'.dependencies] +windows = { version = "0.61.1", features = ["Win32_Foundation", "Win32_Security", "Win32_System_TpmBaseServices", "Win32_Networking", "Win32_Networking_WinSock"] } + +[target.'cfg(unix)'.dependencies] +libc = "0.2" + +[[example]] +name = "tpm_samples" +path = "examples/tpm_samples.rs" diff --git a/TSS.Rust/README.md b/TSS.Rust/README.md new file mode 100644 index 00000000..7f32f938 --- /dev/null +++ b/TSS.Rust/README.md @@ -0,0 +1,64 @@ +# TSS.Rust + +TSS.Rust is a Rust implementation of the TPM 2.0 Software Stack (TSS), providing complete access to the TPM 2.0 API with rich session management and policy support. + +## Features + +* **Complete TPM 2.0 API** - All TPM 2.0 commands, data structures, enumerations, and unions are auto-generated from the TPM 2.0 specification via [TssCodeGen](../TssCodeGen). +* **HMAC Sessions** - Automatic HMAC computation, nonce rolling, and response HMAC verification. +* **Seeded Sessions** - Salted sessions with RSA-OAEP encrypted salt for enhanced security. +* **Bound Sessions** - Sessions bound to specific TPM entities with optimized HMAC handling. +* **Parameter Encryption** - AES-CFB encryption/decryption of command and response parameters. +* **PolicyTree Abstraction** - Object-oriented representation of TPM policy commands with 14 assertion types, supporting software digest computation and TPM session execution. +* **Software Crypto Helpers** - RSA key operations, OAEP encryption, KDFa key derivation, and HMAC computation bridging software and TPM crypto. +* **Async Command Dispatch** - Support for asynchronous TPM command execution. +* **Cross-platform TPM Access** - Windows TBS device support, with simulator connectivity. + +## Building + +```bash +cargo build +``` + +## Running the Samples + +The [examples](./examples) directory contains 37 comprehensive samples. To run them against the Windows TBS device (hardware TPM): + +```bash +cargo run --example tpm_samples +``` + +To connect to a TPM simulator: + +```bash +cargo run --example tpm_samples -- sim +``` + +See the [examples README](./examples/README.md) for a full list of samples. + +## Architecture + +TSS.Rust follows the same architecture as other TSS.MSR implementations: + +* **Auto-generated code** (`src/tpm_types.rs`, `src/tpm2.rs`) - Generated by [TssCodeGen](../TssCodeGen) from the TPM 2.0 specification. Do not edit directly. +* **Hand-written library code:** + - `src/tpm2_impl.rs` - Command dispatch, session handling, marshaling + - `src/auth_session.rs` - HMAC session management (key derivation, nonce rolling, HMAC computation) + - `src/crypto.rs` - Cryptographic primitives (AES, RSA, HMAC, KDFa) + - `src/policy.rs` - PolicyTree abstraction with 14 policy assertion types + - `src/tpm_type_extensions.rs` - Extension methods on generated types + - `src/tpm_device.rs` - TPM device abstraction (TBS, simulator) + +## Dependencies + +Key Rust crates used: +* `rsa`, `sha1`, `sha2`, `hmac` - Cryptographic operations +* `aes`, `cfb-mode` - Symmetric encryption for parameter encryption +* `derivative` - Custom `Default` implementations for generated types +* `windows` - Windows TBS API access + +## See Also + +* [TSS.CPP](../TSS.CPP) - C++ implementation with similar capabilities +* [TSS.Net](../TSS.NET) - C# implementation +* [TssCodeGen](../TssCodeGen) - Code generator tool diff --git a/TSS.Rust/clippy.toml b/TSS.Rust/clippy.toml new file mode 100644 index 00000000..ec880d98 --- /dev/null +++ b/TSS.Rust/clippy.toml @@ -0,0 +1,17 @@ +[package] +name = "tss-rust" +version = "0.1.0" +edition = "2021" + +[build] +rustflags = ["-A", "clippy::non_camel_case_types", "-A", "clippy::unused_variables"] + +[lib] +crate-type = ["cdylib", "lib"] + +[dependencies] +num_enum = "0.7.3" + +[[example]] +name = "tpm_samples" +path = "examples/tpm_samples.rs" diff --git a/TSS.Rust/examples/README.md b/TSS.Rust/examples/README.md new file mode 100644 index 00000000..2941204e --- /dev/null +++ b/TSS.Rust/examples/README.md @@ -0,0 +1,72 @@ +# TSS.Rust Examples + +This directory contains example code for using the TSS.Rust library. + +## Running the Examples + +To run the main samples using the Windows TBS device (hardware TPM): + +```bash +cargo run --example tpm_samples +``` + +To connect to a TPM simulator instead: + +```bash +cargo run --example tpm_samples -- sim +``` + +## Available Samples + +`tpm_samples.rs` contains a comprehensive set of 37 samples demonstrating TPM 2.0 operations: + +### Basic Operations +- **Random** - `GetRandom` / `StirRandom` +- **Hash** - Single-shot and sequence-based hashing (SHA-1, SHA-256) +- **HMAC** - HMAC key creation, sequence and direct computation +- **PCR** - Event, Read, Extend, Reset operations +- **Counter/Timer** - `ReadClock`, `ClockSet`, `ClockRateAdjust` +- **GetCapability** - Enumerate algorithms and commands + +### Key Management +- **Primary Keys** - RSA primary creation, signing, `EvictControl` persistence +- **Child Keys** - Child signing keys, `ContextSave`/`Load`, `ObjectChangeAuth` +- **RSA Encrypt/Decrypt** - RSA-OAEP encryption and decryption +- **Encrypt/Decrypt** - Symmetric AES encryption +- **Software Keys** - Import external RSA keys, cross-validate signatures + +### Auth Sessions +- **Auth Sessions** - HMAC session usage for key creation and signing +- **Seeded Session** - Salted HMAC sessions (RSA-OAEP salt encryption) +- **Bound Session** - Sessions bound to a specific entity +- **Session Encryption** - Parameter encryption/decryption (`decrypt`/`encrypt` attributes) + +### NV Storage +- **NV** - Define/Write/Read/Undefine for simple, counter, bitfield, and extend NV indices + +### Policy +- **Policy Simplest** - `PolicyCommandCode` +- **Policy PCR** - `PolicyPCR` gating access on PCR values +- **Policy OR** - `PolicyOR` branching +- **Policy With Passwords** - `PolicyPassword` / `PolicyAuthValue` +- **Policy CpHash** - Restricting to specific command parameters +- **Policy CounterTimer** - Time-limited access +- **Policy Secret** - Authorization from another entity +- **Policy NV** - NV-based policy conditions +- **Policy NameHash** - Restricting to specific handles +- **Policy Locality** - Locality-based restrictions (trial only on TBS) +- **Policy Tree** - `PolicyTree` abstraction with multiple scenarios + +### Attestation & Audit +- **Attestation** - PCR quoting, time quoting, key certification with signature verification +- **Audit** - Command audit and session audit + +### Other +- **Unseal** - Seal/unseal with PCR + password policy +- **Import/Duplicate** - Key duplication and import +- **ReWrap** - Key rewrapping between parents +- **Activate Credentials** - `MakeCredential` / `ActivateCredential` +- **Async** - Asynchronous command dispatch +- **Dictionary Attack** - DA lockout reset and parameter configuration +- **Misc Admin** - `SelfTest`, `ClockSet`, `ClearControl` +- **Allow Errors** - Error handling demonstration diff --git a/TSS.Rust/examples/tpm_samples.rs b/TSS.Rust/examples/tpm_samples.rs new file mode 100644 index 00000000..bafa94fe --- /dev/null +++ b/TSS.Rust/examples/tpm_samples.rs @@ -0,0 +1,2851 @@ +use std::io::{self, Write}; +use tss_rust::{ + auth_session::Session, + crypto::Crypto, + device::{TpmDevice, TpmTbsDevice}, error::TpmError, + policy::{self, PolicyTree, PolicyCommandCode, PolicyLocality, PolicyOr, PolicyPassword}, + tpm2_impl::*, tpm_structure::{TpmEnum}, tpm_types::* +}; + +lazy_static::lazy_static! { + pub static ref Aes128Cfb: TPMT_SYM_DEF_OBJECT = TPMT_SYM_DEF_OBJECT::new(TPM_ALG_ID::AES, 128, TPM_ALG_ID::CFB); +} + +fn set_color(color: u8) { + if color == 0 { + print!("\x1b[0m"); + } else { + print!("\x1b[1;32m"); // Green + } +} + +fn print_error(msg: &str) { + eprintln!("\x1b[1;31m{}\x1b[0m", msg); +} + +fn announce(test_name: &str) { + set_color(1); + println!(); + println!("=============================================================================================================================="); + println!(" {}", test_name); + println!("=============================================================================================================================="); + println!(); + io::stdout().flush().unwrap(); + set_color(0); +} + +fn get_capabilities(tpm: &mut Tpm2) -> Result<(), Box> { + let mut start_val = 0; + + announce("************************* Algorithms *************************"); + + // For the first example we show how to get a batch (8) properties at a time. + // For simplicity, subsequent samples just get one at a time: avoiding the + // nested loop. + + loop { + let addition_to_start_val: u32; + + let caps = tpm.GetCapability(TPM_CAP::ALGS, start_val, 8)?; + if let Some(caps) = caps.capabilityData { + if let TPMU_CAPABILITIES::algorithms(props) = caps { + for p in props.algProperties.iter() { + println!("{}: {}", p.alg, p.algProperties); + } + + addition_to_start_val = (props.algProperties[props.algProperties.len() - 1] + .alg + .get_value() + + 1) + .into(); + } else { + break; + } + } else { + break; + } + + if (caps.moreData == 0) { + break; + } + + start_val += addition_to_start_val; + } + + start_val = 0; + + let mut supported_commands: Vec = Vec::new(); + + loop { + let caps = tpm.GetCapability(TPM_CAP::COMMANDS, start_val, 32)?; + + if let Some(caps) = caps.capabilityData { + if let TPMU_CAPABILITIES::command(props) = caps { + for p in props.commandAttributes.iter() { + let command_value = p.get_value() & 0xFFFF; + // Decode the packed structure + if let Ok(cc) = TPM_CC::try_from(command_value) { + supported_commands.push(format!("TPM_CC_{}", cc.to_string())); + } + // let masked_attr = TPMA_CC::try_from(p.get_value() & 0xFFff0000)?; + + // println!("Command {}", cc); + + start_val = command_value; + } + } else { + break; + } + } else { + break; + } + + if (caps.moreData == 0) { + break; + } + + start_val += 1; + } + + supported_commands.sort(); + + let announcement = format!("TPM supports {} commands", supported_commands.len()); + + announce(&announcement); + let column_width = 35; + let columns = 3; + let rows = (supported_commands.len() + columns - 1) / columns; + + for row in 0..rows { + for col in 0..columns { + let index = row + col * rows; + if index < supported_commands.len() { + let cmd = &supported_commands[index]; + print!("{: Result { + let object_attributes = TPMA_OBJECT::decrypt | TPMA_OBJECT::restricted + | TPMA_OBJECT::fixedParent | TPMA_OBJECT::fixedTPM + | TPMA_OBJECT::sensitiveDataOrigin | TPMA_OBJECT::userWithAuth; + + let parameters = TPMU_PUBLIC_PARMS::rsaDetail(TPMS_RSA_PARMS::new(&Aes128Cfb, &Some(TPMU_ASYM_SCHEME::null(TPMS_NULL_ASYM_SCHEME::default())), 2048, 65537)); + + let unique = TPMU_PUBLIC_ID::rsa(TPM2B_PUBLIC_KEY_RSA::default()); + + let storage_primary_template = TPMT_PUBLIC::new(TPM_ALG_ID::SHA1, + object_attributes, + &Vec::new(), // No policy + &Some(parameters), + &Some(unique)); + + let resp = tpm.CreatePrimary(&TPM_HANDLE::new(TPM_RH::OWNER.get_value()), + &TPMS_SENSITIVE_CREATE::default(), + &storage_primary_template, + &Default::default(), + &Default::default())?; + + Ok(resp.handle) +} + +fn make_child_signing_key(tpm: &mut Tpm2, parent: &TPM_HANDLE, restricted: bool) -> Result +{ + let restricted_attribute: TPMA_OBJECT = if restricted { TPMA_OBJECT::restricted } else { TPMA_OBJECT(0) }; + + let object_attributes = TPMA_OBJECT::sign | TPMA_OBJECT::fixedParent | TPMA_OBJECT::fixedTPM + | TPMA_OBJECT::sensitiveDataOrigin | TPMA_OBJECT::userWithAuth | restricted_attribute; + + let parameters = TPMU_PUBLIC_PARMS::rsaDetail(TPMS_RSA_PARMS::new(&Default::default(), + &Some(TPMU_ASYM_SCHEME::rsassa(TPMS_SIG_SCHEME_RSASSA { hashAlg: TPM_ALG_ID::SHA1 })), 2048, 65537)); // PKCS1.5 + + let unique = TPMU_PUBLIC_ID::rsa(TPM2B_PUBLIC_KEY_RSA::default()); + + let template = TPMT_PUBLIC::new(TPM_ALG_ID::SHA1, object_attributes, &Default::default(), &Some(parameters), &Some(unique)); + + let new_signing_key = tpm.Create(&parent, &Default::default(), &template, &Default::default(), &Default::default())?; + + tpm.Load(&parent, &new_signing_key.outPrivate, &new_signing_key.outPublic) +} + +fn make_endorsement_key(tpm: &mut Tpm2) -> Result { + let object_attributes = TPMA_OBJECT::decrypt | TPMA_OBJECT::restricted + | TPMA_OBJECT::fixedParent | TPMA_OBJECT::fixedTPM + | TPMA_OBJECT::sensitiveDataOrigin | TPMA_OBJECT::userWithAuth; + + let parameters = TPMU_PUBLIC_PARMS::rsaDetail(TPMS_RSA_PARMS::new(&Aes128Cfb, &Some(TPMU_ASYM_SCHEME::null(TPMS_NULL_ASYM_SCHEME::default())), 2048, 65537)); + + let unique = TPMU_PUBLIC_ID::rsa(TPM2B_PUBLIC_KEY_RSA::default()); + + let template = TPMT_PUBLIC::new(TPM_ALG_ID::SHA1, + object_attributes, + &Vec::new(), + &Some(parameters), + &Some(unique)); + + let resp = tpm.CreatePrimary(&TPM_HANDLE::new(TPM_RH::ENDORSEMENT.get_value()), + &TPMS_SENSITIVE_CREATE::default(), + &template, + &Default::default(), + &Default::default())?; + + Ok(resp.handle) +} + +fn attestation(tpm: &mut Tpm2) -> Result<(), TpmError> { + announce("Attestation Sample"); + + // Attestation is the TPM signing internal data structures. The TPM can perform + // several-types of attestation: we demonstrate signing PCR, keys, and time. + + // To get attestation information we need a restricted signing key and privacy authorization. + let primary_key = make_storage_primary(tpm)?; + let sig_key = make_child_signing_key(tpm, &primary_key, true)?; + + let nonce = vec![2, 6, 1, 1, 9]; + + println!(">> PCR Quoting"); + println!("Created and loaded signing key with handle: {:?}", sig_key); + + // Set up PCR selection for the quote + let pcrs_to_quote = TPMS_PCR_SELECTION::get_selection_array( + TPM_ALG_ID::SHA1, 7 ); + + // Do an event to make sure the value is non-zero + tpm.PCR_Event(&TPM_HANDLE::pcr(7), &vec![1, 2, 3])?; + + // Then read the value so that we can validate the signature later + let pcr_vals = tpm.PCR_Read(&pcrs_to_quote)?; + println!("Read {} PCR values for quoting", pcr_vals.pcrValues.len()); + + // Do the quote. Note that we provide a nonce. + let quote = tpm.Quote(&sig_key, &nonce, &TPMU_SIG_SCHEME::create(TPM_ALG_ID::NULL)?, &pcrs_to_quote)?; + + // Need to cast to the proper attestation type to validate + let attested = quote.quoted.attested; + + if let Some(TPMU_ATTEST::quote(quote_attest)) = attested { + println!("PCR Quote obtained successfully"); + println!("PCR Quote: {:?}", quote_attest); + println!("Nonce: {:?}", quote.quoted.extraData); + } else { + println!("Failed to cast to quote attestation"); + return Err(TpmError::InvalidParameter); + } ; + + let time_nonce: Vec = vec![1, 6, 8, 2, 1]; + println!(">> Time Quoting, using nonce {:?}", time_nonce); + + let time_quote = tpm.GetTime(&TPM_HANDLE::new(TPM_RH::ENDORSEMENT.get_value()), &sig_key, &time_nonce, &TPMU_SIG_SCHEME::create(TPM_ALG_ID::NULL)?)?; + + if let Some(TPMU_ATTEST::time(time_attest)) = time_quote.timeInfo.attested { + println!("Time Quote obtained successfully"); + let clock_info = time_attest.time.clockInfo; + println!(" Firmware Version: {}", time_attest.firmwareVersion); + println!(" Time: {}", time_attest.time.time); + println!(" Clock: {}", clock_info.clock); + println!(" ResetCount: {}", clock_info.resetCount); + println!(" RestartCount: {}", clock_info.restartCount); + println!(" Nonce: {:?}", time_quote.timeInfo.extraData); + } else { + println!("Failed to cast to quote attestation"); + return Err(TpmError::InvalidParameter); + } ; + + // Get a key attestation. For simplicity we have the signingKey self-certify b + let key_nonce: Vec = vec![0, 9, 1, 1, 2, 3]; + println!(">> Key Quoting, using nonce {:?}", key_nonce); + + let key_quote = tpm.Certify(&sig_key, &sig_key, &key_nonce, &TPMU_SIG_SCHEME::create(TPM_ALG_ID::NULL)?)?; + + if let Some(TPMU_ATTEST::certify(certify_attest)) = &key_quote.certifyInfo.attested { + println!("Key certification obtained successfully"); + println!(" Name of certified key: {:?}", certify_attest.name); + println!(" Qualified name of certified key: {:?}", certify_attest.qualifiedName); + println!(" nonce: {:?}", &key_quote.certifyInfo.extraData); + println!(" Signature: {:?}", &key_quote.signature); + } else { + println!("Failed to cast to quote attestation"); + return Err(TpmError::InvalidParameter); + } ; + + let pub_key = tpm.ReadPublic(&sig_key)?; + + if (pub_key.outPublic.validate_certify(&pub_key.outPublic, &key_nonce, &key_quote)?) { + println!("Key certification signature verification SUCCESSFUL! "); + } else { + println!("Key certification signature verification FAILED! "); + } + + // // Clean up - flush keys from TPM + tpm.FlushContext(&sig_key)?; + println!("Cleaned up keys from TPM"); + + Ok(()) +} + + +fn activate_credentials(tpm: &mut Tpm2) -> Result<(), TpmError> { + announce("Activate Credentials"); + + // Make a new EK and get the public key + let ek_handle = make_endorsement_key(tpm)?; + let ek_pub_response = tpm.ReadPublic(&ek_handle)?; + let ek_pub = ek_pub_response.outPublic; + + // Make another key that we will "activate" + let srk = make_storage_primary(tpm)?; + let key_to_activate = make_child_signing_key(tpm, &srk, true)?; + tpm.FlushContext(&srk)?; + + // Make a secret using the TSS.Rust RNG + let secret = Crypto::get_random(20); + let name_of_key_to_activate = key_to_activate.get_name()?; + + // Use TSS.Rust to get an activation blob + let cred = ek_pub.create_activation(&secret, &name_of_key_to_activate)?; + let recovered_secret = tpm.ActivateCredential(&key_to_activate, &ek_handle, + &cred.credential_blob, &cred.secret)?; + + println!("Secret: {:?}", secret); + println!("Secret recovered from Activate: {:?}", recovered_secret); + + if secret != recovered_secret { + print_error("Secret mismatch when using TSS.Rust to create an activation credential (known create_activation issue)"); + } else { + println!("TSS.Rust-created activation blob verified"); + } + + // You can also use the TPM to make the activation credential + let tpm_activator = tpm.MakeCredential(&ek_handle, &secret, &name_of_key_to_activate)?; + + let recovered_secret = tpm.ActivateCredential(&key_to_activate, &ek_handle, + &tpm_activator.credentialBlob, &tpm_activator.secret)?; + + println!("TPM-created activation blob: Secret recovered from Activate: {:?}", recovered_secret); + + assert!(secret == recovered_secret, "Secret mismatch when using the TPM to create an activation credential"); + + tpm.FlushContext(&ek_handle)?; + tpm.FlushContext(&key_to_activate)?; + + Ok(()) +} + +// =============================== Basic Samples (no auth sessions needed) =============================== + +fn rand_sample(tpm: &mut Tpm2) -> Result<(), TpmError> { + announce("Random Number Sample"); + + // Get 20 random bytes from the TPM + let rand = tpm.GetRandom(20)?; + println!("Random bytes (first call): {:?}", rand); + + // Add entropy to the TPM RNG + tpm.StirRandom(&vec![1, 2, 3, 4, 5])?; + println!("Stirred random with [1, 2, 3, 4, 5]"); + + // Get more random bytes + let rand2 = tpm.GetRandom(20)?; + println!("Random bytes (second call): {:?}", rand2); + + assert_ne!(rand, rand2, "Two random calls should produce different results"); + println!("Random number generation works correctly"); + + Ok(()) +} + +fn hash_sample(tpm: &mut Tpm2) -> Result<(), TpmError> { + announce("Hash Sample"); + + let data = b"Hello, TPM hashing!".to_vec(); + + // Simple hash + let hash_resp = tpm.Hash(&data, TPM_ALG_ID::SHA256, &TPM_HANDLE::new(TPM_RH::NULL.get_value()))?; + println!("SHA-256 hash of data: {:?}", hash_resp.outHash); + + // Hash with SHA-1 + let hash1_resp = tpm.Hash(&data, TPM_ALG_ID::SHA1, &TPM_HANDLE::new(TPM_RH::NULL.get_value()))?; + println!("SHA-1 hash of data: {:?}", hash1_resp.outHash); + + // Hash sequence (multi-part hashing) + println!("\n>> Hash Sequence (multi-part hashing)"); + let accumulator = b"Hello, TPM hashing!".to_vec(); + let part1 = accumulator[..10].to_vec(); + let part2 = accumulator[10..].to_vec(); + + let seq_handle = tpm.HashSequenceStart(&vec![], TPM_ALG_ID::SHA256)?; + tpm.SequenceUpdate(&seq_handle, &part1)?; + let seq_result = tpm.SequenceComplete(&seq_handle, &part2, &TPM_HANDLE::new(TPM_RH::NULL.get_value()))?; + + println!("Sequence hash result: {:?}", seq_result.result); + assert_eq!(hash_resp.outHash, seq_result.result, + "Single-shot and sequence hash should match"); + println!("Single-shot and sequence hash results match!"); + + Ok(()) +} + +fn hmac_sample(tpm: &mut Tpm2) -> Result<(), TpmError> { + announce("HMAC Sample"); + + // Create an HMAC primary key + let object_attributes = TPMA_OBJECT::sign + | TPMA_OBJECT::fixedParent | TPMA_OBJECT::fixedTPM + | TPMA_OBJECT::sensitiveDataOrigin | TPMA_OBJECT::userWithAuth; + + let parameters = TPMU_PUBLIC_PARMS::keyedHashDetail(TPMS_KEYEDHASH_PARMS::new( + &Some(TPMU_SCHEME_KEYEDHASH::hmac(TPMS_SCHEME_HMAC { hashAlg: TPM_ALG_ID::SHA256 })))); + + let unique = TPMU_PUBLIC_ID::keyedHash(TPM2B_DIGEST_KEYEDHASH::default()); + + let hmac_template = TPMT_PUBLIC::new( + TPM_ALG_ID::SHA256, + object_attributes, + &Vec::new(), + &Some(parameters), + &Some(unique), + ); + + let hmac_key_resp = tpm.CreatePrimary( + &TPM_HANDLE::new(TPM_RH::OWNER.get_value()), + &TPMS_SENSITIVE_CREATE::default(), + &hmac_template, + &Default::default(), + &Default::default(), + )?; + + println!("Created HMAC key with handle: {:?}", hmac_key_resp.handle); + + // HMAC using sequence interface + let data = b"Data to HMAC".to_vec(); + let hmac_handle = tpm.HMAC_Start(&hmac_key_resp.handle, &vec![], TPM_ALG_ID::SHA256)?; + tpm.SequenceUpdate(&hmac_handle, &data)?; + let hmac_result = tpm.SequenceComplete(&hmac_handle, &vec![], &TPM_HANDLE::new(TPM_RH::NULL.get_value()))?; + println!("HMAC (sequence): {:?}", hmac_result.result); + + // HMAC using direct command + let hmac_direct = tpm.HMAC(&hmac_key_resp.handle, &data, TPM_ALG_ID::SHA256)?; + println!("HMAC (direct): {:?}", hmac_direct); + + assert_eq!(hmac_result.result, hmac_direct, "Sequence and direct HMAC should match"); + println!("Sequence and direct HMAC results match!"); + + tpm.FlushContext(&hmac_key_resp.handle)?; + Ok(()) +} + +fn pcr_sample(tpm: &mut Tpm2) -> Result<(), TpmError> { + announce("PCR Sample"); + + // Use PCR 16 (resettable) + let pcr_handle = TPM_HANDLE::pcr(16); + + // Reset the PCR first + tpm.PCR_Reset(&pcr_handle)?; + println!("PCR 16 reset"); + + // Read the PCR value (should be all zeros after reset) + let pcr_selection = TPMS_PCR_SELECTION::get_selection_array(TPM_ALG_ID::SHA256, 16); + let pcr_vals = tpm.PCR_Read(&pcr_selection)?; + println!("PCR 16 after reset: {:?}", pcr_vals.pcrValues); + + // Extend a value into the PCR + let event_data = vec![1, 2, 3, 4, 5]; + tpm.PCR_Event(&pcr_handle, &event_data)?; + println!("Extended event data [1, 2, 3, 4, 5] into PCR 16"); + + // Read the PCR value after extend + let pcr_vals2 = tpm.PCR_Read(&pcr_selection)?; + println!("PCR 16 after event: {:?}", pcr_vals2.pcrValues); + + // Extend with a hash value + let extend_hash = TPMT_HA::new(TPM_ALG_ID::SHA256, &Crypto::hash(TPM_ALG_ID::SHA256, &vec![6, 7, 8])?); + tpm.PCR_Extend(&pcr_handle, &vec![extend_hash])?; + println!("Extended hash into PCR 16"); + + // Read again + let pcr_vals3 = tpm.PCR_Read(&pcr_selection)?; + println!("PCR 16 after extend: {:?}", pcr_vals3.pcrValues); + + // Reset again + tpm.PCR_Reset(&pcr_handle)?; + let pcr_vals_final = tpm.PCR_Read(&pcr_selection)?; + println!("PCR 16 after final reset: {:?}", pcr_vals_final.pcrValues); + + println!("PCR operations completed successfully"); + Ok(()) +} + +fn primary_keys_sample(tpm: &mut Tpm2) -> Result<(), TpmError> { + announce("Primary Keys Sample"); + + // Create an RSA signing primary key + let sign_attrs = TPMA_OBJECT::sign + | TPMA_OBJECT::fixedParent | TPMA_OBJECT::fixedTPM + | TPMA_OBJECT::sensitiveDataOrigin | TPMA_OBJECT::userWithAuth; + + let sign_parms = TPMU_PUBLIC_PARMS::rsaDetail(TPMS_RSA_PARMS::new( + &Default::default(), + &Some(TPMU_ASYM_SCHEME::rsassa(TPMS_SIG_SCHEME_RSASSA { hashAlg: TPM_ALG_ID::SHA256 })), + 2048, 65537, + )); + + let sign_template = TPMT_PUBLIC::new( + TPM_ALG_ID::SHA256, + sign_attrs, + &Vec::new(), + &Some(sign_parms), + &Some(TPMU_PUBLIC_ID::rsa(TPM2B_PUBLIC_KEY_RSA::default())), + ); + + let new_primary = tpm.CreatePrimary( + &TPM_HANDLE::new(TPM_RH::OWNER.get_value()), + &TPMS_SENSITIVE_CREATE::default(), + &sign_template, + &Default::default(), + &Default::default(), + )?; + println!("Created signing primary key with handle: {:?}", new_primary.handle); + + // Sign some data + let data_to_sign = Crypto::hash(TPM_ALG_ID::SHA256, &b"Data to sign".to_vec())?; + let signature = tpm.Sign( + &new_primary.handle, + &data_to_sign, + &TPMU_SIG_SCHEME::create(TPM_ALG_ID::NULL)?, + &TPMT_TK_HASHCHECK::default(), + )?; + println!("Data signed successfully, signature: {:?}", signature.is_some()); + + // Persist the key with EvictControl + let persistent_handle = TPM_HANDLE::new(0x81000100); + + // First clean up any existing persistent key at this handle + tpm.allow_errors(); + let _ = tpm.EvictControl( + &TPM_HANDLE::new(TPM_RH::OWNER.get_value()), + &persistent_handle, + &persistent_handle, + ); + + tpm.EvictControl( + &TPM_HANDLE::new(TPM_RH::OWNER.get_value()), + &new_primary.handle, + &persistent_handle, + )?; + println!("Key persisted at handle: {:?}", persistent_handle); + + // Read back the public part from the persistent handle + let pub_data = tpm.ReadPublic(&persistent_handle)?; + println!("Read back public data from persistent handle"); + println!("Algorithm: {:?}", pub_data.outPublic.nameAlg); + + // Clean up - remove persistent key + tpm.EvictControl( + &TPM_HANDLE::new(TPM_RH::OWNER.get_value()), + &persistent_handle, + &persistent_handle, + )?; + println!("Removed persistent key"); + + tpm.FlushContext(&new_primary.handle)?; + println!("Primary keys sample completed successfully"); + Ok(()) +} + +fn child_keys_sample(tpm: &mut Tpm2) -> Result<(), TpmError> { + announce("Child Keys Sample"); + + // Create a storage primary (parent key) + let primary = make_storage_primary(tpm)?; + println!("Created storage primary: {:?}", primary); + + // Create a child signing key + let sign_key = make_child_signing_key(tpm, &primary, false)?; + println!("Created child signing key: {:?}", sign_key); + + // Sign some data + let data_to_sign = Crypto::hash(TPM_ALG_ID::SHA1, &b"Test data for signing".to_vec())?; + let signature = tpm.Sign( + &sign_key, + &data_to_sign, + &TPMU_SIG_SCHEME::create(TPM_ALG_ID::NULL)?, + &TPMT_TK_HASHCHECK::default(), + )?; + assert!(signature.is_some(), "Signature should not be empty"); + println!("Signed data with child key"); + + // Context save and load + // Note: ContextSave/ContextLoad may be blocked by Windows TBS + println!("\n>> Context Save/Load"); + let saved_context = tpm.ContextSave(&sign_key)?; + println!("Saved signing key context"); + + tpm.FlushContext(&sign_key)?; + println!("Flushed signing key from TPM"); + + let restored_key = tpm.ContextLoad(&saved_context)?; + println!("Restored signing key from saved context: {:?}", restored_key); + + // Sign again with restored key to verify it works + let signature2 = tpm.Sign( + &restored_key, + &data_to_sign, + &TPMU_SIG_SCHEME::create(TPM_ALG_ID::NULL)?, + &TPMT_TK_HASHCHECK::default(), + )?; + assert!(signature2.is_some(), "Restored key signature should not be empty"); + println!("Signed data with restored key"); + + tpm.FlushContext(&restored_key)?; + tpm.FlushContext(&primary)?; + println!("Child keys sample completed successfully"); + Ok(()) +} + +fn counter_timer_sample(tpm: &mut Tpm2) -> Result<(), TpmError> { + announce("Counter/Timer Sample"); + + let time_info = tpm.ReadClock()?; + println!("TPM Clock Information:"); + println!("Time (ms since last reset): {}", time_info.time); + println!("Clock (ms total): {}", time_info.clockInfo.clock); + println!("Reset count: {}", time_info.clockInfo.resetCount); + println!("Restart count: {}", time_info.clockInfo.restartCount); + println!("Safe: {}", time_info.clockInfo.safe); + + println!("Counter/Timer sample completed successfully"); + Ok(()) +} + +fn nv_sample(tpm: &mut Tpm2) -> Result<(), TpmError> { + announce("NV (Non-Volatile) Storage Sample"); + + let owner = TPM_HANDLE::new(TPM_RH::OWNER.get_value()); + + // ---- Simple NV (ordinary data) ---- + println!(">> Simple NV (read/write bytes)"); + let nv_index = TPM_HANDLE::new(0x01500100); + let nv_data_size: u16 = 32; + + // Clean up any existing NV index + tpm.allow_errors(); + let _ = tpm.NV_UndefineSpace(&owner, &nv_index); + + // Define the NV space + let nv_pub = TPMS_NV_PUBLIC::new( + &nv_index, + TPM_ALG_ID::SHA256, + TPMA_NV::AUTHREAD | TPMA_NV::AUTHWRITE, + &Vec::new(), + nv_data_size, + ); + tpm.NV_DefineSpace(&owner, &vec![], &nv_pub)?; + println!("Defined NV index at {:?}, size = {}", nv_index, nv_data_size); + + // Write data + let write_data: Vec = (0..nv_data_size as u8).collect(); + tpm.NV_Write(&nv_index, &nv_index, &write_data, 0)?; + println!("Wrote {} bytes to NV", write_data.len()); + + // Read it back + let read_data = tpm.NV_Read(&nv_index, &nv_index, nv_data_size, 0)?; + println!("Read back: {:?}", read_data); + assert_eq!(write_data, read_data, "NV read should match write"); + println!("NV read matches write"); + + // Read public info + let nv_pub_info = tpm.NV_ReadPublic(&nv_index)?; + println!("NV Public info - dataSize: {}, nameAlg: {:?}", nv_pub_info.nvPublic.dataSize, nv_pub_info.nvPublic.nameAlg); + + // Clean up + tpm.NV_UndefineSpace(&owner, &nv_index)?; + println!("Undefined NV space"); + + // ---- Counter NV ---- + println!("\n>> Counter NV"); + let counter_index = TPM_HANDLE::new(0x01500101); + + tpm.allow_errors(); + let _ = tpm.NV_UndefineSpace(&owner, &counter_index); + + let counter_pub = TPMS_NV_PUBLIC::new( + &counter_index, + TPM_ALG_ID::SHA256, + TPMA_NV::AUTHREAD | TPMA_NV::AUTHWRITE | TPMA_NV::COUNTER, + &Vec::new(), + 8, + ); + tpm.NV_DefineSpace(&owner, &vec![], &counter_pub)?; + println!("Defined counter NV index"); + + // Increment + tpm.NV_Increment(&counter_index, &counter_index)?; + let counter_val = tpm.NV_Read(&counter_index, &counter_index, 8, 0)?; + println!("Counter after first increment: {:?}", counter_val); + + tpm.NV_Increment(&counter_index, &counter_index)?; + let counter_val2 = tpm.NV_Read(&counter_index, &counter_index, 8, 0)?; + println!("Counter after second increment: {:?}", counter_val2); + + tpm.NV_UndefineSpace(&owner, &counter_index)?; + println!("Counter NV works correctly"); + + // ---- Bit field NV ---- + println!("\n>> Bit Field NV"); + let bit_index = TPM_HANDLE::new(0x01500102); + + tpm.allow_errors(); + let _ = tpm.NV_UndefineSpace(&owner, &bit_index); + + let bits_pub = TPMS_NV_PUBLIC::new( + &bit_index, + TPM_ALG_ID::SHA256, + TPMA_NV::AUTHREAD | TPMA_NV::AUTHWRITE | TPMA_NV::BITS, + &Vec::new(), + 8, + ); + tpm.NV_DefineSpace(&owner, &vec![], &bits_pub)?; + println!("Defined bit field NV index"); + + tpm.NV_SetBits(&bit_index, &bit_index, 0x0000_0001)?; + let bits_val = tpm.NV_Read(&bit_index, &bit_index, 8, 0)?; + println!("Bits after setting bit 0: {:?}", bits_val); + + tpm.NV_SetBits(&bit_index, &bit_index, 0x0000_0004)?; + let bits_val2 = tpm.NV_Read(&bit_index, &bit_index, 8, 0)?; + println!("Bits after setting bit 2: {:?}", bits_val2); + + tpm.NV_UndefineSpace(&owner, &bit_index)?; + println!("Bit field NV works correctly"); + + // ---- Extend NV ---- + println!("\n>> Extend NV"); + let extend_index = TPM_HANDLE::new(0x01500103); + + tpm.allow_errors(); + let _ = tpm.NV_UndefineSpace(&owner, &extend_index); + + let extend_pub = TPMS_NV_PUBLIC::new( + &extend_index, + TPM_ALG_ID::SHA256, + TPMA_NV::AUTHREAD | TPMA_NV::AUTHWRITE | TPMA_NV::EXTEND, + &Vec::new(), + 32, // SHA-256 digest size + ); + tpm.NV_DefineSpace(&owner, &vec![], &extend_pub)?; + println!("Defined extend NV index"); + + tpm.NV_Extend(&extend_index, &extend_index, &vec![1, 2, 3, 4, 5])?; + let extend_val = tpm.NV_Read(&extend_index, &extend_index, 32, 0)?; + println!("Extend NV after extend: {:?}", extend_val); + + tpm.NV_UndefineSpace(&owner, &extend_index)?; + println!("Extend NV works correctly"); + + Ok(()) +} + +fn rsa_encrypt_decrypt_sample(tpm: &mut Tpm2) -> Result<(), TpmError> { + announce("RSA Encrypt/Decrypt Sample"); + + // Create an RSA decryption key (not restricted - for general encrypt/decrypt) + let rsa_attrs = TPMA_OBJECT::decrypt + | TPMA_OBJECT::fixedParent | TPMA_OBJECT::fixedTPM + | TPMA_OBJECT::sensitiveDataOrigin | TPMA_OBJECT::userWithAuth; + + let rsa_parms = TPMU_PUBLIC_PARMS::rsaDetail(TPMS_RSA_PARMS::new( + &Default::default(), + &Some(TPMU_ASYM_SCHEME::oaep(TPMS_ENC_SCHEME_OAEP { hashAlg: TPM_ALG_ID::SHA256 })), + 2048, 65537, + )); + + let rsa_template = TPMT_PUBLIC::new( + TPM_ALG_ID::SHA256, + rsa_attrs, + &Vec::new(), + &Some(rsa_parms), + &Some(TPMU_PUBLIC_ID::rsa(TPM2B_PUBLIC_KEY_RSA::default())), + ); + + let key_resp = tpm.CreatePrimary( + &TPM_HANDLE::new(TPM_RH::NULL.get_value()), + &TPMS_SENSITIVE_CREATE::default(), + &rsa_template, + &Default::default(), + &Default::default(), + )?; + println!("Created RSA decryption key: {:?}", key_resp.handle); + + // Encrypt data using the TPM + let plaintext = b"Secret message for RSA encryption!".to_vec(); + let null_scheme = TPMU_ASYM_SCHEME::null(TPMS_NULL_ASYM_SCHEME::default()); + let ciphertext = tpm.RSA_Encrypt(&key_resp.handle, &plaintext, &Some(null_scheme.clone()), &vec![])?; + println!("Encrypted {} bytes -> {} bytes ciphertext", plaintext.len(), ciphertext.len()); + + // Decrypt + let decrypted = tpm.RSA_Decrypt(&key_resp.handle, &ciphertext, &Some(null_scheme), &vec![])?; + println!("Decrypted: {:?}", String::from_utf8_lossy(&decrypted)); + + assert_eq!(plaintext, decrypted, "Decrypted data should match original"); + println!("RSA encrypt/decrypt works correctly"); + + tpm.FlushContext(&key_resp.handle)?; + Ok(()) +} + +fn encrypt_decrypt_sample(tpm: &mut Tpm2) -> Result<(), TpmError> { + announce("Symmetric Encrypt/Decrypt Sample"); + + // Create a storage primary + let primary = make_storage_primary(tpm)?; + + // Create an AES symmetric key + let aes_attrs = TPMA_OBJECT::decrypt | TPMA_OBJECT::sign + | TPMA_OBJECT::fixedParent | TPMA_OBJECT::fixedTPM + | TPMA_OBJECT::sensitiveDataOrigin | TPMA_OBJECT::userWithAuth; + + let aes_parms = TPMU_PUBLIC_PARMS::symDetail(TPMS_SYMCIPHER_PARMS::new(&Aes128Cfb)); + + let aes_template = TPMT_PUBLIC::new( + TPM_ALG_ID::SHA256, + aes_attrs, + &Vec::new(), + &Some(aes_parms), + &Some(TPMU_PUBLIC_ID::sym(TPM2B_DIGEST_SYMCIPHER::default())), + ); + + let aes_key = tpm.Create( + &primary, + &TPMS_SENSITIVE_CREATE::default(), + &aes_template, + &Default::default(), + &Default::default(), + )?; + let aes_handle = tpm.Load(&primary, &aes_key.outPrivate, &aes_key.outPublic)?; + println!("Created and loaded AES key: {:?}", aes_handle); + + // Note: EncryptDecrypt/EncryptDecrypt2 may be blocked by Windows TBS + let plaintext = b"Hello AES encryption! padding!!".to_vec(); // 32 bytes (block-aligned) + let iv = vec![0u8; 16]; + let encrypted = tpm.EncryptDecrypt(&aes_handle, 0, TPM_ALG_ID::CFB, &iv, &plaintext)?; + println!("Encrypted {} bytes", plaintext.len()); + + // Decrypt (decrypt=1) + let decrypted = tpm.EncryptDecrypt(&aes_handle, 1, TPM_ALG_ID::CFB, &iv, &encrypted.outData)?; + println!("Decrypted: {:?}", String::from_utf8_lossy(&decrypted.outData)); + + assert_eq!(plaintext, decrypted.outData, "Decrypted data should match original"); + println!("AES encrypt/decrypt works correctly"); + + tpm.FlushContext(&aes_handle)?; + tpm.FlushContext(&primary)?; + Ok(()) +} + +// =============================== Auth Session Samples =============================== + +/// Helper: create an HMAC primary key with a policy digest and optional auth value. +fn make_hmac_primary_with_policy( + tpm: &mut Tpm2, + policy_digest: &[u8], + use_auth: &[u8], + hash_alg: TPM_ALG_ID, +) -> Result { + let key_data = vec![5, 4, 3, 2, 1, 0]; + let mut attrs = TPMA_OBJECT::sign | TPMA_OBJECT::fixedParent | TPMA_OBJECT::fixedTPM; + if !use_auth.is_empty() { + attrs = attrs | TPMA_OBJECT::userWithAuth; + } + + let parameters = TPMU_PUBLIC_PARMS::keyedHashDetail(TPMS_KEYEDHASH_PARMS::new( + &Some(TPMU_SCHEME_KEYEDHASH::hmac(TPMS_SCHEME_HMAC { hashAlg: hash_alg })))); + let unique = TPMU_PUBLIC_ID::keyedHash(TPM2B_DIGEST_KEYEDHASH::default()); + + let templ = TPMT_PUBLIC::new( + hash_alg, attrs, &policy_digest.to_vec(), + &Some(parameters), &Some(unique), + ); + + let sens = TPMS_SENSITIVE_CREATE::new(&use_auth.to_vec(), &key_data); + let resp = tpm.CreatePrimary( + &TPM_HANDLE::new(TPM_RH::OWNER.get_value()), + &sens, &templ, &Default::default(), &Default::default(), + )?; + Ok(resp.handle) +} + +/// Helper: get the session handle from a Session (for policy commands and FlushContext). +fn session_handle(sess: &Session) -> TPM_HANDLE { + sess.sess_in.sessionHandle.clone() +} + +fn auth_sessions_sample(tpm: &mut Tpm2) -> Result<(), TpmError> { + announce("Auth Sessions Sample"); + + // Start a simple HMAC authorization session (no salt, no encryption, no bound-object) + let mut sess = tpm.start_auth_session(TPM_SE::HMAC, TPM_ALG_ID::SHA1)?; + println!("Started HMAC auth session: {:?}", session_handle(&sess)); + + // Create a storage primary + let primary = make_storage_primary(tpm)?; + + // Create a child key template + let child_attrs = TPMA_OBJECT::sign | TPMA_OBJECT::fixedParent | TPMA_OBJECT::fixedTPM + | TPMA_OBJECT::sensitiveDataOrigin | TPMA_OBJECT::userWithAuth; + let child_parms = TPMU_PUBLIC_PARMS::rsaDetail(TPMS_RSA_PARMS::new( + &Default::default(), + &Some(TPMU_ASYM_SCHEME::rsassa(TPMS_SIG_SCHEME_RSASSA { hashAlg: TPM_ALG_ID::SHA1 })), + 2048, 65537, + )); + let child_template = TPMT_PUBLIC::new( + TPM_ALG_ID::SHA1, child_attrs, &Default::default(), + &Some(child_parms), + &Some(TPMU_PUBLIC_ID::rsa(TPM2B_PUBLIC_KEY_RSA::default())), + ); + + // Create child key using the HMAC session (parent handle uses auth) + let new_key = tpm.with_session(sess.clone()).Create( + &primary, &Default::default(), &child_template, + &Default::default(), &Default::default(), + )?; + // Retrieve updated session (nonces rolled by TPM) + sess = tpm.last_session().unwrap(); + println!("Created child key with HMAC session"); + + // Load the child key with the same session + let loaded_key = tpm.with_session(sess.clone()).Load( + &primary, &new_key.outPrivate, &new_key.outPublic, + )?; + sess = tpm.last_session().unwrap(); + println!("Loaded child key with HMAC session: {:?}", loaded_key); + + // Sign data with the loaded key using the session + let data_to_sign = Crypto::hash(TPM_ALG_ID::SHA1, &b"Auth session test data".to_vec())?; + let sig = tpm.with_session(sess.clone()).Sign( + &loaded_key, &data_to_sign, + &TPMU_SIG_SCHEME::create(TPM_ALG_ID::NULL)?, + &TPMT_TK_HASHCHECK::default(), + )?; + assert!(sig.is_some(), "HMAC session signature should not be empty"); + sess = tpm.last_session().unwrap(); + println!("Signed data using HMAC session"); + + // Clean up + tpm.FlushContext(&session_handle(&sess))?; + tpm.FlushContext(&loaded_key)?; + tpm.FlushContext(&primary)?; + + println!("Auth sessions sample completed successfully"); + Ok(()) +} + +fn dictionary_attack_sample(tpm: &mut Tpm2) -> Result<(), TpmError> { + announce("Dictionary Attack Sample"); + + // Reset the lockout counter. + // This may fail if the TPM's lockout hierarchy is locked from a previous run + // or if TBS restricts this command on Windows. + let lockout = TPM_HANDLE::new(TPM_RH::LOCKOUT.get_value()); + tpm.allow_errors(); + let _ = tpm.DictionaryAttackLockReset(&lockout); + if tpm.last_response_code() != TPM_RC::SUCCESS { + print_error(&format!("DictionaryAttackLockReset failed (rc={:?}) - \ + TPM lockout hierarchy may be locked from a previous run. \ + The lockoutRecovery timer must expire before this command succeeds.", + tpm.last_response_code())); + return Ok(()); + } + println!("Dictionary attack lockout reset"); + + // Configure dictionary attack parameters to be forgiving for testing + let new_max_tries: u32 = 1000; + let new_recovery_time: u32 = 1; + let lockout_recovery: u32 = 1; + tpm.DictionaryAttackParameters(&lockout, new_max_tries, new_recovery_time, lockout_recovery)?; + println!("Set DA parameters: maxTries={}, recoveryTime={}, lockoutRecovery={}", + new_max_tries, new_recovery_time, lockout_recovery); + + println!("Dictionary attack sample completed successfully"); + Ok(()) +} + +fn misc_admin_sample(tpm: &mut Tpm2) -> Result<(), TpmError> { + announce("Misc Admin Sample"); + + // Self Testing + println!(">> Self Testing"); + tpm.allow_errors(); + let _ = tpm.SelfTest(1); + println!("SelfTest completed (or was already done)"); + + let test_result = tpm.GetTestResult()?; + println!("GetTestResult: {} bytes of data, rc={}", test_result.outData.len(), test_result.testResult); + + let to_be_tested = tpm.IncrementalSelfTest(&vec![TPM_ALG_ID::SHA1, TPM_ALG_ID::AES])?; + println!("IncrementalSelfTest: {} algorithms still to test", to_be_tested.len()); + + // Clock Management + println!("\n>> Clock Management"); + let start_clock = tpm.ReadClock()?; + println!("Start clock: {}", start_clock.clockInfo.clock); + + let dt: u64 = 10_000_000; + let new_clock = start_clock.clockInfo.clock + dt; + tpm.ClockSet(&TPM_HANDLE::new(TPM_RH::OWNER.get_value()), new_clock)?; + + let now_clock = tpm.ReadClock()?; + let dt_actual = now_clock.clockInfo.clock - start_clock.clockInfo.clock; + println!("Clock advanced by: {} (requested {})", dt_actual, dt); + + // Can't set clock backwards + tpm.allow_errors(); + let _ = tpm.ClockSet(&TPM_HANDLE::new(TPM_RH::OWNER.get_value()), start_clock.clockInfo.clock); + println!("Setting clock backwards: last_rc = {}", tpm.last_response_code()); + + // Adjust clock rate + tpm.ClockRateAdjust(&TPM_HANDLE::new(TPM_RH::OWNER.get_value()), TPM_CLOCK_ADJUST::MEDIUM_SLOWER)?; + tpm.ClockRateAdjust(&TPM_HANDLE::new(TPM_RH::OWNER.get_value()), TPM_CLOCK_ADJUST::MEDIUM_FASTER)?; + println!("Clock rate adjusted (slower, then faster)"); + + println!("Misc admin sample completed successfully"); + Ok(()) +} + +fn policy_simplest_sample(tpm: &mut Tpm2) -> Result<(), TpmError> { + announce("Policy Simplest Sample (PolicyCommandCode)"); + + // Use a trial session to compute the policy digest for PolicyCommandCode(HMAC_Start) + let trial = tpm.start_auth_session(TPM_SE::TRIAL, TPM_ALG_ID::SHA1)?; + tpm.PolicyCommandCode(&session_handle(&trial), TPM_CC::HMAC_Start)?; + let policy_digest = tpm.PolicyGetDigest(&session_handle(&trial))?; + tpm.FlushContext(&session_handle(&trial))?; + println!("Computed policy digest (trial): {:?}", policy_digest); + + // Create an HMAC primary with this policy (no userAuth) + let hmac_key = make_hmac_primary_with_policy(tpm, &policy_digest, &[], TPM_ALG_ID::SHA1)?; + println!("Created HMAC key with PolicyCommandCode policy"); + + // Show that plain authValue-based access fails + tpm.allow_errors(); + let _ = tpm.HMAC_Start(&hmac_key, &vec![], TPM_ALG_ID::SHA1); + println!("Plain auth HMAC_Start: last_rc = {} (expected AUTH_UNAVAILABLE)", tpm.last_response_code()); + + // Use a real policy session + let sess = tpm.start_auth_session(TPM_SE::POLICY, TPM_ALG_ID::SHA1)?; + tpm.PolicyCommandCode(&session_handle(&sess), TPM_CC::HMAC_Start)?; + + // Verify the policy digest matches + let digest = tpm.PolicyGetDigest(&session_handle(&sess))?; + println!("Computed policy digest (real): {:?}", digest); + assert_eq!(policy_digest, digest, "Trial and real policy digests should match"); + + // Execute the authorized command - should succeed + let hmac_seq_handle = tpm.with_session(sess.clone()).HMAC_Start(&hmac_key, &vec![], TPM_ALG_ID::SHA1)?; + println!("Policy-authorized HMAC_Start succeeded: {:?}", hmac_seq_handle); + tpm.FlushContext(&hmac_seq_handle)?; + tpm.FlushContext(&session_handle(&sess))?; + + // Try a different command with the same policy - should fail with POLICY_CC + let sess2 = tpm.start_auth_session(TPM_SE::POLICY, TPM_ALG_ID::SHA1)?; + tpm.PolicyCommandCode(&session_handle(&sess2), TPM_CC::HMAC_Start)?; + + tpm.allow_errors(); + let _ = tpm.with_session(sess2.clone()).Unseal(&hmac_key); + println!("Unseal with HMAC_Start policy: last_rc = {} (expected POLICY_CC)", tpm.last_response_code()); + + tpm.FlushContext(&session_handle(&sess2))?; + tpm.FlushContext(&hmac_key)?; + + println!("Policy simplest sample completed successfully"); + Ok(()) +} + +fn unseal_sample(tpm: &mut Tpm2) -> Result<(), TpmError> { + announce("Unseal Sample"); + + // Reset dictionary attack lockout (may fail on some TPMs) + tpm.allow_errors(); + let _ = tpm.DictionaryAttackLockReset(&TPM_HANDLE::new(TPM_RH::LOCKOUT.get_value())); + if tpm.last_response_code() != TPM_RC::SUCCESS { + println!("Note: DictionaryAttackLockReset failed (rc={}), continuing...", tpm.last_response_code()); + } + + let pcr: u32 = 15; + let bank = TPM_ALG_ID::SHA256; + + // Set the PCR to a known value + tpm.PCR_Event(&TPM_HANDLE::pcr(pcr), &vec![1, 2, 3, 4])?; + + // Read the current PCR value + let pcr_selection = TPMS_PCR_SELECTION::get_selection_array(bank, pcr); + let pcr_vals = tpm.PCR_Read(&pcr_selection)?; + println!("PCR {} value: {:?}", pcr, pcr_vals.pcrValues); + + // Compute policy digest: PolicyPCR + PolicyPassword + // Use a trial session to compute the digest + let trial = tpm.start_auth_session(TPM_SE::TRIAL, TPM_ALG_ID::SHA256)?; + + // Compute the PCR digest (hash of selected PCR values) + let mut pcr_digest_data = Vec::new(); + for v in &pcr_vals.pcrValues { + pcr_digest_data.extend_from_slice(&v.buffer); + } + let pcr_digest = Crypto::hash(bank, &pcr_digest_data)?; + + tpm.PolicyPCR(&session_handle(&trial), &pcr_digest, &pcr_selection)?; + tpm.PolicyPassword(&session_handle(&trial))?; + let policy_digest = tpm.PolicyGetDigest(&session_handle(&trial))?; + tpm.FlushContext(&session_handle(&trial))?; + println!("Policy digest (PCR + Password): {:?}", policy_digest); + + // Create a sealed object under a storage primary + let primary = make_storage_primary(tpm)?; + + let seal_attrs = TPMA_OBJECT::fixedParent | TPMA_OBJECT::fixedTPM; + let seal_parms = TPMU_PUBLIC_PARMS::keyedHashDetail( + TPMS_KEYEDHASH_PARMS::new(&Some(TPMU_SCHEME_KEYEDHASH::null(TPMS_NULL_SCHEME_KEYEDHASH::default())))); + let seal_template = TPMT_PUBLIC::new( + TPM_ALG_ID::SHA256, seal_attrs, &policy_digest, + &Some(seal_parms), + &Some(TPMU_PUBLIC_ID::keyedHash(TPM2B_DIGEST_KEYEDHASH::default())), + ); + + let data_to_seal: Vec = vec![1, 2, 3, 4, 5, 0xf, 0xe, 0xd, 0xa, 9, 8]; + let auth_value: Vec = vec![9, 8, 7, 6, 5]; + let sens_create = TPMS_SENSITIVE_CREATE::new(&auth_value, &data_to_seal); + + let sealed_obj = tpm.Create(&primary, &sens_create, &seal_template, &Default::default(), &Default::default())?; + let mut sealed_key = tpm.Load(&primary, &sealed_obj.outPrivate, &sealed_obj.outPublic)?; + sealed_key.set_auth(&auth_value); + println!("Created sealed object: {:?}", sealed_key); + + // Start a policy session and execute the policy + let mut sess = tpm.start_auth_session(TPM_SE::POLICY, TPM_ALG_ID::SHA256)?; + tpm.PolicyPCR(&session_handle(&sess), &pcr_digest, &pcr_selection)?; + tpm.PolicyPassword(&session_handle(&sess))?; + // After PolicyPassword, set the flag so auth is sent as password + sess.needs_password = true; + + // Unseal - should succeed with correct auth and PCR + let unsealed = tpm.with_session(sess.clone()).Unseal(&sealed_key)?; + println!("Unsealed data: {:?}", unsealed); + assert_eq!(data_to_seal, unsealed, "Unsealed data should match"); + tpm.FlushContext(&session_handle(&sess))?; + + // Try without auth value - should fail + sealed_key.set_auth(&[]); + let mut sess2 = tpm.start_auth_session(TPM_SE::POLICY, TPM_ALG_ID::SHA256)?; + tpm.PolicyPCR(&session_handle(&sess2), &pcr_digest, &pcr_selection)?; + tpm.PolicyPassword(&session_handle(&sess2))?; + sess2.needs_password = true; + + tpm.allow_errors(); + let _ = tpm.with_session(sess2.clone()).Unseal(&sealed_key); + println!("Unseal without auth: last_rc = {} (expected AUTH_FAIL)", tpm.last_response_code()); + tpm.FlushContext(&session_handle(&sess2))?; + + // Try with wrong PCR value - policy execution should fail + sealed_key.set_auth(&auth_value); + tpm.PCR_Event(&TPM_HANDLE::pcr(pcr), &vec![1, 2, 3, 4])?; // change PCR + let mut sess3 = tpm.start_auth_session(TPM_SE::POLICY, TPM_ALG_ID::SHA256)?; + + tpm.allow_errors(); + let _ = tpm.PolicyPCR(&session_handle(&sess3), &pcr_digest, &pcr_selection); + println!("PolicyPCR with wrong value: last_rc = {} (expected VALUE)", tpm.last_response_code()); + + // Try unseal anyway - should fail + tpm.PolicyPassword(&session_handle(&sess3))?; + sess3.needs_password = true; + tpm.allow_errors(); + let _ = tpm.with_session(sess3.clone()).Unseal(&sealed_key); + println!("Unseal with wrong PCR: last_rc = {} (expected POLICY_FAIL)", tpm.last_response_code()); + tpm.FlushContext(&session_handle(&sess3))?; + + tpm.FlushContext(&sealed_key)?; + tpm.FlushContext(&primary)?; + + println!("Unseal sample completed successfully"); + Ok(()) +} + +fn policy_or_sample(tpm: &mut Tpm2) -> Result<(), TpmError> { + announce("PolicyOR Sample"); + + let bank = TPM_ALG_ID::SHA256; + let pcr: u32 = 15; + + // Set PCR to a known value + tpm.PCR_Event(&TPM_HANDLE::pcr(pcr), &vec![1, 2, 3, 4])?; + + let pcr_selection = TPMS_PCR_SELECTION::get_selection_array(bank, pcr); + let pcr_vals = tpm.PCR_Read(&pcr_selection)?; + + // Compute the PCR digest + let mut pcr_digest_data = Vec::new(); + for v in &pcr_vals.pcrValues { + pcr_digest_data.extend_from_slice(&v.buffer); + } + let pcr_digest = Crypto::hash(bank, &pcr_digest_data)?; + + // Branch 1: PolicyPCR (current PCR value) + let trial1 = tpm.start_auth_session(TPM_SE::TRIAL, TPM_ALG_ID::SHA256)?; + tpm.PolicyPCR(&session_handle(&trial1), &pcr_digest, &pcr_selection)?; + let branch1_digest = tpm.PolicyGetDigest(&session_handle(&trial1))?; + tpm.FlushContext(&session_handle(&trial1))?; + println!("Branch 1 (PolicyPCR) digest: {:?}", branch1_digest); + + // Branch 2: PolicyCommandCode(HMAC_Start) + let trial2 = tpm.start_auth_session(TPM_SE::TRIAL, TPM_ALG_ID::SHA256)?; + tpm.PolicyCommandCode(&session_handle(&trial2), TPM_CC::HMAC_Start)?; + let branch2_digest = tpm.PolicyGetDigest(&session_handle(&trial2))?; + tpm.FlushContext(&session_handle(&trial2))?; + println!("Branch 2 (PolicyCommandCode) digest: {:?}", branch2_digest); + + // Compute the OR policy digest using trial session + let hash_list = vec![ + TPM2B_DIGEST { buffer: branch1_digest.clone() }, + TPM2B_DIGEST { buffer: branch2_digest.clone() }, + ]; + + let trial_or = tpm.start_auth_session(TPM_SE::TRIAL, TPM_ALG_ID::SHA256)?; + tpm.PolicyOR(&session_handle(&trial_or), &hash_list)?; + let or_policy_digest = tpm.PolicyGetDigest(&session_handle(&trial_or))?; + tpm.FlushContext(&session_handle(&trial_or))?; + println!("OR policy digest: {:?}", or_policy_digest); + + // Create an HMAC key with the OR policy + let hmac_key = make_hmac_primary_with_policy(tpm, &or_policy_digest, &[], TPM_ALG_ID::SHA256)?; + + // Use branch 1 (PolicyPCR) - should succeed while PCR is unchanged + let sess1 = tpm.start_auth_session(TPM_SE::POLICY, TPM_ALG_ID::SHA256)?; + tpm.PolicyPCR(&session_handle(&sess1), &pcr_digest, &pcr_selection)?; + tpm.PolicyOR(&session_handle(&sess1), &hash_list)?; + + let hmac_result = tpm.with_session(sess1.clone()).HMAC(&hmac_key, &vec![1, 2, 3, 4], TPM_ALG_ID::SHA256)?; + println!("Branch 1 HMAC succeeded: {:?}", hmac_result); + tpm.FlushContext(&session_handle(&sess1))?; + + // Change PCR - branch 1 should now fail + tpm.PCR_Event(&TPM_HANDLE::pcr(pcr), &vec![5, 6, 7, 8])?; + + let sess2 = tpm.start_auth_session(TPM_SE::POLICY, TPM_ALG_ID::SHA256)?; + tpm.allow_errors(); + let _ = tpm.PolicyPCR(&session_handle(&sess2), &pcr_digest, &pcr_selection); + println!("Branch 1 after PCR change: last_rc = {} (expected VALUE)", tpm.last_response_code()); + tpm.FlushContext(&session_handle(&sess2))?; + + // Use branch 2 (PolicyCommandCode) - should succeed regardless of PCR + let sess3 = tpm.start_auth_session(TPM_SE::POLICY, TPM_ALG_ID::SHA256)?; + tpm.PolicyCommandCode(&session_handle(&sess3), TPM_CC::HMAC_Start)?; + tpm.PolicyOR(&session_handle(&sess3), &hash_list)?; + + let hmac_seq = tpm.with_session(sess3.clone()).HMAC_Start(&hmac_key, &vec![], TPM_ALG_ID::SHA256)?; + println!("Branch 2 HMAC_Start succeeded: {:?}", hmac_seq); + tpm.FlushContext(&hmac_seq)?; + tpm.FlushContext(&session_handle(&sess3))?; + + tpm.FlushContext(&hmac_key)?; + + println!("PolicyOR sample completed successfully"); + Ok(()) +} + +fn policy_with_passwords_sample(tpm: &mut Tpm2) -> Result<(), TpmError> { + announce("Policy With Passwords Sample"); + + // Reset dictionary attack lockout (may fail on some TPMs) + tpm.allow_errors(); + let _ = tpm.DictionaryAttackLockReset(&TPM_HANDLE::new(TPM_RH::LOCKOUT.get_value())); + if tpm.last_response_code() != TPM_RC::SUCCESS { + println!("Note: DictionaryAttackLockReset failed (rc={}), continuing...", tpm.last_response_code()); + } + + // --- PolicyPassword demo --- + println!(">> PolicyPassword"); + + // Compute policy digest for PolicyPassword + let trial = tpm.start_auth_session(TPM_SE::TRIAL, TPM_ALG_ID::SHA256)?; + tpm.PolicyPassword(&session_handle(&trial))?; + let policy_digest = tpm.PolicyGetDigest(&session_handle(&trial))?; + tpm.FlushContext(&session_handle(&trial))?; + println!("PolicyPassword digest: {:?}", policy_digest); + + let use_auth = Crypto::hash(TPM_ALG_ID::SHA256, &b"password".to_vec())?; + let mut hmac_handle = make_hmac_primary_with_policy(tpm, &policy_digest, &use_auth, TPM_ALG_ID::SHA256)?; + hmac_handle.set_auth(&use_auth); + + // Works with correct password + let mut sess = tpm.start_auth_session(TPM_SE::POLICY, TPM_ALG_ID::SHA256)?; + tpm.PolicyPassword(&session_handle(&sess))?; + sess.needs_password = true; + + let hmac_result = tpm.with_session(sess.clone()).HMAC(&hmac_handle, &vec![1, 2, 3, 4], TPM_ALG_ID::SHA256)?; + println!("HMAC with correct password: {:?}", hmac_result); + tpm.FlushContext(&session_handle(&sess))?; + + // Fails without password + hmac_handle.set_auth(&[]); + let mut sess2 = tpm.start_auth_session(TPM_SE::POLICY, TPM_ALG_ID::SHA256)?; + tpm.PolicyPassword(&session_handle(&sess2))?; + sess2.needs_password = true; + + tpm.allow_errors(); + let _ = tpm.with_session(sess2.clone()).HMAC(&hmac_handle, &vec![1, 2, 3, 4], TPM_ALG_ID::SHA256); + println!("HMAC without password: last_rc = {} (expected AUTH_FAIL)", tpm.last_response_code()); + tpm.FlushContext(&session_handle(&sess2))?; + tpm.FlushContext(&hmac_handle)?; + + // --- PolicyAuthValue demo --- + println!("\n>> PolicyAuthValue"); + + let trial2 = tpm.start_auth_session(TPM_SE::TRIAL, TPM_ALG_ID::SHA256)?; + tpm.PolicyAuthValue(&session_handle(&trial2))?; + let policy_digest2 = tpm.PolicyGetDigest(&session_handle(&trial2))?; + tpm.FlushContext(&session_handle(&trial2))?; + println!("PolicyAuthValue digest: {:?}", policy_digest2); + + let use_auth2 = Crypto::hash(TPM_ALG_ID::SHA256, &b"password2".to_vec())?; + let mut hmac_handle2 = make_hmac_primary_with_policy(tpm, &policy_digest2, &use_auth2, TPM_ALG_ID::SHA256)?; + hmac_handle2.set_auth(&use_auth2); + + // Works with correct auth value (HMAC-based proof of possession) + let mut sess3 = tpm.start_auth_session(TPM_SE::POLICY, TPM_ALG_ID::SHA256)?; + tpm.PolicyAuthValue(&session_handle(&sess3))?; + sess3.needs_hmac = true; + + let hmac_result2 = tpm.with_session(sess3.clone()).HMAC(&hmac_handle2, &vec![1, 2, 3, 4], TPM_ALG_ID::SHA256)?; + println!("HMAC with PolicyAuthValue: {:?}", hmac_result2); + tpm.FlushContext(&session_handle(&sess3))?; + + // Fails without auth value + hmac_handle2.set_auth(&[]); + let mut sess4 = tpm.start_auth_session(TPM_SE::POLICY, TPM_ALG_ID::SHA256)?; + tpm.PolicyAuthValue(&session_handle(&sess4))?; + sess4.needs_hmac = true; + + tpm.allow_errors(); + let _ = tpm.with_session(sess4.clone()).HMAC(&hmac_handle2, &vec![1, 2, 3, 4], TPM_ALG_ID::SHA256); + println!("HMAC without auth value: last_rc = {} (expected AUTH_FAIL)", tpm.last_response_code()); + tpm.FlushContext(&session_handle(&sess4))?; + tpm.FlushContext(&hmac_handle2)?; + + println!("Policy with passwords sample completed successfully"); + Ok(()) +} + +fn import_duplicate_sample(tpm: &mut Tpm2) -> Result<(), TpmError> { + announce("Import/Duplicate Sample"); + + // Create storage primary + let primary = make_storage_primary(tpm)?; + println!("Created storage primary: {:?}", primary); + + // Compute policy for Duplicate command + let trial = tpm.start_auth_session(TPM_SE::TRIAL, TPM_ALG_ID::SHA256)?; + tpm.PolicyCommandCode(&session_handle(&trial), TPM_CC::Duplicate)?; + let policy_digest = tpm.PolicyGetDigest(&session_handle(&trial))?; + tpm.FlushContext(&session_handle(&trial))?; + println!("Duplicate policy digest: {:?}", policy_digest); + + // Create a signing key that allows duplication (via policy) + let key_attrs = TPMA_OBJECT::sign | TPMA_OBJECT::userWithAuth + | TPMA_OBJECT::sensitiveDataOrigin; + let key_parms = TPMU_PUBLIC_PARMS::rsaDetail(TPMS_RSA_PARMS::new( + &Default::default(), + &Some(TPMU_ASYM_SCHEME::rsassa(TPMS_SIG_SCHEME_RSASSA { hashAlg: TPM_ALG_ID::SHA256 })), + 2048, 65537, + )); + let key_template = TPMT_PUBLIC::new( + TPM_ALG_ID::SHA256, key_attrs, &policy_digest, + &Some(key_parms), + &Some(TPMU_PUBLIC_ID::rsa(TPM2B_PUBLIC_KEY_RSA::default())), + ); + + let new_key = tpm.Create(&primary, &Default::default(), &key_template, + &Default::default(), &Default::default())?; + let sign_key = tpm.Load(&primary, &new_key.outPrivate, &new_key.outPublic)?; + println!("Created duplicatable signing key: {:?}", sign_key); + + // Duplicate using policy session + let sess = tpm.start_auth_session(TPM_SE::POLICY, TPM_ALG_ID::SHA256)?; + tpm.PolicyCommandCode(&session_handle(&sess), TPM_CC::Duplicate)?; + + let null_parent = TPM_HANDLE::new(TPM_RH::NULL.get_value()); + let no_sym = TPMT_SYM_DEF_OBJECT::default(); + println!("About to call Duplicate..."); + let dup_result = tpm.with_session(sess.clone()).Duplicate( + &sign_key, &null_parent, &vec![], &no_sym)?; + println!("Duplicated key successfully"); + tpm.FlushContext(&session_handle(&sess))?; + tpm.FlushContext(&sign_key)?; + + // Import the key back to the same parent (with no outer wrapper) + let imported = tpm.Import(&primary, &vec![], &new_key.outPublic, + &dup_result.duplicate, &vec![], &no_sym)?; + println!("Imported key back"); + + // Load the imported key and sign with it + let imported_key = tpm.Load(&primary, &imported, &new_key.outPublic)?; + let data_to_sign = Crypto::hash(TPM_ALG_ID::SHA256, &b"test import".to_vec())?; + let sig = tpm.Sign(&imported_key, &data_to_sign, + &TPMU_SIG_SCHEME::create(TPM_ALG_ID::NULL)?, + &TPMT_TK_HASHCHECK::default())?; + println!("Signed with imported key: {:?}", sig.is_some()); + + tpm.FlushContext(&imported_key)?; + tpm.FlushContext(&primary)?; + + println!("Import/Duplicate sample completed successfully"); + Ok(()) +} + +fn policy_counter_timer_sample(tpm: &mut Tpm2) -> Result<(), TpmError> { + announce("PolicyCounterTimer Sample"); + + // PolicyCounterTimer allows actions to be gated on the TPM's clocks and timers. + // Here we demonstrate giving a user owner-privileges for ~5 seconds. + + let start_clock = tpm.ReadClock()?; + let now_time = start_clock.time; + let end_time = now_time + 5 * 1000; // 5 seconds from now + + // Construct the operand: UINT64 big-endian representation of end_time + let operand = end_time.to_be_bytes().to_vec(); + + // Compute the policy digest using trial session + // PolicyCounterTimer(endTime, offset=0, UNSIGNED_LT) means: + // "Allow if TPMS_TIME_INFO.time < endTime" + let trial = tpm.start_auth_session(TPM_SE::TRIAL, TPM_ALG_ID::SHA256)?; + tpm.PolicyCounterTimer(&session_handle(&trial), &operand, 0, TPM_EO::UNSIGNED_LT)?; + let policy_digest = tpm.PolicyGetDigest(&session_handle(&trial))?; + tpm.FlushContext(&session_handle(&trial))?; + println!("PolicyCounterTimer digest: {:?}", policy_digest); + + // Set the owner policy to this value + tpm.SetPrimaryPolicy(&TPM_HANDLE::new(TPM_RH::OWNER.get_value()), + &policy_digest, TPM_ALG_ID::SHA256)?; + + // Now try using the policy a few times - should succeed until time expires + println!("Operations should start failing in about 5 seconds..."); + + for i in 0..4 { + let sess = tpm.start_auth_session(TPM_SE::POLICY, TPM_ALG_ID::SHA256)?; + tpm.allow_errors(); + let _ = tpm.PolicyCounterTimer(&session_handle(&sess), &operand, 0, TPM_EO::UNSIGNED_LT); + let timer_ok = tpm.last_response_code() == TPM_RC::SUCCESS; + + if timer_ok { + tpm.allow_errors(); + let _ = tpm.with_session(sess.clone()).SetPrimaryPolicy( + &TPM_HANDLE::new(TPM_RH::OWNER.get_value()), + &policy_digest, TPM_ALG_ID::SHA256); + if tpm.last_response_code() == TPM_RC::SUCCESS { + println!("Iteration {}: Succeeded", i); + } else { + println!("Iteration {}: Policy valid but command failed (rc={})", i, tpm.last_response_code()); + } + } else { + println!("Iteration {}: Policy expired (rc={})", i, tpm.last_response_code()); + } + tpm.FlushContext(&session_handle(&sess))?; + std::thread::sleep(std::time::Duration::from_millis(1500)); + } + + // Put things back the way they were + tpm.SetPrimaryPolicy(&TPM_HANDLE::new(TPM_RH::OWNER.get_value()), + &vec![], TPM_ALG_ID::NULL)?; + + println!("PolicyCounterTimer sample completed successfully"); + Ok(()) +} + +fn policy_secret_sample(tpm: &mut Tpm2) -> Result<(), TpmError> { + announce("PolicySecret Sample"); + + // PolicySecret demands proof-of-knowledge of the admin auth value. + // The TPM verifies the auth by using a policy session that references + // the OWNER hierarchy handle. + + // Use trial session to compute policy digest for PolicySecret(OWNER) + let owner_handle = TPM_HANDLE::new(TPM_RH::OWNER.get_value()); + + let trial = tpm.start_auth_session(TPM_SE::TRIAL, TPM_ALG_ID::SHA256)?; + tpm.PolicySecret(&owner_handle, &session_handle(&trial), + &vec![], &vec![], &vec![], 0)?; + let policy_digest = tpm.PolicyGetDigest(&session_handle(&trial))?; + tpm.FlushContext(&session_handle(&trial))?; + println!("PolicySecret digest: {:?}", policy_digest); + + // Make an object with this policy + let hmac_key = make_hmac_primary_with_policy(tpm, &policy_digest, &[], TPM_ALG_ID::SHA256)?; + + // Now run the policy: this will use PWAP to prove knowledge of the admin password + let sess = tpm.start_auth_session(TPM_SE::POLICY, TPM_ALG_ID::SHA256)?; + tpm.PolicySecret(&owner_handle, &session_handle(&sess), + &vec![], &vec![], &vec![], 0)?; + + // Use the session to authorize HMAC_Start + let hmac_seq = tpm.with_session(sess.clone()).HMAC_Start(&hmac_key, &vec![], TPM_ALG_ID::SHA256)?; + println!("PolicySecret-authorized HMAC_Start succeeded: {:?}", hmac_seq); + + tpm.FlushContext(&hmac_seq)?; + tpm.FlushContext(&session_handle(&sess))?; + tpm.FlushContext(&hmac_key)?; + + println!("PolicySecret sample completed successfully"); + Ok(()) +} + +fn policy_nv_sample(tpm: &mut Tpm2) -> Result<(), TpmError> { + announce("PolicyNV Sample"); + + // PolicyNV allows actions to be gated on the contents of an NV-storage slot + + let nv_auth: Vec = vec![1, 5, 1, 1]; + let nv_index: u32 = 0x01500030; // Use a different index to avoid conflicts + let mut nv_handle = TPM_HANDLE::new(nv_index); + + // Try to delete the slot if it exists (ignore failure) + { + tpm.allow_errors(); + let _ = tpm.NV_UndefineSpace(&TPM_HANDLE::new(TPM_RH::OWNER.get_value()), &nv_handle); + } + + // Make a new simple NV slot, 16 bytes, RW with auth + let nv_template = TPMS_NV_PUBLIC::new( + &TPM_HANDLE::new(nv_index), + TPM_ALG_ID::SHA256, + TPMA_NV::AUTHREAD | TPMA_NV::AUTHWRITE, + &vec![], + 16, + ); + + tpm.NV_DefineSpace(&TPM_HANDLE::new(TPM_RH::OWNER.get_value()), &nv_auth, &nv_template)?; + nv_handle.set_auth(&nv_auth); + println!("Defined NV slot at 0x{:08x}", nv_index); + + // Write some data + let to_write: Vec = vec![1, 2, 3, 4, 5, 4, 3, 2, 1]; + tpm.NV_Write(&nv_handle, &nv_handle, &to_write, 0)?; + println!("NV_Write succeeded"); + + // Read back the NV public info to get the name + let nv_info = tpm.NV_ReadPublic(&nv_handle)?; + nv_handle.name = nv_info.nvName.clone(); + println!("NV_ReadPublic succeeded, name len={}", nv_info.nvName.len()); + + // Compute PolicyNV digest using trial session + // Use the NV handle as auth handle (with proper auth) + println!("Starting PolicyNV trial session..."); + let trial = tpm.start_auth_session(TPM_SE::TRIAL, TPM_ALG_ID::SHA256)?; + println!("Trial session started, calling PolicyNV..."); + tpm.PolicyNV(&nv_handle, &nv_handle, &session_handle(&trial), + &to_write, 0, TPM_EO::EQ)?; + println!("PolicyNV succeeded in trial session"); + let policy_digest = tpm.PolicyGetDigest(&session_handle(&trial))?; + tpm.FlushContext(&session_handle(&trial))?; + println!("PolicyNV digest: {:?}", policy_digest); + + // Create HMAC key with PolicyNV policy + let hmac_key = make_hmac_primary_with_policy(tpm, &policy_digest, &[], TPM_ALG_ID::SHA256)?; + + // Use the policy - should succeed when NV matches + let sess = tpm.start_auth_session(TPM_SE::POLICY, TPM_ALG_ID::SHA256)?; + tpm.PolicyNV(&nv_handle, &nv_handle, &session_handle(&sess), + &to_write, 0, TPM_EO::EQ)?; + + let hmac_result = tpm.with_session(sess.clone()).HMAC(&hmac_key, &vec![1, 2, 3], TPM_ALG_ID::SHA256)?; + println!("HMAC with correct NV: {:?}", hmac_result); + tpm.FlushContext(&session_handle(&sess))?; + + // Change NV data and verify policy fails + tpm.NV_Write(&nv_handle, &nv_handle, &vec![3, 1], 0)?; + + let sess2 = tpm.start_auth_session(TPM_SE::POLICY, TPM_ALG_ID::SHA256)?; + tpm.allow_errors(); + let _ = tpm.PolicyNV(&nv_handle, &nv_handle, &session_handle(&sess2), + &to_write, 0, TPM_EO::EQ); + println!("PolicyNV with changed data: last_rc = {} (expected POLICY_FAIL)", tpm.last_response_code()); + tpm.FlushContext(&session_handle(&sess2))?; + + // Cleanup + tpm.FlushContext(&hmac_key)?; + tpm.NV_UndefineSpace(&TPM_HANDLE::new(TPM_RH::OWNER.get_value()), &nv_handle)?; + + println!("PolicyNV sample completed successfully"); + Ok(()) +} + +fn software_keys_sample(tpm: &mut Tpm2) -> Result<(), TpmError> { + announce("Software Keys Sample"); + + // This sample demonstrates creating a duplicatable key in the TPM, + // exporting it via Duplicate, re-importing it, and signing with both. + + let primary = make_storage_primary(tpm)?; + + // Compute policy for Duplicate command + let trial = tpm.start_auth_session(TPM_SE::TRIAL, TPM_ALG_ID::SHA256)?; + tpm.PolicyCommandCode(&session_handle(&trial), TPM_CC::Duplicate)?; + let dup_policy = tpm.PolicyGetDigest(&session_handle(&trial))?; + tpm.FlushContext(&session_handle(&trial))?; + + // Create a duplicatable signing key + let key_attrs = TPMA_OBJECT::sign | TPMA_OBJECT::userWithAuth + | TPMA_OBJECT::sensitiveDataOrigin; + let key_parms = TPMU_PUBLIC_PARMS::rsaDetail(TPMS_RSA_PARMS::new( + &Default::default(), + &Some(TPMU_ASYM_SCHEME::rsassa(TPMS_SIG_SCHEME_RSASSA { hashAlg: TPM_ALG_ID::SHA256 })), + 2048, 65537, + )); + let key_template = TPMT_PUBLIC::new( + TPM_ALG_ID::SHA256, key_attrs, &dup_policy, + &Some(key_parms), + &Some(TPMU_PUBLIC_ID::rsa(TPM2B_PUBLIC_KEY_RSA::default())), + ); + + let key_data = tpm.Create(&primary, &Default::default(), &key_template, + &Default::default(), &Default::default())?; + let tpm_key = tpm.Load(&primary, &key_data.outPrivate, &key_data.outPublic)?; + println!("Created duplicatable signing key in TPM"); + + // Sign with the TPM key + let to_sign = Crypto::hash(TPM_ALG_ID::SHA256, &b"hello from software key".to_vec())?; + let tpm_sig = tpm.Sign(&tpm_key, &to_sign, + &TPMU_SIG_SCHEME::create(TPM_ALG_ID::NULL)?, + &TPMT_TK_HASHCHECK::default())?; + println!("Signed with TPM-created key: {:?}", tpm_sig.is_some()); + + // Verify with VerifySignature + let verify_result = tpm.VerifySignature(&tpm_key, &to_sign, &tpm_sig)?; + println!("TPM verified its own signature: hierarchy={:?}", verify_result.hierarchy); + + // Duplicate the key out (unwrapped, no encryption) + let dup_sess = tpm.start_auth_session(TPM_SE::POLICY, TPM_ALG_ID::SHA256)?; + tpm.PolicyCommandCode(&session_handle(&dup_sess), TPM_CC::Duplicate)?; + + let null_parent = TPM_HANDLE::new(TPM_RH::NULL.get_value()); + let dup = tpm.with_session(dup_sess.clone()).Duplicate( + &tpm_key, &null_parent, &vec![], &TPMT_SYM_DEF_OBJECT::default())?; + println!("Exported key via Duplicate"); + + tpm.FlushContext(&session_handle(&dup_sess))?; + tpm.FlushContext(&tpm_key)?; + + // Re-import the duplicated key + let re_imported = tpm.Import(&primary, &vec![], &key_data.outPublic, + &dup.duplicate, &vec![], &TPMT_SYM_DEF_OBJECT::default())?; + let re_key = tpm.Load(&primary, &re_imported, &key_data.outPublic)?; + println!("Re-imported duplicated key"); + + // Sign with the re-imported key + let re_sig = tpm.Sign(&re_key, &to_sign, + &TPMU_SIG_SCHEME::create(TPM_ALG_ID::NULL)?, + &TPMT_TK_HASHCHECK::default())?; + println!("Signed with re-imported key: {:?}", re_sig.is_some()); + + // Verify the re-imported key signature with the original public key + let verify2 = tpm.VerifySignature(&re_key, &to_sign, &re_sig)?; + println!("Verified re-imported key signature: hierarchy={:?}", verify2.hierarchy); + + tpm.FlushContext(&re_key)?; + tpm.FlushContext(&primary)?; + + println!("Software keys sample completed successfully"); + Ok(()) +} + +fn policy_pcr_sample(tpm: &mut Tpm2) -> Result<(), TpmError> { + announce("Policy PCR Sample"); + + let bank = TPM_ALG_ID::SHA256; + let pcr: u32 = 15; + + // Set PCR to a known value + tpm.PCR_Event(&TPM_HANDLE::pcr(pcr), &vec![1, 2, 3, 4])?; + + let pcr_selection = TPMS_PCR_SELECTION::get_selection_array(bank, pcr); + let pcr_vals = tpm.PCR_Read(&pcr_selection)?; + + // Compute the PCR digest + let mut pcr_digest_data = Vec::new(); + for v in &pcr_vals.pcrValues { + pcr_digest_data.extend_from_slice(&v.buffer); + } + let pcr_digest = Crypto::hash(bank, &pcr_digest_data)?; + + // Compute policy digest using trial session + let trial = tpm.start_auth_session(TPM_SE::TRIAL, TPM_ALG_ID::SHA256)?; + tpm.PolicyPCR(&session_handle(&trial), &pcr_digest, &pcr_selection)?; + let policy_digest = tpm.PolicyGetDigest(&session_handle(&trial))?; + tpm.FlushContext(&session_handle(&trial))?; + println!("PolicyPCR digest: {:?}", policy_digest); + + // Create HMAC key with PCR policy + let hmac_key = make_hmac_primary_with_policy(tpm, &policy_digest, &[], TPM_ALG_ID::SHA256)?; + + // Succeeds when PCR matches + let sess = tpm.start_auth_session(TPM_SE::POLICY, TPM_ALG_ID::SHA256)?; + tpm.PolicyPCR(&session_handle(&sess), &pcr_digest, &pcr_selection)?; + let hmac_result = tpm.with_session(sess.clone()).HMAC(&hmac_key, &vec![1, 2, 3, 4], TPM_ALG_ID::SHA256)?; + println!("HMAC with correct PCR: {:?}", hmac_result); + tpm.FlushContext(&session_handle(&sess))?; + + // Change PCR - should fail + tpm.PCR_Event(&TPM_HANDLE::pcr(pcr), &vec![5, 6, 7, 8])?; + let sess2 = tpm.start_auth_session(TPM_SE::POLICY, TPM_ALG_ID::SHA256)?; + tpm.allow_errors(); + let _ = tpm.PolicyPCR(&session_handle(&sess2), &pcr_digest, &pcr_selection); + println!("PolicyPCR with wrong value: last_rc = {} (expected VALUE)", tpm.last_response_code()); + tpm.FlushContext(&session_handle(&sess2))?; + + tpm.FlushContext(&hmac_key)?; + + println!("Policy PCR sample completed successfully"); + Ok(()) +} + +fn policy_cphash_sample(tpm: &mut Tpm2) -> Result<(), TpmError> { + announce("PolicyCpHash Sample"); + + // PolicyCpHash restricts the actions that can be performed with a secured object + // to a specific operation identified by the hash of the command parameters. + // + // Approach: compute the policy digest using a trial session, then create a key + // with that policy. The tricky part is that cpHash depends on the key's name, + // which isn't known until the key is created. So we use a two-step approach: + // 1. Create a key with just PolicyCommandCode + // 2. Show that PolicyCpHash works in trial sessions + + let hash_alg = TPM_ALG_ID::SHA256; + + // Compute trial PolicyCpHash to demonstrate how it works + // cpHash = H(cc || handle_names || parameters) + // We'll use a dummy hash value for the trial + let dummy_cphash = Crypto::hash(hash_alg, b"example cpHash input")?; + + let trial = tpm.start_auth_session(TPM_SE::TRIAL, hash_alg)?; + tpm.PolicyCpHash(&session_handle(&trial), &dummy_cphash)?; + let cphash_digest = tpm.PolicyGetDigest(&session_handle(&trial))?; + tpm.FlushContext(&session_handle(&trial))?; + println!("PolicyCpHash trial digest: {:?}", &cphash_digest[..8]); + + // Also combine with PolicyCommandCode + let trial2 = tpm.start_auth_session(TPM_SE::TRIAL, hash_alg)?; + tpm.PolicyCpHash(&session_handle(&trial2), &dummy_cphash)?; + tpm.PolicyCommandCode(&session_handle(&trial2), TPM_CC::HMAC_Start)?; + let combined_digest = tpm.PolicyGetDigest(&session_handle(&trial2))?; + tpm.FlushContext(&session_handle(&trial2))?; + println!("PolicyCpHash + PolicyCommandCode trial digest: {:?}", &combined_digest[..8]); + println!("(Demonstrates policy digest computation - cpHash restricts to specific parameters)"); + + println!("PolicyCpHash sample completed successfully"); + Ok(()) +} + +fn policy_name_hash_sample(tpm: &mut Tpm2) -> Result<(), TpmError> { + announce("PolicyNameHash Sample"); + + // PolicyNameHash restricts a policy to only authorize operations when specific + // handles are used. We demonstrate computing the policy digest. + // + // Note: PolicyNameHash is typically used to restrict which handles can be used + // with admin operations. Since modifying hierarchy auth on a real TPM is risky + // (DA lockout can prevent recovery), we demonstrate the policy computation + // using trial sessions. + + let hash_alg = TPM_ALG_ID::SHA256; + + // Compute nameHash for the OWNER handle + let owner_name = TPM_HANDLE::new(TPM_RH::OWNER.get_value()).get_name()?; + let name_hash = Crypto::hash(hash_alg, &owner_name)?; + println!("nameHash(OWNER): {:?}", &name_hash[..8]); + + // Build policy digest using trial session + let trial = tpm.start_auth_session(TPM_SE::TRIAL, hash_alg)?; + tpm.PolicyNameHash(&session_handle(&trial), &name_hash)?; + let policy_digest = tpm.PolicyGetDigest(&session_handle(&trial))?; + tpm.FlushContext(&session_handle(&trial))?; + println!("PolicyNameHash trial digest: {:?}", &policy_digest[..8]); + + // Combine with PolicyCommandCode for a more realistic policy + let trial2 = tpm.start_auth_session(TPM_SE::TRIAL, hash_alg)?; + tpm.PolicyNameHash(&session_handle(&trial2), &name_hash)?; + tpm.PolicyCommandCode(&session_handle(&trial2), TPM_CC::HierarchyChangeAuth)?; + let combined_digest = tpm.PolicyGetDigest(&session_handle(&trial2))?; + tpm.FlushContext(&session_handle(&trial2))?; + println!("PolicyNameHash + PolicyCommandCode trial digest: {:?}", &combined_digest[..8]); + println!("(Demonstrates policy that restricts HierarchyChangeAuth to OWNER handle only)"); + + println!("PolicyNameHash sample completed successfully"); + Ok(()) +} + +fn rewrap_sample(tpm: &mut Tpm2) -> Result<(), TpmError> { + announce("ReWrap Sample"); + + // Make an exportable key with Duplicate policy, duplicate it with no encryption, + // then rewrap it to a new parent. + + let hash_alg = TPM_ALG_ID::SHA256; + + // Compute policy for Duplicate command + let trial = tpm.start_auth_session(TPM_SE::TRIAL, hash_alg)?; + tpm.PolicyCommandCode(&session_handle(&trial), TPM_CC::Duplicate)?; + let dup_policy = tpm.PolicyGetDigest(&session_handle(&trial))?; + tpm.FlushContext(&session_handle(&trial))?; + + // Create a duplicatable storage primary + let dup_attrs = TPMA_OBJECT::decrypt | TPMA_OBJECT::restricted + | TPMA_OBJECT::sensitiveDataOrigin | TPMA_OBJECT::userWithAuth; + let dup_parms = TPMU_PUBLIC_PARMS::rsaDetail(TPMS_RSA_PARMS::new( + &Aes128Cfb, + &Some(TPMU_ASYM_SCHEME::null(TPMS_NULL_ASYM_SCHEME::default())), + 2048, 65537, + )); + let dup_template = TPMT_PUBLIC::new( + hash_alg, dup_attrs, &dup_policy, + &Some(dup_parms), + &Some(TPMU_PUBLIC_ID::rsa(TPM2B_PUBLIC_KEY_RSA::default())), + ); + + let dup_key_resp = tpm.CreatePrimary( + &TPM_HANDLE::new(TPM_RH::OWNER.get_value()), + &TPMS_SENSITIVE_CREATE::default(), + &dup_template, + &Default::default(), + &Default::default(), + )?; + let dup_key = dup_key_resp.handle; + + // Make a new storage parent + let new_parent = make_storage_primary(tpm)?; + + // Duplicate the key to NULL parent (plaintext export, no encryption) + let sess = tpm.start_auth_session(TPM_SE::POLICY, hash_alg)?; + tpm.PolicyCommandCode(&session_handle(&sess), TPM_CC::Duplicate)?; + let dup_resp = tpm.with_session(sess.clone()).Duplicate( + &dup_key, &TPM_HANDLE::new(TPM_RH::NULL.get_value()), + &vec![], &Default::default(), + )?; + println!("Duplicated key (plaintext), duplicate size: {}", dup_resp.duplicate.buffer.len()); + tpm.FlushContext(&session_handle(&sess))?; + + // Rewrap from NULL parent to new parent + let rewrap_resp = tpm.Rewrap( + &TPM_HANDLE::new(TPM_RH::NULL.get_value()), + &new_parent, + &dup_resp.duplicate, + &dup_key.get_name()?, + &vec![], // No sym seed since duplicated to NULL + )?; + println!("Rewrapped key to new parent, outDuplicate size: {}", rewrap_resp.outDuplicate.buffer.len()); + + tpm.FlushContext(&dup_key)?; + tpm.FlushContext(&new_parent)?; + + println!("ReWrap sample completed successfully"); + Ok(()) +} + +fn audit_sample(tpm: &mut Tpm2) -> Result<(), TpmError> { + announce("Audit Sample"); + + // The TPM supports command audit - keeping a running hash of commands/responses + // for commands in a specified list. + + let audit_alg = TPM_ALG_ID::SHA256; + let owner_handle = TPM_HANDLE::new(TPM_RH::OWNER.get_value()); + let empty_cc: Vec = vec![]; + + // Reset audit status + tpm.SetCommandCodeAuditStatus(&owner_handle, TPM_ALG_ID::NULL, &empty_cc, &empty_cc)?; + + // Start auditing GetRandom and StirRandom + let to_audit = vec![TPM_CC::GetRandom, TPM_CC::StirRandom]; + tpm.SetCommandCodeAuditStatus(&owner_handle, audit_alg, &empty_cc, &empty_cc)?; + tpm.SetCommandCodeAuditStatus(&owner_handle, TPM_ALG_ID::NULL, &to_audit, &empty_cc)?; + println!("Set up command audit for GetRandom and StirRandom"); + + // Read the audit digest before our commands + let audit_before = tpm.GetCommandAuditDigest( + &TPM_HANDLE::new(TPM_RH::ENDORSEMENT.get_value()), + &TPM_HANDLE::new(TPM_RH::NULL.get_value()), + &vec![], + &Some(TPMU_SIG_SCHEME::null(TPMS_NULL_SIG_SCHEME::default())), + )?; + println!("Audit digest before commands: {:?}", &audit_before.auditInfo.attested); + + // Execute some audited commands + let _ = tpm.GetRandom(20)?; + tpm.StirRandom(&vec![1, 2, 3, 4])?; + let _ = tpm.GetRandom(10)?; + tpm.StirRandom(&vec![9, 8, 7, 6])?; + println!("Executed 4 audited commands"); + + // Stop auditing + tpm.SetCommandCodeAuditStatus(&owner_handle, TPM_ALG_ID::NULL, &empty_cc, &empty_cc)?; + + // Read the audit digest after commands + let audit_after = tpm.GetCommandAuditDigest( + &TPM_HANDLE::new(TPM_RH::ENDORSEMENT.get_value()), + &TPM_HANDLE::new(TPM_RH::NULL.get_value()), + &vec![], + &Some(TPMU_SIG_SCHEME::null(TPMS_NULL_SIG_SCHEME::default())), + )?; + println!("Audit digest after commands: {:?}", &audit_after.auditInfo.attested); + + // Now demonstrate session audit + println!("\n>> Session Audit"); + + // Create a signing key for the session audit quote + let primary = make_storage_primary(tpm)?; + let sig_key = make_child_signing_key(tpm, &primary, true)?; + tpm.FlushContext(&primary)?; + + // Start an HMAC session with audit attribute + let audit_attrs = TPMA_SESSION::audit | TPMA_SESSION::continueSession; + let sess = tpm.start_auth_session_full( + TPM_SE::HMAC, audit_alg, + audit_attrs, + TPMT_SYM_DEF::default(), + )?; + + // Execute some commands in the audit session + tpm.with_session(sess.clone()).GetRandom(20)?; + let sess = tpm.last_session().unwrap(); + tpm.with_session(sess.clone()).StirRandom(&vec![1, 2, 3, 4])?; + let sess = tpm.last_session().unwrap(); + + // Get the session audit digest + let session_quote = tpm.GetSessionAuditDigest( + &TPM_HANDLE::new(TPM_RH::ENDORSEMENT.get_value()), + &sig_key, + &session_handle(&sess), + &vec![], + &Some(TPMU_SIG_SCHEME::null(TPMS_NULL_SIG_SCHEME::default())), + )?; + println!("Session audit quote obtained"); + println!("Session audit attested: {:?}", &session_quote.auditInfo.attested); + + tpm.FlushContext(&session_handle(&sess))?; + tpm.FlushContext(&sig_key)?; + + println!("Audit sample completed successfully"); + Ok(()) +} + +fn policy_locality_sample(tpm: &mut Tpm2) -> Result<(), TpmError> { + announce("PolicyLocality Sample (trial only)"); + + // PolicyLocality restricts key usage to specific TPM localities. + // On real hardware (TBS), we can't change locality, so we only + // demonstrate computing the policy digest. + + let hash_alg = TPM_ALG_ID::SHA256; + + // Build policy digest using trial session + let trial = tpm.start_auth_session(TPM_SE::TRIAL, hash_alg)?; + tpm.PolicyLocality(&session_handle(&trial), TPMA_LOCALITY::LOC_ONE)?; + let policy_digest = tpm.PolicyGetDigest(&session_handle(&trial))?; + tpm.FlushContext(&session_handle(&trial))?; + + println!("PolicyLocality(LOC_ONE) digest: {:?}", &policy_digest[..8]); + + // Create a key with this policy + let hmac_key = make_hmac_primary_with_policy(tpm, &policy_digest, &[], hash_alg)?; + println!("Created HMAC key with locality policy"); + + // Try to use with a policy session - will fail since we can't set locality on TBS + let sess = tpm.start_auth_session(TPM_SE::POLICY, hash_alg)?; + tpm.allow_errors(); + let _ = tpm.PolicyLocality(&session_handle(&sess), TPMA_LOCALITY::LOC_ONE); + println!("PolicyLocality in real session: last_rc = {} (expected LOCALITY on TBS)", tpm.last_response_code()); + tpm.FlushContext(&session_handle(&sess))?; + + tpm.FlushContext(&hmac_key)?; + + println!("PolicyLocality sample completed (trial only on TBS)"); + Ok(()) +} + +fn async_sample(tpm: &mut Tpm2) -> Result<(), TpmError> { + announce("Async Sample"); + + // The TPM supports asynchronous command dispatch: you send the command, + // then poll for completion, and finally retrieve the result. + // On Windows TBS, commands complete synchronously, but the API pattern + // is still useful for non-blocking designs and other transport layers. + + // Fast async operation: GetRandom + println!(">> Async GetRandom"); + { + let mut async_tpm = tpm.async_methods(); + async_tpm.GetRandom_async(16)?; + } + // On TBS, response is immediately available + { + let mut async_tpm = tpm.async_methods(); + let rand_data = async_tpm.GetRandom_complete()?; + println!("Async random data ({} bytes): {:?}", rand_data.len(), &rand_data[..8]); + } + + // Slow async operation: CreatePrimary + println!(">> Async CreatePrimary"); + let object_attributes = TPMA_OBJECT::sign | TPMA_OBJECT::fixedParent + | TPMA_OBJECT::fixedTPM | TPMA_OBJECT::sensitiveDataOrigin + | TPMA_OBJECT::userWithAuth; + let parameters = TPMU_PUBLIC_PARMS::rsaDetail(TPMS_RSA_PARMS::new( + &Default::default(), + &Some(TPMU_ASYM_SCHEME::rsassa(TPMS_SIG_SCHEME_RSASSA { hashAlg: TPM_ALG_ID::SHA256 })), + 2048, 65537, + )); + let template = TPMT_PUBLIC::new( + TPM_ALG_ID::SHA1, object_attributes, &Default::default(), + &Some(parameters), + &Some(TPMU_PUBLIC_ID::rsa(TPM2B_PUBLIC_KEY_RSA::default())), + ); + + { + let mut async_tpm = tpm.async_methods(); + async_tpm.CreatePrimary_async( + &TPM_HANDLE::new(TPM_RH::OWNER.get_value()), + &TPMS_SENSITIVE_CREATE::default(), + &template, + &Default::default(), + &Default::default(), + )?; + } + + let new_primary = { + let mut async_tpm = tpm.async_methods(); + async_tpm.CreatePrimary_complete()? + }; + + println!("Asynchronously created primary key: handle={:?}", new_primary.handle); + tpm.FlushContext(&new_primary.handle)?; + + println!("Async sample completed successfully"); + Ok(()) +} + +fn session_encryption_sample(tpm: &mut Tpm2) -> Result<(), TpmError> { + announce("SessionEncryption Sample"); + + // Session encryption is transparent to the application programmer. + // Create a session with decrypt/encrypt attributes and the library handles + // the AES-CFB encryption/decryption of the first parameter automatically. + + // Part 1: Encrypt commands TO the TPM (decrypt attribute) + println!(">> Encrypt commands to TPM (TPMA_SESSION::decrypt)"); + let sess = tpm.start_auth_session_full( + TPM_SE::HMAC, TPM_ALG_ID::SHA256, + TPMA_SESSION::continueSession | TPMA_SESSION::decrypt, + TPMT_SYM_DEF::new(TPM_ALG_ID::AES, 128, TPM_ALG_ID::CFB), + )?; + + // StirRandom: the stirValue buffer will be encrypted before sending to TPM + tpm.with_session(sess.clone()).StirRandom(&vec![1, 1, 1, 1, 1, 1, 1, 1])?; + let sess = tpm.last_session().unwrap(); + println!("StirRandom with encrypted parameter succeeded"); + + // Do it again to verify continueSession nonce rolling works + tpm.with_session(sess.clone()).StirRandom(&vec![2, 2, 2, 2])?; + let sess = tpm.last_session().unwrap(); + println!("Second StirRandom with encrypted parameter succeeded"); + + tpm.FlushContext(&session_handle(&sess))?; + + // Part 2: Encrypt responses FROM the TPM (encrypt attribute) + println!("\n>> Encrypt responses from TPM (TPMA_SESSION::encrypt)"); + + // Create a primary key so we have something to read + let storage_primary = make_storage_primary(tpm)?; + + // Read public key without encryption + let plaintext_read = tpm.ReadPublic(&storage_primary)?; + + // Make an encrypting session for response + let enc_sess = tpm.start_auth_session_full( + TPM_SE::HMAC, TPM_ALG_ID::SHA256, + TPMA_SESSION::continueSession | TPMA_SESSION::encrypt, + TPMT_SYM_DEF::new(TPM_ALG_ID::AES, 128, TPM_ALG_ID::CFB), + )?; + + // ReadPublic with encrypted response - the library should decrypt automatically + let encrypted_read = tpm.with_session(enc_sess.clone()).ReadPublic(&storage_primary)?; + let enc_sess = tpm.last_session().unwrap(); + + // Compare: the decrypted response should match the plaintext + if plaintext_read.outPublic.nameAlg == encrypted_read.outPublic.nameAlg + && plaintext_read.name == encrypted_read.name + { + println!("Return parameter encryption succeeded: plaintext and decrypted responses match"); + } else { + println!("Warning: Responses differ (may indicate encryption/decryption issue)"); + } + + tpm.FlushContext(&session_handle(&enc_sess))?; + tpm.FlushContext(&storage_primary)?; + + println!("SessionEncryption sample completed successfully"); + Ok(()) +} + +fn policy_signed_sample(tpm: &mut Tpm2) -> Result<(), TpmError> { + announce("PolicySigned"); + + // PolicySigned allows a policy to be satisfied by a signature from a specific key. + // We create a software RSA key, load its public part into the TPM, and then + // sign the nonce to satisfy the policy. + + let hash_alg = TPM_ALG_ID::SHA256; + + // Create a SW signing key + let mut sw_key = TSS_KEY::default(); + sw_key.publicPart = TPMT_PUBLIC { + nameAlg: hash_alg, + objectAttributes: TPMA_OBJECT( + TPMA_OBJECT::sign.get_value() | TPMA_OBJECT::userWithAuth.get_value(), + ), + authPolicy: vec![], + parameters: Some(TPMU_PUBLIC_PARMS::rsaDetail(TPMS_RSA_PARMS { + symmetric: TPMT_SYM_DEF_OBJECT::default(), + scheme: Some(TPMU_ASYM_SCHEME::rsassa(TPMS_SIG_SCHEME_RSASSA { + hashAlg: hash_alg, + })), + keyBits: 2048, + exponent: 0, + })), + unique: Some(TPMU_PUBLIC_ID::rsa(TPM2B_PUBLIC_KEY_RSA::default())), + }; + sw_key.create_key()?; + println!("Created software RSA-2048 signing key"); + + // Load the public part into the TPM (OWNER hierarchy for valid tickets) + let auth_key_handle = tpm.LoadExternal( + &TPMT_SENSITIVE::default(), + &sw_key.publicPart, + &TPM_HANDLE::new(TPM_RH::OWNER.get_value()), + )?; + println!("Loaded SW key public part into TPM: {:?}", auth_key_handle); + + // Step 1: Compute trial policy digest for PolicySigned + // Note: TPM checks signature scheme matches the key even in trial mode, + // so we must provide a properly-schemed signature (content doesn't matter). + let trial = tpm.start_auth_session(TPM_SE::TRIAL, hash_alg)?; + let policy_ref: Vec = vec![]; + + let dummy_hash = Crypto::hash(hash_alg, &[])?; + let dummy_sig = sw_key.sign(&dummy_hash, hash_alg)?; + tpm.PolicySigned( + &auth_key_handle, + &session_handle(&trial), + &vec![], // nonceTPM (ignored in trial) + &vec![], // cpHashA + &policy_ref, + 0, // expiration + &dummy_sig.signature, + )?; + let policy_digest = tpm.PolicyGetDigest(&session_handle(&trial))?; + tpm.FlushContext(&session_handle(&trial))?; + println!("PolicySigned trial digest: {:?}", &policy_digest[..8]); + + // Step 2: Start a real policy session + let policy_sess = tpm.start_auth_session(TPM_SE::POLICY, hash_alg)?; + let nonce_tpm = policy_sess.sess_out.nonce.clone(); + + // Step 3: Compute aHash = Hash(nonceTPM || expiration || cpHashA || policyRef) + let mut to_hash = Vec::new(); + to_hash.extend_from_slice(&nonce_tpm); + to_hash.extend_from_slice(&0i32.to_be_bytes()); // expiration = 0 + // cpHashA is empty, policyRef is empty + let a_hash = Crypto::hash(hash_alg, &to_hash)?; + + // Step 4: Sign the aHash with our SW key + let signature = sw_key.sign(&a_hash, hash_alg)?; + println!("Signed aHash ({} bytes) with SW key", a_hash.len()); + + // Step 5: Execute PolicySigned with the real signature + tpm.PolicySigned( + &auth_key_handle, + &session_handle(&policy_sess), + &nonce_tpm, + &vec![], // cpHashA + &policy_ref, + 0, // expiration + &signature.signature, + )?; + + // Verify the policy digest matches the trial + let actual_digest = tpm.PolicyGetDigest(&session_handle(&policy_sess))?; + if actual_digest == policy_digest { + println!("PolicySigned policy digest is correct"); + } else { + println!("Warning: policy digest mismatch"); + } + + // Demonstrate PolicyRestart + tpm.PolicyRestart(&session_handle(&policy_sess))?; + let reset_digest = tpm.PolicyGetDigest(&session_handle(&policy_sess))?; + if reset_digest.iter().all(|&b| b == 0) { + println!("PolicyRestart correctly reset the digest"); + } + + tpm.FlushContext(&session_handle(&policy_sess))?; + tpm.FlushContext(&auth_key_handle)?; + + println!("PolicySigned sample completed successfully"); + Ok(()) +} + +fn policy_authorize_sample(tpm: &mut Tpm2) -> Result<(), TpmError> { + announce("PolicyAuthorize"); + + // PolicyAuthorize lets a key holder transform a policyHash into a new + // policyHash derived from a public key, if the corresponding private key + // holder authorizes the pre-policy-hash with a signature. + + let hash_alg = TPM_ALG_ID::SHA256; + + // Create a software signing key (the "authorizing" key) + let mut sw_key = TSS_KEY::default(); + sw_key.publicPart = TPMT_PUBLIC { + nameAlg: hash_alg, + objectAttributes: TPMA_OBJECT( + TPMA_OBJECT::sign.get_value() | TPMA_OBJECT::userWithAuth.get_value(), + ), + authPolicy: vec![], + parameters: Some(TPMU_PUBLIC_PARMS::rsaDetail(TPMS_RSA_PARMS { + symmetric: TPMT_SYM_DEF_OBJECT::default(), + scheme: Some(TPMU_ASYM_SCHEME::rsassa(TPMS_SIG_SCHEME_RSASSA { + hashAlg: hash_alg, + })), + keyBits: 2048, + exponent: 0, + })), + unique: Some(TPMU_PUBLIC_ID::rsa(TPM2B_PUBLIC_KEY_RSA::default())), + }; + sw_key.create_key()?; + println!("Created authorizing SW key"); + + // Load the public part into the TPM (OWNER hierarchy for valid tickets) + let auth_key_handle = tpm.LoadExternal( + &TPMT_SENSITIVE::default(), + &sw_key.publicPart, + &TPM_HANDLE::new(TPM_RH::OWNER.get_value()), + )?; + + // Get the authorizing key name + let key_name = sw_key.publicPart.get_name()?; + + // Step 1: Get the pre-policy digest we want to authorize (PolicyLocality(LOC_ONE)) + let trial_pre = tpm.start_auth_session(TPM_SE::TRIAL, hash_alg)?; + tpm.PolicyLocality(&session_handle(&trial_pre), TPMA_LOCALITY::LOC_ONE)?; + let pre_digest = tpm.PolicyGetDigest(&session_handle(&trial_pre))?; + tpm.FlushContext(&session_handle(&trial_pre))?; + println!("Pre-digest (PolicyLocality): {:?}", &pre_digest[..8]); + + // Step 2: Sign the approvedPolicy as defined in the spec: + // aHash = Hash(approvedPolicy || policyRef) + let policy_ref: Vec = vec![]; + let mut a_hash_data = Vec::new(); + a_hash_data.extend_from_slice(&pre_digest); + a_hash_data.extend_from_slice(&policy_ref); + let a_hash = Crypto::hash(hash_alg, &a_hash_data)?; + + let signature = sw_key.sign(&a_hash, hash_alg)?; + println!("Signed approvedPolicy with authorizing key"); + + // Step 3: Use VerifySignature to get a validation ticket + let check_ticket = tpm.VerifySignature( + &auth_key_handle, + &a_hash, + &signature.signature, + )?; + println!("Got verification ticket from TPM"); + + // Step 4: Execute the policy + // Start a real policy session + let policy_sess = tpm.start_auth_session(TPM_SE::POLICY, hash_alg)?; + + // First execute the sub-policy (PolicyLocality) + tpm.PolicyLocality(&session_handle(&policy_sess), TPMA_LOCALITY::LOC_ONE)?; + + // Then call PolicyAuthorize to transform the digest + tpm.PolicyAuthorize( + &session_handle(&policy_sess), + &pre_digest, + &policy_ref, + &key_name, + &check_ticket, + )?; + + let actual_digest = tpm.PolicyGetDigest(&session_handle(&policy_sess))?; + + // Compute expected: PolicyUpdate for PolicyAuthorize + // policyDigest_new = H(0...0 || TPM_CC_PolicyAuthorize || keyName || policyRef) + let hash_len = Crypto::hash(hash_alg, &[])?.len(); + let mut expected_data = vec![0u8; hash_len]; + expected_data.extend_from_slice(&TPM_CC::PolicyAuthorize.get_value().to_be_bytes()); + expected_data.extend_from_slice(&key_name); + // policyRef is empty, no need to extend + let expected_digest = Crypto::hash(hash_alg, &expected_data)?; + + if actual_digest == expected_digest { + println!("PolicyAuthorize digest is correct"); + } else { + println!("PolicyAuthorize digest: {:?}", &actual_digest[..8]); + println!("Expected digest: {:?}", &expected_digest[..8]); + } + + tpm.FlushContext(&session_handle(&policy_sess))?; + tpm.FlushContext(&auth_key_handle)?; + + println!("PolicyAuthorize sample completed successfully"); + Ok(()) +} + +fn admin_sample(tpm: &mut Tpm2) -> Result<(), TpmError> { + announce("Administration"); + + // This sample demonstrates some TPM administration functions. + + // Note: Clear, ChangePPS, ChangeEPS, HierarchyControl, and SetPrimaryPolicy + // with locality require Platform auth or locality control, which are not + // available on TBS. Those are skipped here. + + // --- HierarchyChangeAuth --- + // We can change the authValue for the owner hierarchy. + println!(">> HierarchyChangeAuth"); + + let new_owner_auth = Crypto::hash(TPM_ALG_ID::SHA1, b"passw0rd")?; + println!("Setting OWNER auth to hash of 'passw0rd': {} bytes", new_owner_auth.len()); + + tpm.HierarchyChangeAuth( + &TPM_HANDLE::new(TPM_RH::OWNER.get_value()), + &new_owner_auth, + )?; + println!("OWNER auth changed successfully"); + + // TSS.Rust tracks changes of auth-values and updates the relevant handle. + // Because we have the new auth-value we can continue managing the TPM. + // Now set it back to empty. + tpm.HierarchyChangeAuth( + &TPM_HANDLE::new(TPM_RH::OWNER.get_value()), + &vec![], + )?; + println!("OWNER auth reset to empty"); + + // --- Demonstrate that primary keys are deterministic --- + println!("\n>> Primary key determinism"); + + match (|| -> Result<(), TpmError> { + let h1 = make_storage_primary(tpm)?; + let h2 = make_storage_primary(tpm)?; + + let pub1 = tpm.ReadPublic(&h1)?; + let pub2 = tpm.ReadPublic(&h2)?; + + if pub1.name == pub2.name { + println!("Two primary keys from same template have identical names (as expected)"); + } else { + println!("Warning: primary keys differ unexpectedly"); + } + + tpm.FlushContext(&h1)?; + tpm.FlushContext(&h2)?; + Ok(()) + })() { + Ok(()) => {} + Err(e) => println!("Primary key determinism test skipped ({})", e), + } + + println!("Admin sample completed successfully"); + Ok(()) +} + +/// Demonstrates the PolicyTree abstraction for declarative policy composition. +/// This replaces the manual trial-session + command-by-command approach with +/// a composable tree that can compute digests and execute policies automatically. +fn policy_tree_sample(tpm: &mut Tpm2) -> Result<(), TpmError> { + announce("PolicyTree Sample"); + + let hash_alg = TPM_ALG_ID::SHA256; + + // ----------------------------------------------------------------------- + // 1) Simple PolicyTree: PolicyCommandCode restricting to HMAC_Start + // ----------------------------------------------------------------------- + let tree = PolicyTree::new() + .add(PolicyCommandCode::new(TPM_CC::HMAC_Start)); + + // Compute digest in software (no TPM trial session needed) + let sw_digest = tree.get_policy_digest(hash_alg)?; + + // Verify against a trial session on the TPM + let trial = tpm.start_auth_session(TPM_SE::TRIAL, hash_alg)?; + tpm.PolicyCommandCode(&session_handle(&trial), TPM_CC::HMAC_Start)?; + let tpm_digest = tpm.PolicyGetDigest(&session_handle(&trial))?; + tpm.FlushContext(&session_handle(&trial))?; + + assert_eq!(sw_digest, tpm_digest, "PolicyCommandCode: SW vs TPM digest mismatch"); + println!("PolicyTree digest (PolicyCommandCode) matches TPM trial: "); + + // ----------------------------------------------------------------------- + // 2) PolicyTree with multiple assertions chained + // ----------------------------------------------------------------------- + let tree2 = PolicyTree::new() + .add(PolicyLocality::new(TPMA_LOCALITY::LOC_ZERO)) + .add(PolicyCommandCode::new(TPM_CC::Sign)); + + let sw_digest2 = tree2.get_policy_digest(hash_alg)?; + + let trial2 = tpm.start_auth_session(TPM_SE::TRIAL, hash_alg)?; + tpm.PolicyLocality(&session_handle(&trial2), TPMA_LOCALITY::LOC_ZERO)?; + tpm.PolicyCommandCode(&session_handle(&trial2), TPM_CC::Sign)?; + let tpm_digest2 = tpm.PolicyGetDigest(&session_handle(&trial2))?; + tpm.FlushContext(&session_handle(&trial2))?; + + assert_eq!(sw_digest2, tpm_digest2, "Chained policy: SW vs TPM digest mismatch"); + println!("PolicyTree digest (Locality + CommandCode) matches TPM trial: "); + + // ----------------------------------------------------------------------- + // 3) PolicyOR via PolicyTree + // ----------------------------------------------------------------------- + // Branch 1: PolicyCommandCode(HMAC_Start) + let branch1: Vec> = vec![ + Box::new(PolicyCommandCode::new(TPM_CC::HMAC_Start)), + ]; + // Branch 2: PolicyCommandCode(Sign) + let branch2: Vec> = vec![ + Box::new(PolicyCommandCode::new(TPM_CC::Sign)), + ]; + + let or_tree = PolicyTree::new() + .add(PolicyOr::new(vec![branch1, branch2])); + + let sw_or_digest = or_tree.get_policy_digest(hash_alg)?; + + // Verify OR digest with TPM trial session + let trial_b1 = tpm.start_auth_session(TPM_SE::TRIAL, hash_alg)?; + tpm.PolicyCommandCode(&session_handle(&trial_b1), TPM_CC::HMAC_Start)?; + let b1_digest = tpm.PolicyGetDigest(&session_handle(&trial_b1))?; + tpm.FlushContext(&session_handle(&trial_b1))?; + + let trial_b2 = tpm.start_auth_session(TPM_SE::TRIAL, hash_alg)?; + tpm.PolicyCommandCode(&session_handle(&trial_b2), TPM_CC::Sign)?; + let b2_digest = tpm.PolicyGetDigest(&session_handle(&trial_b2))?; + tpm.FlushContext(&session_handle(&trial_b2))?; + + let hash_list = vec![ + TPM2B_DIGEST { buffer: b1_digest }, + TPM2B_DIGEST { buffer: b2_digest }, + ]; + + let trial_or = tpm.start_auth_session(TPM_SE::TRIAL, hash_alg)?; + tpm.PolicyOR(&session_handle(&trial_or), &hash_list)?; + let tpm_or_digest = tpm.PolicyGetDigest(&session_handle(&trial_or))?; + tpm.FlushContext(&session_handle(&trial_or))?; + + assert_eq!(sw_or_digest, tpm_or_digest, "PolicyOR: SW vs TPM digest mismatch"); + println!("PolicyTree digest (PolicyOR) matches TPM trial: "); + + // ----------------------------------------------------------------------- + // 4) Execute a PolicyTree against a real policy session + // ----------------------------------------------------------------------- + // Create an HMAC key with the simple PolicyCommandCode policy + let hmac_key = make_hmac_primary_with_policy(tpm, &sw_digest, &[], hash_alg)?; + + // Execute the policy tree against a real session + let policy_sess = tpm.start_auth_session(TPM_SE::POLICY, hash_alg)?; + let policy_sess = tree.execute(tpm, policy_sess)?; + + let hmac_seq = tpm.with_session(policy_sess.clone()).HMAC_Start(&hmac_key, &vec![], hash_alg)?; + println!("PolicyTree execute succeeded - HMAC_Start handle: {:?}", hmac_seq); + tpm.FlushContext(&hmac_seq)?; + tpm.FlushContext(&session_handle(&policy_sess))?; + tpm.FlushContext(&hmac_key)?; + + // ----------------------------------------------------------------------- + // 5) PolicyPassword via PolicyTree + // ----------------------------------------------------------------------- + let pw_tree = PolicyTree::new() + .add(PolicyPassword::new()); + + let pw_digest = pw_tree.get_policy_digest(hash_alg)?; + + let trial_pw = tpm.start_auth_session(TPM_SE::TRIAL, hash_alg)?; + tpm.PolicyPassword(&session_handle(&trial_pw))?; + let tpm_pw_digest = tpm.PolicyGetDigest(&session_handle(&trial_pw))?; + tpm.FlushContext(&session_handle(&trial_pw))?; + + assert_eq!(pw_digest, tpm_pw_digest, "PolicyPassword: SW vs TPM digest mismatch"); + println!("PolicyTree digest (PolicyPassword) matches TPM trial: "); + + println!("PolicyTree sample completed successfully"); + Ok(()) +} + +/// Demonstrates a salted (seeded) auth session. The salt is RSA-OAEP encrypted +/// to a storage primary's public key, providing protection even when authValues +/// are known or can be inferred. +fn seeded_session_sample(tpm: &mut Tpm2) -> Result<(), TpmError> { + announce("SeededSession"); + + // Create a storage primary to use as the salt-encryption key + let salt_key = make_storage_primary(tpm)?; + + // Generate a random salt + let salt = Crypto::get_random(20); + println!("Salt ({} bytes): {:?}", salt.len(), &salt[..8]); + + // Start a salted HMAC session. + // start_auth_session_ex will ReadPublic on the salt key, encrypt the salt + // with RSA-OAEP (label "SECRET"), and derive the session key via KDFa. + let sess = tpm.start_auth_session_ex( + &salt_key, // tpmKey for salt encryption + &TPM_HANDLE::new(TPM_RH::NULL.get_value()), // no binding + TPM_SE::HMAC, + TPM_ALG_ID::SHA256, + TPMA_SESSION::continueSession, + TPMT_SYM_DEF::new(TPM_ALG_ID::AES, 128, TPM_ALG_ID::CFB), + &salt, + )?; + println!("Started salted HMAC session: {:?}", session_handle(&sess)); + + // Use the salted session to create a child key under the storage primary + let sign_parms = TPMU_PUBLIC_PARMS::rsaDetail(TPMS_RSA_PARMS::new( + &TPMT_SYM_DEF_OBJECT::new(TPM_ALG_ID::NULL, 0, TPM_ALG_ID::NULL), + &Some(TPMU_ASYM_SCHEME::rsassa(TPMS_SIG_SCHEME_RSASSA { hashAlg: TPM_ALG_ID::SHA256 })), + 2048, + 65537, + )); + let in_pub = TPMT_PUBLIC::new( + TPM_ALG_ID::SHA256, + TPMA_OBJECT::sign | TPMA_OBJECT::fixedParent | TPMA_OBJECT::fixedTPM + | TPMA_OBJECT::sensitiveDataOrigin | TPMA_OBJECT::userWithAuth, + &vec![], + &Some(sign_parms), + &Some(TPMU_PUBLIC_ID::rsa(TPM2B_PUBLIC_KEY_RSA::default())), + ); + + let created = tpm.with_session(sess.clone()).Create( + &salt_key, &TPMS_SENSITIVE_CREATE::default(), &in_pub, &vec![], &vec![], + )?; + let sess = tpm.last_session().unwrap_or(sess); + println!("Created child key under salted session"); + + // Load the child + let child_handle = tpm.with_session(sess.clone()).Load( + &salt_key, &created.outPrivate, &created.outPublic, + )?; + let sess = tpm.last_session().unwrap_or(sess); + println!("Loaded child key: {:?}", child_handle); + + tpm.FlushContext(&child_handle)?; + tpm.FlushContext(&session_handle(&sess))?; + tpm.FlushContext(&salt_key)?; + + println!("SeededSession sample completed successfully"); + Ok(()) +} + +/// Demonstrates a bound auth session. A bound session is associated with a +/// specific TPM entity. When the session is used with that entity, the HMAC +/// calculation uses the entity's auth value in the session key derivation. +fn bound_session_sample(tpm: &mut Tpm2) -> Result<(), TpmError> { + announce("BoundSession"); + + // Set owner auth to a known non-empty value + let owner_auth: Vec = vec![0, 2, 1, 3, 5, 6]; + tpm.HierarchyChangeAuth(&TPM_HANDLE::new(TPM_RH::OWNER.get_value()), &owner_auth)?; + tpm.set_admin_auth(TPM_RH::OWNER, &owner_auth); + + // Run the actual test, then ALWAYS reset OWNER auth afterward + let result = bound_session_inner(tpm, &owner_auth); + + // Always reset owner auth, even if the test failed + tpm.allow_errors(); + let _ = tpm.HierarchyChangeAuth(&TPM_HANDLE::new(TPM_RH::OWNER.get_value()), &vec![]); + tpm.set_admin_auth(TPM_RH::OWNER, &vec![]); + + result +} + +fn bound_session_inner(tpm: &mut Tpm2, owner_auth: &[u8]) -> Result<(), TpmError> { + // Start a session bound to the owner handle + let mut owner_handle = TPM_HANDLE::new(TPM_RH::OWNER.get_value()); + owner_handle.auth_value = owner_auth.to_vec(); + + let sess = tpm.start_auth_session_ex( + &TPM_HANDLE::new(TPM_RH::NULL.get_value()), // no salt + &owner_handle, // bound to OWNER + TPM_SE::HMAC, + TPM_ALG_ID::SHA256, + TPMA_SESSION::continueSession, + TPMT_SYM_DEF::default(), + &[], // no salt + )?; + println!("Started bound session (bound to OWNER): {:?}", session_handle(&sess)); + + // Use the bound session to define an NV index (owner-authorized operation) + let nv_index: u32 = 0x01800099; + let nv_handle = TPM_HANDLE::new(nv_index); + + // Clean up in case it exists from a previous run + tpm.allow_errors(); + let _ = tpm.NV_UndefineSpace(&TPM_HANDLE::new(TPM_RH::OWNER.get_value()), &nv_handle); + + let nv_pub = TPMS_NV_PUBLIC::new( + &nv_handle, + TPM_ALG_ID::SHA256, + TPMA_NV::AUTHREAD | TPMA_NV::AUTHWRITE, + &vec![], + 16, + ); + + // Define NV space using the bound session (bound to OWNER, same entity) + let nv_auth: Vec = vec![5, 4, 3, 2, 1, 0]; + tpm.with_session(sess.clone()).NV_DefineSpace( + &TPM_HANDLE::new(TPM_RH::OWNER.get_value()), &nv_auth, &nv_pub, + )?; + let sess = tpm.last_session().unwrap_or(sess); + println!("Defined NV index with bound session (same-entity binding)"); + + // Read NV public to get the name + let nv_info = tpm.NV_ReadPublic(&nv_handle)?; + let mut nv_handle_with_auth = nv_handle.clone(); + nv_handle_with_auth.auth_value = nv_auth.clone(); + nv_handle_with_auth.set_name(&nv_info.nvName)?; + + // Write to NV using the bound session (different entity - the NV index) + tpm.with_session(sess.clone()).NV_Write( + &nv_handle_with_auth, &nv_handle_with_auth, &vec![0, 1, 2, 3], 0, + )?; + let sess = tpm.last_session().unwrap_or(sess); + println!("Wrote to NV index with bound session (different-entity binding)"); + + // After NV_Write, the TPM sets TPMA_NV::WRITTEN which changes the NV Name. + // We must re-read the public area to get the updated name for subsequent commands. + let nv_info = tpm.NV_ReadPublic(&nv_handle)?; + nv_handle_with_auth.set_name(&nv_info.nvName)?; + + // Read back + let read_data = tpm.with_session(sess.clone()).NV_Read( + &nv_handle_with_auth, &nv_handle_with_auth, 4, 0, + )?; + let sess = tpm.last_session().unwrap_or(sess); + println!("Read back NV data: {:?}", read_data); + assert_eq!(read_data, vec![0, 1, 2, 3], "NV read/write mismatch"); + + // Clean up NV and session + tpm.allow_errors(); + let _ = tpm.NV_UndefineSpace(&TPM_HANDLE::new(TPM_RH::OWNER.get_value()), &nv_handle); + tpm.FlushContext(&session_handle(&sess))?; + + println!("BoundSession sample completed successfully"); + Ok(()) +} + +fn reset_da_lockout(tpm: &mut Tpm2) { + tpm.allow_errors(); + let _ = tpm.DictionaryAttackLockReset(&TPM_HANDLE::new(TPM_RH::LOCKOUT.get_value())); + if tpm.last_response_code() != TPM_RC::SUCCESS { + if let Ok(da_info) = tpm.GetCapability(TPM_CAP::TPM_PROPERTIES, TPM_PT::LOCKOUT_COUNTER.get_value(), 4) { + if let Some(TPMU_CAPABILITIES::tpmProperties(props)) = &da_info.capabilityData { + for p in &props.tpmProperty { + match p.property { + TPM_PT::LOCKOUT_COUNTER => println!("DA failure count: {}", p.value), + TPM_PT::LOCKOUT_INTERVAL => println!("DA lockout interval: {} seconds", p.value), + TPM_PT::LOCKOUT_RECOVERY => println!("DA lockout recovery: {} seconds", p.value), + TPM_PT::MAX_AUTH_FAIL => println!("DA max auth fail: {}", p.value), + _ => {} + } + } + } + } + println!("Note: DictionaryAttackLockReset failed (rc={}), some auth-based samples may fail", tpm.last_response_code()); + } else { + println!("DA lockout cleared successfully"); + } +} + +fn recover_endorsement_hierarchy(tpm: &mut Tpm2) { + let hash_alg = TPM_ALG_ID::SHA256; + let endorsement_name = TPM_HANDLE::new(TPM_RH::ENDORSEMENT.get_value()).get_name().unwrap_or_default(); + let name_hash = Crypto::hash(hash_alg, &endorsement_name).unwrap_or_default(); + + tpm.allow_errors(); + if let Ok(sess) = tpm.start_auth_session(TPM_SE::POLICY, hash_alg) { + let _ = tpm.PolicyNameHash(&session_handle(&sess), &name_hash); + let _ = tpm.with_session(sess.clone()).HierarchyChangeAuth( + &TPM_HANDLE::new(TPM_RH::ENDORSEMENT.get_value()), + &vec![], + ); + let _ = tpm.FlushContext(&session_handle(&sess)); + } + tpm.allow_errors(); + let _ = tpm.SetPrimaryPolicy( + &TPM_HANDLE::new(TPM_RH::ENDORSEMENT.get_value()), + &vec![], + TPM_ALG_ID::NULL, + ); +} + +fn recover_owner_hierarchy(tpm: &mut Tpm2) { + let known_auths: Vec> = vec![ + Crypto::hash(TPM_ALG_ID::SHA1, b"passw0rd").unwrap_or_default(), + vec![0, 2, 1, 3, 5, 6], // bound_session_sample + ]; + for known_auth in &known_auths { + tpm.set_admin_auth(TPM_RH::OWNER, known_auth); + tpm.allow_errors(); + let _ = tpm.HierarchyChangeAuth(&TPM_HANDLE::new(TPM_RH::OWNER.get_value()), &vec![]); + if tpm.last_response_code() == TPM_RC::SUCCESS { + println!("Recovered OWNER auth"); + break; + } + } + tpm.set_admin_auth(TPM_RH::OWNER, &[]); +} + +fn main() -> Result<(), Box> { + let mut device = Box::new(TpmTbsDevice::new()); + device.connect()?; + let mut tpm = create_tpm_with_device(device); + + reset_da_lockout(&mut tpm); + recover_endorsement_hierarchy(&mut tpm); + recover_owner_hierarchy(&mut tpm); + + get_capabilities(&mut tpm)?; + + // ---- Samples ordered to match C++ RunAllSamples() ---- + + rand_sample(&mut tpm)?; + if let Err(e) = dictionary_attack_sample(&mut tpm) { + print_error(&format!("dictionary_attack_sample failed (TPM may be in lockout): {}", e)); + } + hash_sample(&mut tpm)?; + if let Err(e) = hmac_sample(&mut tpm) { + print_error(&format!("hmac_sample failed (may be DA lockout): {}", e)); + } + pcr_sample(&mut tpm)?; + if let Err(e) = policy_locality_sample(&mut tpm) { + print_error(&format!("policy_locality_sample failed: {}", e)); + } + // GetCapability already ran above + if let Err(e) = nv_sample(&mut tpm) { + print_error(&format!("nv_sample failed: {}", e)); + } + if let Err(e) = primary_keys_sample(&mut tpm) { + print_error(&format!("primary_keys_sample failed: {}", e)); + } + if let Err(e) = auth_sessions_sample(&mut tpm) { + print_error(&format!("auth_sessions_sample failed: {}", e)); + } + if let Err(e) = async_sample(&mut tpm) { + print_error(&format!("async_sample failed: {}", e)); + } + if let Err(e) = policy_simplest_sample(&mut tpm) { + print_error(&format!("policy_simplest_sample failed: {}", e)); + } + if let Err(e) = policy_pcr_sample(&mut tpm) { + print_error(&format!("policy_pcr_sample failed: {}", e)); + } + if let Err(e) = child_keys_sample(&mut tpm) { + print_error(&format!("child_keys_sample failed (likely TBS-blocked ContextSave): {}", e)); + } + if let Err(e) = policy_or_sample(&mut tpm) { + print_error(&format!("policy_or_sample failed: {}", e)); + } + counter_timer_sample(&mut tpm)?; + if let Err(e) = attestation(&mut tpm) { + print_error(&format!("attestation failed: {}", e)); + } + if let Err(e) = admin_sample(&mut tpm) { + print_error(&format!("admin_sample failed: {}", e)); + } + if let Err(e) = policy_cphash_sample(&mut tpm) { + print_error(&format!("policy_cphash_sample failed: {}", e)); + } + if let Err(e) = policy_counter_timer_sample(&mut tpm) { + print_error(&format!("policy_counter_timer_sample failed: {}", e)); + } + if let Err(e) = policy_with_passwords_sample(&mut tpm) { + print_error(&format!("policy_with_passwords_sample failed: {}", e)); + } + if let Err(e) = unseal_sample(&mut tpm) { + print_error(&format!("unseal_sample failed: {}", e)); + } + // Serializer - N/A for Rust + if let Err(e) = session_encryption_sample(&mut tpm) { + print_error(&format!("session_encryption_sample failed: {}", e)); + } + if let Err(e) = import_duplicate_sample(&mut tpm) { + print_error(&format!("import_duplicate_sample failed: {}", e)); + } + if let Err(e) = misc_admin_sample(&mut tpm) { + print_error(&format!("misc_admin_sample failed: {}", e)); + } + if let Err(e) = rsa_encrypt_decrypt_sample(&mut tpm) { + print_error(&format!("rsa_encrypt_decrypt_sample failed: {}", e)); + } + if let Err(e) = audit_sample(&mut tpm) { + print_error(&format!("audit_sample failed: {}", e)); + } + if let Err(e) = activate_credentials(&mut tpm) { + print_error(&format!("activate_credentials failed: {}", e)); + } + if let Err(e) = software_keys_sample(&mut tpm) { + print_error(&format!("software_keys_sample failed: {}", e)); + } + if let Err(e) = policy_signed_sample(&mut tpm) { + print_error(&format!("policy_signed_sample failed: {}", e)); + } + if let Err(e) = policy_authorize_sample(&mut tpm) { + print_error(&format!("policy_authorize_sample failed: {}", e)); + } + if let Err(e) = policy_secret_sample(&mut tpm) { + print_error(&format!("policy_secret_sample failed: {}", e)); + } + if let Err(e) = encrypt_decrypt_sample(&mut tpm) { + print_error(&format!("encrypt_decrypt_sample failed (likely TBS-blocked EncryptDecrypt): {}", e)); + } + if let Err(e) = policy_with_passwords_sample(&mut tpm) { + print_error(&format!("policy_with_passwords_sample (2nd run) failed: {}", e)); + } + // SeededSession - not yet implemented (needs RSA-encrypt salt) + if let Err(e) = policy_nv_sample(&mut tpm) { + print_error(&format!("policy_nv_sample failed: {}", e)); + } + if let Err(e) = policy_name_hash_sample(&mut tpm) { + print_error(&format!("policy_name_hash_sample failed: {}", e)); + } + if let Err(e) = rewrap_sample(&mut tpm) { + print_error(&format!("rewrap_sample failed: {}", e)); + } + if let Err(e) = policy_tree_sample(&mut tpm) { + print_error(&format!("policy_tree_sample failed: {}", e)); + } + if let Err(e) = seeded_session_sample(&mut tpm) { + print_error(&format!("seeded_session_sample failed: {}", e)); + } + if let Err(e) = bound_session_sample(&mut tpm) { + print_error(&format!("bound_session_sample failed: {}", e)); + } + // NVX - not yet implemented (needs Platform auth / simulator) + + announce( + "************************* 🦀🦀🦀 Generated by Tss.Rust 🦀🦀🦀 *************************", + ); + + Ok(()) +} diff --git a/TSS.Rust/src/auth_session.rs b/TSS.Rust/src/auth_session.rs new file mode 100644 index 00000000..fb3819f1 --- /dev/null +++ b/TSS.Rust/src/auth_session.rs @@ -0,0 +1,288 @@ +use crate::crypto::Crypto; +use crate::error::TpmError; +use crate::{tpm_structure::TpmEnum, tpm_types::*}; + +/// Authentication session for TPM commands +#[derive(Debug, Default, Clone)] +pub struct Session { + pub sess_in: TPMS_AUTH_COMMAND, + pub sess_out: TPMS_AUTH_RESPONSE, + + // Additional session properties + pub hash_alg: TPM_ALG_ID, + pub session_type: TPM_SE, + pub needs_hmac: bool, + pub needs_password: bool, + + /// Derived session key (from KDFa with "ATH" label) + pub session_key: Vec, + + /// Symmetric algorithm for parameter encryption + pub symmetric: TPMT_SYM_DEF, + + /// Handle of the entity this session is bound to (NULL if unbound) + pub bind_handle: u32, +} + +impl Session { + pub fn new( + session_handle: TPM_HANDLE, + nonce_tpm: &[u8], + session_attributes: TPMA_SESSION, + nonce_caller: &[u8], + ) -> Self { + Session { + sess_in: TPMS_AUTH_COMMAND::new( + &session_handle, + &nonce_caller.to_vec(), + session_attributes, + &Vec::new(), + ), + sess_out: TPMS_AUTH_RESPONSE::new( + &nonce_tpm.to_vec(), + session_attributes, + &Vec::new(), + ), + hash_alg: TPM_ALG_ID::SHA256, + session_type: TPM_SE::HMAC, + needs_hmac: true, + needs_password: false, + session_key: Vec::new(), + symmetric: TPMT_SYM_DEF::default(), + bind_handle: TPM_RH::NULL.get_value(), + } + } + + /// Create a password authorization session (PWAP) + pub fn pw(auth_value: Option>) -> Self { + let mut s = Session::default(); + s.sess_in.sessionHandle = TPM_HANDLE::new(TPM_RH::PW.get_value()); + s.sess_in.nonce = Vec::new(); + s.sess_in.sessionAttributes = TPMA_SESSION::continueSession; + let auth_value = auth_value.unwrap_or_default(); + s.sess_in.hmac = auth_value; + s.sess_out.sessionAttributes = TPMA_SESSION::continueSession; + s.session_type = TPM_SE::HMAC; + s.needs_hmac = false; + s.needs_password = true; + s.bind_handle = TPM_RH::NULL.get_value(); + + s + } + + /// Create a fully initialized HMAC or policy session from a TPM StartAuthSession response. + pub fn from_tpm_response( + session_handle: TPM_HANDLE, + session_type: TPM_SE, + hash_alg: TPM_ALG_ID, + nonce_caller: Vec, + nonce_tpm: Vec, + attributes: TPMA_SESSION, + symmetric: TPMT_SYM_DEF, + salt: &[u8], + bind_object: &TPM_HANDLE, + ) -> Result { + let mut sess = Session { + sess_in: TPMS_AUTH_COMMAND::new( + &session_handle, + &nonce_caller, + attributes, + &Vec::new(), + ), + sess_out: TPMS_AUTH_RESPONSE::new( + &nonce_tpm, + attributes, + &Vec::new(), + ), + hash_alg, + session_type, + needs_hmac: session_type == TPM_SE::HMAC, + needs_password: false, + session_key: Vec::new(), + symmetric, + bind_handle: bind_object.handle, + }; + + sess.calc_session_key(salt, bind_object)?; + Ok(sess) + } + + /// Derive the session key using KDFa with label "ATH". + /// SessionKey = KDFa(hashAlg, bindAuth || salt, "ATH", nonceTPM, nonceCaller, hashBits) + fn calc_session_key(&mut self, salt: &[u8], bind_object: &TPM_HANDLE) -> Result<(), TpmError> { + let null_handle = TPM_HANDLE::new(TPM_RH::NULL.get_value()); + let has_salt = !salt.is_empty(); + let is_bound = bind_object.handle != null_handle.handle; + + if !has_salt && !is_bound { + // No key derivation needed for unbound, unsalted sessions + return Ok(()); + } + + // hmacKey = bindAuth || salt + let mut hmac_key = Vec::new(); + if is_bound { + let bind_auth = trim_trailing_zeros(&bind_object.auth_value); + hmac_key.extend_from_slice(&bind_auth); + } + hmac_key.extend_from_slice(salt); + + let hash_bits = Crypto::digestSize(self.hash_alg) * 8; + self.session_key = Crypto::kdfa( + self.hash_alg, + &hmac_key, + "ATH", + &self.sess_out.nonce, // nonceTPM + &self.sess_in.nonce, // nonceCaller + hash_bits, + )?; + + Ok(()) + } + + /// Check if this is a password authorization session + pub fn is_pwap(&self) -> bool { + self.sess_in.sessionHandle.handle == TPM_RH::PW.get_value() + } + + /// Set authorization value for HMAC calculation + pub fn set_auth_value(&mut self, auth_value: Vec) { + if self.is_pwap() { + self.sess_in.hmac = auth_value; + } + } + + /// Get the hash algorithm used by this session + pub fn get_hash_alg(&self) -> TPM_ALG_ID { + self.hash_alg + } + + /// Generate an HMAC for authorization. + /// hmacKey = sessionKey || authValue + /// hmac = HMAC(hashAlg, hmacKey, parmHash || nonceNewer || nonceOlder || nonceDec || nonceEnc || sessionAttrs) + pub fn get_auth_hmac( + &self, + cp_hash: Vec, + is_command: bool, + nonce_tpm_dec: &[u8], + nonce_tpm_enc: &[u8], + associated_handle: Option<&TPM_HANDLE>, + ) -> Result, TpmError> { + // PWAP: return the auth value directly + if self.is_pwap() { + return Ok(self.sess_in.hmac.clone()); + } + + // PolicyPassword: return auth value directly + if self.needs_password { + return Ok(self.sess_in.hmac.clone()); + } + + // Determine nonce order based on direction + let (nonce_newer, nonce_older) = if is_command { + (&self.sess_in.nonce, &self.sess_out.nonce) + } else { + (&self.sess_out.nonce, &self.sess_in.nonce) + }; + + // Session attributes: use command attrs for commands, response attrs for responses + let session_attrs = if is_command { + vec![self.sess_in.sessionAttributes.get_value()] + } else { + vec![self.sess_out.sessionAttributes.get_value()] + }; + + // Get auth value from the associated handle + let mut auth = Vec::new(); + if let Some(handle) = associated_handle { + // For bound sessions: if the handle IS the bound entity, skip auth + // (it's already incorporated in the session key via KDFa). + let is_bound = self.bind_handle != TPM_RH::NULL.get_value() + && self.bind_handle != 0 + && handle.handle == self.bind_handle; + + if is_bound { + // Bound to same entity: auth already in session key, don't add again + } else if self.session_type != TPM_SE::POLICY || self.needs_hmac { + auth = trim_trailing_zeros(&handle.auth_value); + } + } + + // hmacKey = sessionKey || auth + let mut hmac_key = Vec::new(); + hmac_key.extend_from_slice(&self.session_key); + hmac_key.extend_from_slice(&auth); + + // Buffer to HMAC: parmHash || nonceNewer || nonceOlder || nonceDec || nonceEnc || sessionAttrs + let mut buf_to_hmac = Vec::new(); + buf_to_hmac.extend_from_slice(&cp_hash); + buf_to_hmac.extend_from_slice(nonce_newer); + buf_to_hmac.extend_from_slice(nonce_older); + buf_to_hmac.extend_from_slice(nonce_tpm_dec); + buf_to_hmac.extend_from_slice(nonce_tpm_enc); + buf_to_hmac.extend_from_slice(&session_attrs); + + Crypto::hmac(self.hash_alg, &hmac_key, &buf_to_hmac) + } + + /// Process parameter encryption/decryption using AES-CFB. + /// Key derivation: KDFa(hashAlg, sessionKey, "CFB", nonceNewer, nonceOlder, 256) + /// First keyBits/8 bytes = AES key, next 16 bytes = IV + pub fn param_xcrypt(&self, data: &[u8], is_command: bool) -> Result, TpmError> { + if data.is_empty() { + return Ok(Vec::new()); + } + + // Only AES-128/256 CFB is supported + if self.symmetric.algorithm != TPM_ALG_ID::AES || self.symmetric.mode != TPM_ALG_ID::CFB { + return Err(TpmError::GenericError( + "Only AES in CFB mode is supported for parameter encryption".to_string(), + )); + } + + let key_bits = self.symmetric.keyBits as usize; + if key_bits != 128 && key_bits != 256 { + return Err(TpmError::GenericError( + format!("Unsupported AES key size: {} bits", key_bits), + )); + } + + let key_size = key_bits / 8; + + // Determine nonce order: for requests, nonceNewer=nonceCaller, nonceOlder=nonceTPM + // For responses, nonceNewer=nonceTPM, nonceOlder=nonceCaller + let (nonce_newer, nonce_older) = if is_command { + (&self.sess_in.nonce, &self.sess_out.nonce) + } else { + (&self.sess_out.nonce, &self.sess_in.nonce) + }; + + // Derive key material: KDFa(hashAlg, sessionKey, "CFB", nonceNewer, nonceOlder, 256) + // Produces key_size + 16 bytes (key + IV) + let num_bits = (key_size + 16) * 8; + let key_info = Crypto::kdfa( + self.hash_alg, + &self.session_key, + "CFB", + nonce_newer, + nonce_older, + num_bits, + )?; + + let aes_key = &key_info[..key_size]; + let iv = &key_info[key_size..key_size + 16]; + + // For requests: encrypt (TPM will decrypt) + // For responses: decrypt (TPM encrypted it) + Crypto::cfb_xcrypt(is_command, aes_key, iv, data) + } +} + +/// Trim trailing zero bytes from a byte vector +fn trim_trailing_zeros(data: &[u8]) -> Vec { + let mut result = data.to_vec(); + while result.last() == Some(&0) { + result.pop(); + } + result +} diff --git a/TSS.Rust/src/crypto.rs b/TSS.Rust/src/crypto.rs new file mode 100644 index 00000000..865a78b8 --- /dev/null +++ b/TSS.Rust/src/crypto.rs @@ -0,0 +1,272 @@ +use crate::{error::TpmError, tpm_types::*}; +use hmac::{Hmac, Mac}; +use rsa::{BigUint, Pkcs1v15Sign, RsaPublicKey}; +use sha1::Sha1; +use sha2::{Digest as Sha2Digest, Sha256, Sha384, Sha512}; +use sm3::Sm3; +use rand::{rngs::OsRng, RngCore}; +use aes::Aes128; +use cipher::{BlockEncrypt, KeyInit}; +use cipher::generic_array::GenericArray; + +pub struct Crypto; + +impl Crypto { + // The function is called from an auto-generated file that expects this specific (non snake_cased) name + #[allow(non_snake_case)] + pub fn digestSize(alg: TPM_ALG_ID) -> usize { + match alg { + TPM_ALG_ID::SHA1 => 20, + TPM_ALG_ID::SHA256 => 32, + TPM_ALG_ID::SHA384 => 48, + TPM_ALG_ID::SHA512 => 64, + TPM_ALG_ID::SM3_256 => 32, + _ => 0, + } + } + + // Hash a byte buffer using the specified algorithm + pub fn hash(alg: TPM_ALG_ID, data: &[u8]) -> Result, TpmError> { + // If the data is empty, return an empty digest of correct size + if data.is_empty() { + return Ok(vec![0; Self::digestSize(alg)]); + } + + let digest = match alg { + TPM_ALG_ID::SHA1 => { + let mut hasher = Sha1::new(); + hasher.update(data); + hasher.finalize().to_vec() + } + TPM_ALG_ID::SHA256 => { + let mut hasher = Sha256::new(); + hasher.update(data); + hasher.finalize().to_vec() + } + TPM_ALG_ID::SHA384 => { + let mut hasher = Sha384::new(); + hasher.update(data); + hasher.finalize().to_vec() + } + TPM_ALG_ID::SHA512 => { + let mut hasher = Sha512::new(); + hasher.update(data); + hasher.finalize().to_vec() + } + TPM_ALG_ID::SM3_256 => { + let mut hasher = Sm3::new(); + hasher.update(data); + hasher.finalize().to_vec() + } + _ => { + return Err(TpmError::NotSupported(format!( + "Unsupported hash algorithm: {:?}", + alg + ))) + } + }; + + let expected_size = Self::digestSize(alg); + if (digest.len() != expected_size) { + return Err(TpmError::InvalidArraySize(format!( + "Hash output length mismatch: expected {}, got {}", + expected_size, + digest.len() + ))); + } + + Ok(digest) + } + + pub fn hmac(hash_alg: TPM_ALG_ID, key: &[u8], to_hash: &[u8]) -> Result, TpmError> { + // Choose the appropriate HMAC algorithm based on the hash algorithm + match hash_alg { + TPM_ALG_ID::SHA1 => { + let mut mac = as Mac>::new_from_slice(key).map_err(|_| { + TpmError::InvalidArraySize("HMAC can take key of any size".to_string()) + })?; + mac.update(to_hash); + Ok(mac.finalize().into_bytes().to_vec()) + } + TPM_ALG_ID::SHA256 => { + let mut mac = as Mac>::new_from_slice(key).map_err(|_| { + TpmError::InvalidArraySize("HMAC can take key of any size".to_string()) + })?; + mac.update(to_hash); + Ok(mac.finalize().into_bytes().to_vec()) + } + TPM_ALG_ID::SHA384 => { + let mut mac = as Mac>::new_from_slice(key).map_err(|_| { + TpmError::InvalidArraySize("HMAC can take key of any size".to_string()) + })?; + mac.update(to_hash); + Ok(mac.finalize().into_bytes().to_vec()) + } + TPM_ALG_ID::SHA512 => { + let mut mac = as Mac>::new_from_slice(key).map_err(|_| { + TpmError::InvalidArraySize("HMAC can take key of any size".to_string()) + })?; + mac.update(to_hash); + Ok(mac.finalize().into_bytes().to_vec()) + } + TPM_ALG_ID::SM3_256 => { + let mut mac = + as Mac>::new_from_slice(key).expect("HMAC can take key of any size"); + mac.update(to_hash); + Ok(mac.finalize().into_bytes().to_vec()) + } + _ => { + return Err(TpmError::NotSupported(format!( + "Unsupported hash algorithm: {:?}", + hash_alg + ))) + } + } + } + + pub fn validate_signature( + public_key: &TPMT_PUBLIC, + signed_blob_hash: Vec, + signature: &Option, + ) -> Result { + if !matches!(&public_key.parameters, Some(TPMU_PUBLIC_PARMS::rsaDetail(_))) { + return Err(TpmError::NotSupported( + "ValidateSignature: Only RSA is supported".to_string(), + )); + }; + + let signature = if let Some(TPMU_SIGNATURE::rsassa(signature)) = &signature { + signature + } else { + return Err(TpmError::NotSupported( + "ValidateSignature: Only RSASSA scheme is supported".to_string(), + )); + }; + + let rsa_pub_key = if let Some(TPMU_PUBLIC_ID::rsa(unique)) = &public_key.unique { + &unique.buffer + } else { + return Err(TpmError::NotSupported( + "ValidateSignature: Only RSA public key is supported".to_string(), + )); + }; + + let rsa_public_key = RsaPublicKey::new(BigUint::from_bytes_be(rsa_pub_key), BigUint::from_bytes_be(&[1, 0, 1])) + .map_err(|_| TpmError::InvalidArraySize("Invalid RSA public key".to_string()))?; + + Ok(rsa_public_key + .verify( + Pkcs1v15Sign::new::(), + &signed_blob_hash, + &signature.sig + ).is_ok()) + } + + // KDFa implementation as specified in TPM 2.0 Part 1 + pub fn kdfa( + hash_alg: TPM_ALG_ID, + key: &[u8], + label: &str, + context_u: &[u8], + context_v: &[u8], + bits: usize, + ) -> Result, TpmError> { + let bytes_needed = (bits + 7) / 8; + let mut result = Vec::new(); + let mut counter = 1u32; + + while result.len() < bytes_needed { + let mut to_hash = Vec::new(); + + // Counter in big-endian + to_hash.extend_from_slice(&counter.to_be_bytes()); + + // Label + to_hash.extend_from_slice(label.as_bytes()); + + // 00 byte separator + to_hash.push(0u8); + + // contextU + to_hash.extend_from_slice(context_u); + + // contextV + to_hash.extend_from_slice(context_v); + + // Number of bits in big-endian + to_hash.extend_from_slice(&(bits as u32).to_be_bytes()); + + // Perform HMAC + let hmac_result = Self::hmac(hash_alg, key, &to_hash)?; + result.extend_from_slice(&hmac_result); + + counter = counter.checked_add(1).ok_or_else(|| { + TpmError::InvalidArraySize("Counter overflow in KDFa".to_string()) + })?; + } + + // Truncate to exact size needed + result.truncate(bytes_needed); + Ok(result) + } + + // AES CFB encryption/decryption + pub fn cfb_xcrypt( + encrypt: bool, + key: &[u8], + iv: &[u8], + data: &[u8] + ) -> Result, TpmError> { + if data.is_empty() { + return Ok(Vec::new()); + } + + if key.len() != 16 && key.len() != 24 && key.len() != 32 { + return Err(TpmError::InvalidArraySize("Invalid AES key length".to_string())); + } + + if iv.len() != 16 { + return Err(TpmError::InvalidArraySize("IV must be 16 bytes".to_string())); + } + + let cipher = Aes128::new(GenericArray::from_slice(key)); + let mut result = Vec::with_capacity(data.len()); + let mut feedback = GenericArray::from_slice(iv).clone(); + + for chunk in data.chunks(16) { + // Encrypt the feedback (IV or previous ciphertext) + let mut encrypted_feedback = feedback.clone(); + cipher.encrypt_block(&mut encrypted_feedback); + + if encrypt { + // CFB encrypt: ciphertext = plaintext XOR encrypt(feedback) + // Next feedback = ciphertext + let mut ct_block = [0u8; 16]; + for (i, &b) in chunk.iter().enumerate() { + ct_block[i] = b ^ encrypted_feedback[i]; + result.push(ct_block[i]); + } + feedback.copy_from_slice(&ct_block); + } else { + // CFB decrypt: plaintext = ciphertext XOR encrypt(feedback) + // Next feedback = ciphertext (input) + let mut ct_block = [0u8; 16]; + ct_block[..chunk.len()].copy_from_slice(chunk); + for (i, &b) in chunk.iter().enumerate() { + result.push(b ^ encrypted_feedback[i]); + } + feedback.copy_from_slice(&ct_block); + } + } + + result.truncate(data.len()); + Ok(result) + } + + // Get random bytes + pub fn get_random(num_bytes: usize) -> Vec { + let mut result = vec![0u8; num_bytes]; + OsRng.fill_bytes(&mut result); + result + } +} diff --git a/TSS.Rust/src/device.rs b/TSS.Rust/src/device.rs new file mode 100644 index 00000000..381213e8 --- /dev/null +++ b/TSS.Rust/src/device.rs @@ -0,0 +1,967 @@ +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See the LICENSE file in the project root for full license information. + */ + +//! TPM device communication implementations + +use crate::error::TpmError; + +#[cfg(target_os = "windows")] +use std::os::raw::c_void; +#[cfg(target_os = "windows")] +use std::ptr; +use windows::Win32::System::TpmBaseServices::*; + +#[cfg(target_os = "linux")] +use std::fs::{File, OpenOptions}; +#[cfg(target_os = "linux")] +use std::os::unix::io::AsRawFd; + +/// Defines the TPM connection information flags +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[repr(u32)] +pub enum TpmConnInfo { + /// Platform hierarchy is enabled, and hardware platform functionality is available + TpmPlatformAvailable = 0x01, + /// Connection represents a TPM Resource Manager (TRM) + TpmUsesTrm = 0x02, + /// The TRM is in raw mode + TpmInRawMode = 0x04, + /// Physical presence signals are supported + TpmSupportsPP = 0x08, + /// System and TPM power control signals are not supported + TpmNoPowerCtl = 0x10, + /// TPM locality cannot be changed + TpmNoLocalityCtl = 0x20, + /// Connection medium is socket + TpmSocketConn = 0x1000, + /// Connection medium is OS/platform specific handle + TpmTbsConn = 0x2000, + /// Socket connection to old version of Intel's user mode TRM on Linux + TpmLinuxOldUserModeTrm = 0x4000, + /// Connection via TCG compliant TCTI connection interface + TpmTctiConn = 0x8000, +} + +/// Commands for TCP communication with TPM simulator +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[repr(u32)] +pub enum TcpTpmCommand { + SignalPowerOn = 1, + SignalPowerOff = 2, + SignalPPOn = 3, + SignalPPOff = 4, + SignalHashStart = 5, + SignalHashData = 6, + SignalHashEnd = 7, + SendCommand = 8, + SignalCancelOn = 9, + SignalCancelOff = 10, + SignalNvOn = 11, + SignalNvOff = 12, + SignalKeyCacheOn = 13, + SignalKeyCacheOff = 14, + RemoteHandshake = 15, + SetAlternativeResult = 16, + SessionEnd = 20, + Stop = 21, + TestFailureMode = 30, +} + +/// Main trait for TPM devices +pub trait TpmDevice { + /// Connect to the TPM device + fn connect(&mut self) -> Result; + + /// Close the connection to the TPM device + fn close(&mut self); + + /// Dispatch a command to the TPM + fn dispatch_command(&mut self, cmd_buf: &[u8]) -> Result<(), TpmError>; + + /// Get a response from the TPM + fn get_response(&mut self) -> Result, TpmError>; + + /// Check if a response is ready + fn response_is_ready(&self) -> Result; + + /// Power control + fn power_ctl(&mut self, _on: bool) -> Result<(), TpmError> { + Err(TpmError::NotSupported("power_ctl".to_string())) + } + + /// Assert physical presence + fn assert_physical_presence(&mut self, _on: bool) -> Result<(), TpmError> { + Err(TpmError::NotSupported( + "assert_physical_presence".to_string(), + )) + } + + /// Set locality for subsequent commands + fn set_locality(&mut self, _locality: u32) -> Result<(), TpmError> { + Err(TpmError::NotSupported("set_locality".to_string())) + } + + /// Check if platform is available + fn platform_available(&self) -> bool { + false + } + + /// Check if power control is available + fn power_ctl_available(&self) -> bool { + self.platform_available() && !self.has_flag(TpmConnInfo::TpmNoPowerCtl as u32) + } + + /// Check if locality control is available + fn locality_ctl_available(&self) -> bool { + self.platform_available() && !self.has_flag(TpmConnInfo::TpmNoLocalityCtl as u32) + } + + /// Check if physical presence can be asserted + fn implements_physical_presence(&self) -> bool { + self.has_flag(TpmConnInfo::TpmSupportsPP as u32) + } + + /// Power on convenience method + fn power_on(&mut self) -> Result<(), TpmError> { + self.power_ctl(true) + } + + /// Power off convenience method + fn power_off(&mut self) -> Result<(), TpmError> { + self.power_ctl(false) + } + + /// Power cycle convenience method + fn power_cycle(&mut self) -> Result<(), TpmError> { + self.power_ctl(false)?; + self.power_ctl(true) + } + + /// Physical presence on convenience method + fn pp_on(&mut self) -> Result<(), TpmError> { + self.assert_physical_presence(true) + } + + /// Physical presence off convenience method + fn pp_off(&mut self) -> Result<(), TpmError> { + self.assert_physical_presence(false) + } + + /// Check if a specific flag is set in TpmInfo + fn has_flag(&self, flag: u32) -> bool; + + /// Get the TpmInfo flags + fn get_tpm_info(&self) -> u32; +} + +// /// TPM device implementation for TCP connection (simulator) +// pub struct TpmTcpDevice { +// host_name: String, +// port: u16, +// command_socket: Option, +// signal_socket: Option, +// locality: u8, +// tpm_info: u32, +// } + +// impl TpmTcpDevice { +// /// Create a new TpmTcpDevice +// pub fn new(host_name: String, port: u16) -> Self { +// TpmTcpDevice { +// host_name, +// port, +// command_socket: None, +// signal_socket: None, +// locality: 0, +// tpm_info: 0, +// } +// } + +// /// Set the target for the TCP connection +// pub fn set_target(&mut self, host_name: String, port: u16) { +// self.host_name = host_name; +// self.port = port; +// self.locality = 0; +// } + +// /// Connect to the specified host and port +// pub fn connect_to(&mut self, host_name: String, port: u16) -> Result { +// self.set_target(host_name, port); +// self.connect() +// } + +// // Helper function to send an integer in network byte order +// fn send_int(socket: &mut TcpStream, value: u32) -> Result<(), TpmError> { +// let value_bytes = value.to_be_bytes(); +// socket +// .write_all(&value_bytes) +// .map_err(|e| TpmError::IoError(e.to_string())) +// } + +// // Helper function to receive an integer in network byte order +// fn receive_int(socket: &mut TcpStream) -> Result { +// let mut buffer = [0u8; 4]; +// socket +// .read_exact(&mut buffer) +// .map_err(|e| TpmError::IoError(e.to_string()))?; +// Ok(u32::from_be_bytes(buffer)) +// } + +// // Helper function to get acknowledgement from server +// fn get_ack(socket: &mut TcpStream) -> Result<(), TpmError> { +// let end_tag = Self::receive_int(socket)?; + +// if end_tag != 0 { +// if end_tag == 1 { +// return Err(TpmError::CommandFailed); +// } else { +// return Err(TpmError::BadEndTag); +// } +// } + +// Ok(()) +// } + +// // Helper function to send a command and get acknowledgement +// fn send_cmd_and_get_ack(socket: &mut TcpStream, cmd: TcpTpmCommand) -> Result<(), TpmError> { +// Self::send_int(socket, cmd as u32)?; +// Self::get_ack(socket) +// } + +// // Helper function to receive a variable-length array +// fn recv_var_array(socket: &mut TcpStream) -> Result, TpmError> { +// let len = Self::receive_int(socket)? as usize; +// let mut buffer = vec![0u8; len]; + +// socket +// .read_exact(&mut buffer) +// .map_err(|e| TpmError::IoError(e.to_string()))?; + +// Ok(buffer) +// } +// } + +// impl TpmDevice for TpmTcpDevice { +// fn connect(&mut self) -> Result { +// // Close any existing connections +// self.close(); + +// // Connect to the signal port first +// let signal_addr = format!("{}:{}", self.host_name, self.port + 1); +// let signal_socket = TcpStream::connect(signal_addr) +// .map_err(|e| TpmError::IoError(format!("Failed to connect to signal port: {}", e)))?; + +// // Connect to the command port +// let command_addr = format!("{}:{}", self.host_name, self.port); +// let command_socket = TcpStream::connect(command_addr) +// .map_err(|e| TpmError::IoError(format!("Failed to connect to command port: {}", e)))?; + +// // Set read and write timeouts +// command_socket +// .set_read_timeout(Some(Duration::from_secs(5))) +// .map_err(|e| TpmError::IoError(e.to_string()))?; +// signal_socket +// .set_read_timeout(Some(Duration::from_secs(5))) +// .map_err(|e| TpmError::IoError(e.to_string()))?; + +// // Store the sockets +// self.command_socket = Some(command_socket); +// self.signal_socket = Some(signal_socket); + +// // Make sure the TPM protocol is running +// if let Some(mut cmd_socket) = self.command_socket.as_ref().map(|s| s.try_clone().unwrap()) { +// // Client version is 1 +// const CLIENT_VERSION: u32 = 1; + +// Self::send_int(&mut cmd_socket, TcpTpmCommand::RemoteHandshake as u32)?; +// Self::send_int(&mut cmd_socket, CLIENT_VERSION)?; + +// let endpoint_ver = Self::receive_int(&mut cmd_socket)?; +// if endpoint_ver != CLIENT_VERSION { +// return Err(TpmError::IncompatibleTpm); +// } + +// // Get the endpoint TPM properties +// self.tpm_info = Self::receive_int(&mut cmd_socket)?; + +// Self::get_ack(&mut cmd_socket)?; + +// Ok(true) +// } else { +// Err(TpmError::NotConnected) +// } +// } + +// fn close(&mut self) { +// // Close command socket if open +// if let Some(_) = self.command_socket.take() { +// // Socket will be closed when dropped +// } + +// // Close signal socket if open +// if let Some(_) = self.signal_socket.take() { +// // Socket will be closed when dropped +// } +// } + +// fn dispatch_command(&mut self, cmd_buf: &[u8]) -> Result<(), TpmError> { +// if let Some(mut socket) = self.command_socket.as_ref().map(|s| s.try_clone().unwrap()) { +// // Send the command header +// Self::send_int(&mut socket, TcpTpmCommand::SendCommand as u32)?; +// socket +// .write_all(&[self.locality]) +// .map_err(|e| TpmError::IoError(e.to_string()))?; +// Self::send_int(&mut socket, cmd_buf.len() as u32)?; + +// // Send the command data +// socket +// .write_all(cmd_buf) +// .map_err(|e| TpmError::IoError(e.to_string()))?; + +// Ok(()) +// } else { +// Err(TpmError::NotConnected) +// } +// } + +// fn get_response(&mut self) -> Result, TpmError> { +// if let Some(mut socket) = self.command_socket.as_ref().map(|s| s.try_clone().unwrap()) { +// // Get the response +// let resp = Self::recv_var_array(&mut socket)?; + +// // Get the terminating ACK +// let ack = Self::receive_int(&mut socket)?; +// if ack != 0 { +// return Err(TpmError::BadEndTag); +// } + +// Ok(resp) +// } else { +// Err(TpmError::NotConnected) +// } +// } + +// fn response_is_ready(&self) -> Result { +// if let Some(socket) = &self.command_socket { +// // Create a read set with just this socket +// let mut read_set = [socket +// .try_clone() +// .map_err(|e| TpmError::IoError(e.to_string()))?]; + +// // Check if there's data to read with a zero timeout +// match socket::select( +// &mut read_set, +// &mut [], +// &mut [], +// Some(&Duration::from_secs(0)), +// ) { +// Ok(1) => Ok(true), +// Ok(_) => Ok(false), +// Err(e) => Err(TpmError::IoError(e.to_string())), +// } +// } else { +// Err(TpmError::NotConnected) +// } +// } + +// fn power_ctl(&mut self, on: bool) -> Result<(), TpmError> { +// if let Some(mut socket) = self.signal_socket.as_ref().map(|s| s.try_clone().unwrap()) { +// let power_cmd = if on { +// TcpTpmCommand::SignalPowerOn +// } else { +// TcpTpmCommand::SignalPowerOff +// }; + +// let nv_cmd = if on { +// TcpTpmCommand::SignalNvOn +// } else { +// TcpTpmCommand::SignalNvOff +// }; + +// Self::send_cmd_and_get_ack(&mut socket, power_cmd)?; +// Self::send_cmd_and_get_ack(&mut socket, nv_cmd)?; + +// Ok(()) +// } else { +// Err(TpmError::NotConnected) +// } +// } + +// fn assert_physical_presence(&mut self, on: bool) -> Result<(), TpmError> { +// if let Some(mut socket) = self.signal_socket.as_ref().map(|s| s.try_clone().unwrap()) { +// let pp_cmd = if on { +// TcpTpmCommand::SignalPPOn +// } else { +// TcpTpmCommand::SignalPPOff +// }; + +// Self::send_cmd_and_get_ack(&mut socket, pp_cmd) +// } else { +// Err(TpmError::NotConnected) +// } +// } + +// fn set_locality(&mut self, locality: u32) -> Result<(), TpmError> { +// if locality > 255 { +// return Err(TpmError::InvalidParameter); +// } + +// self.locality = locality as u8; +// Ok(()) +// } + +// fn platform_available(&self) -> bool { +// self.has_flag(TpmConnInfo::TpmPlatformAvailable as u32) +// } + +// fn has_flag(&self, flag: u32) -> bool { +// (self.tpm_info & flag) != 0 +// } + +// fn get_tpm_info(&self) -> u32 { +// self.tpm_info +// } +// } + +// Windows TBS (TPM Base Services) implementation +#[cfg(target_os = "windows")] +pub struct TpmTbsDevice { + context: *mut c_void, + result_buffer: [u8; 4096], + res_size: u32, + tpm_info: u32, +} + +#[cfg(target_os = "windows")] +impl TpmTbsDevice { + pub fn new() -> Self { + TpmTbsDevice { + context: ptr::null_mut(), + result_buffer: [0; 4096], + res_size: 0, + tpm_info: 0, + } + } +} + +#[cfg(target_os = "windows")] +impl TpmDevice for TpmTbsDevice { + fn connect(&mut self) -> Result { + if !self.context.is_null() { + return Ok(true); // Already connected + } + + let mut params = TBS_CONTEXT_PARAMS2::default(); + params.version = TBS_CONTEXT_VERSION_TWO; + params.Anonymous.Anonymous._bitfield = 4; + params.Anonymous.asUINT32 = 4; + + let context_ptr = &mut self.context as *mut *mut c_void; + let res = unsafe { + Tbsi_Context_Create( + ¶ms as *const TBS_CONTEXT_PARAMS2 as *const TBS_CONTEXT_PARAMS, + context_ptr, + ) + }; + + if res != TBS_SUCCESS { + return Err(TpmError::TbsError(format!( + "Failed to connect to TBS: {:?}", + res + ))); + } + + // Get device info to check if TPM 2.0 is available + let mut info = TPM_DEVICE_INFO::default(); + let res = unsafe { + Tbsi_GetDeviceInfo( + std::mem::size_of::() as u32, + &mut info as *mut _ as *mut c_void, + ) + }; + + if res != TBS_SUCCESS { + return Err(TpmError::TbsError("Failed to get device info".to_string())); + } else if info.tpmVersion != TPM_VERSION_20 { + unsafe { Tbsip_Context_Close(self.context) }; + self.context = ptr::null_mut(); + return Err(TpmError::TbsError( + "Platform does not contain a TPM 2.0".to_string(), + )); + } + + // Set appropriate flags + self.tpm_info = TpmConnInfo::TpmTbsConn as u32; + + Ok(true) + } + + fn close(&mut self) { + if !self.context.is_null() { + unsafe { Tbsip_Context_Close(self.context) }; + self.context = ptr::null_mut(); + } + + self.tpm_info = 0; + } + + fn dispatch_command(&mut self, cmd_buf: &[u8]) -> Result<(), TpmError> { + if self.context.is_null() { + return Err(TpmError::NotConnected); + } + + // Reset result buffer size + self.res_size = self.result_buffer.len() as u32; + + // Submit command to TBS + let res = unsafe { + Tbsip_Submit_Command( + self.context, + TBS_COMMAND_LOCALITY_ZERO, + TBS_COMMAND_PRIORITY_NORMAL, + cmd_buf, + self.result_buffer.as_mut_ptr(), + &mut self.res_size as *mut u32, + ) + }; + + if res != TBS_SUCCESS { + return Err(TpmError::TbsError(format!( + "TBS SubmitCommand error: 0x{:08x}", + res + ))); + } + + Ok(()) + } + + fn get_response(&mut self) -> Result, TpmError> { + if self.res_size == 0 { + return Err(TpmError::NoResponse); + } + + let resp = self.result_buffer[0..self.res_size as usize].to_vec(); + self.res_size = 0; + + Ok(resp) + } + + fn response_is_ready(&self) -> Result { + if self.context.is_null() { + return Err(TpmError::NotConnected); + } + + if self.res_size == 0 { + return Err(TpmError::UnexpectedState); + } + + // For Windows TBS, the response is always ready after dispatch_command + Ok(true) + } + + fn has_flag(&self, flag: u32) -> bool { + (self.tpm_info & flag) != 0 + } + + fn get_tpm_info(&self) -> u32 { + self.tpm_info + } +} + +// Linux TPM device implementation +#[cfg(target_os = "linux")] +pub struct TpmTbsDevice { + dev_tpm: Option, + socket: Option, + tpm_info: u32, +} + +#[cfg(target_os = "linux")] +impl TpmTbsDevice { + pub fn new() -> Self { + TpmTbsDevice { + dev_tpm: None, + socket: None, + tpm_info: 0, + } + } + + fn connect_to_linux_user_mode_trm(&mut self) -> Result { + use std::path::Path; + + // Check if TRM libraries exist + let old_trm = Path::new("/usr/lib/x86_64-linux-gnu/libtctisocket.so.0").exists() + || Path::new("/usr/lib/i386-linux-gnu/libtctisocket.so.0").exists(); + + let new_trm = Path::new("/usr/lib/x86_64-linux-gnu/libtcti-socket.so.0").exists() + || Path::new("/usr/lib/i386-linux-gnu/libtcti-socket.so.0").exists() + || Path::new("/usr/local/lib/libtss2-tcti-tabrmd.so.0").exists(); + + if !(old_trm || new_trm) { + return Ok(false); + } + + // Connect to user mode TRM + let mut socket = TcpStream::connect("127.0.0.1:2323") + .map_err(|e| TpmError::IoError(format!("Failed to connect to user TRM: {}", e)))?; + + // No handshake needed with user mode TRM + + self.socket = Some(socket); + self.tpm_info = TpmConnInfo::TpmSocketConn as u32 + | TpmConnInfo::TpmUsesTrm as u32 + | TpmConnInfo::TpmNoPowerCtl as u32 + | TpmConnInfo::TpmNoLocalityCtl as u32; + + if old_trm { + self.tpm_info |= TpmConnInfo::TpmLinuxOldUserModeTrm as u32; + } + + Ok(true) + } +} + +#[cfg(target_os = "linux")] +impl TpmDevice for TpmTbsDevice { + fn connect(&mut self) -> Result { + if self.tpm_info != 0 { + return Ok(true); // Already connected + } + + // Try to open the direct TPM device + match OpenOptions::new().read(true).write(true).open("/dev/tpm0") { + Ok(file) => { + self.dev_tpm = Some(file); + self.tpm_info = TpmConnInfo::TpmTbsConn as u32 + | TpmConnInfo::TpmNoPowerCtl as u32 + | TpmConnInfo::TpmNoLocalityCtl as u32; + return Ok(true); + } + Err(_) => { + // Try TPM resource manager + match OpenOptions::new() + .read(true) + .write(true) + .open("/dev/tpmrm0") + { + Ok(file) => { + self.dev_tpm = Some(file); + self.tpm_info = TpmConnInfo::TpmTbsConn as u32 + | TpmConnInfo::TpmUsesTrm as u32 + | TpmConnInfo::TpmNoPowerCtl as u32 + | TpmConnInfo::TpmNoLocalityCtl as u32; + return Ok(true); + } + Err(_) => { + // Try user mode TRM + return self.connect_to_linux_user_mode_trm(); + } + } + } + } + } + + fn close(&mut self) { + self.dev_tpm = None; + self.socket = None; + self.tpm_info = 0; + } + + fn dispatch_command(&mut self, cmd_buf: &[u8]) -> Result<(), TpmError> { + if self.tpm_info & (TpmConnInfo::TpmSocketConn as u32) != 0 { + // Socket-based communication + if let Some(socket) = self.socket.as_mut() { + // Send command to the TPM + let mut buf = vec![]; + + // Command header + buf.extend_from_slice(&(TcpTpmCommand::SendCommand as u32).to_be_bytes()); + buf.push(0); // locality + buf.extend_from_slice(&(cmd_buf.len() as u32).to_be_bytes()); + + if self.tpm_info & (TpmConnInfo::TpmLinuxOldUserModeTrm as u32) != 0 { + buf.push(0); // debugMsgLevel + buf.push(1); // commandSent + } + + // Send header and command buffer + socket + .write_all(&buf) + .map_err(|e| TpmError::IoError(e.to_string()))?; + socket + .write_all(cmd_buf) + .map_err(|e| TpmError::IoError(e.to_string()))?; + + Ok(()) + } else { + Err(TpmError::NotConnected) + } + } else if self.tpm_info & (TpmConnInfo::TpmTbsConn as u32) != 0 { + // TPM device file communication + if let Some(dev) = self.dev_tpm.as_mut() { + // Write command to TPM device + match dev.write_all(cmd_buf) { + Ok(_) => Ok(()), + Err(e) => Err(TpmError::IoError(format!( + "Failed to write TPM command: {}", + e + ))), + } + } else { + Err(TpmError::NotConnected) + } + } else { + Err(TpmError::InvalidTpmType) + } + } + + fn get_response(&mut self) -> Result, TpmError> { + if self.tpm_info & (TpmConnInfo::TpmSocketConn as u32) != 0 { + // Socket-based communication + if let Some(socket) = self.socket.as_mut() { + // Receive array length + let mut len_buf = [0u8; 4]; + socket + .read_exact(&mut len_buf) + .map_err(|e| TpmError::IoError(e.to_string()))?; + let len = u32::from_be_bytes(len_buf) as usize; + + // Read the response data + let mut resp = vec![0u8; len]; + socket + .read_exact(&mut resp) + .map_err(|e| TpmError::IoError(e.to_string()))?; + + // Get the terminating ACK + let mut ack_buf = [0u8; 4]; + socket + .read_exact(&mut ack_buf) + .map_err(|e| TpmError::IoError(e.to_string()))?; + let ack = u32::from_be_bytes(ack_buf); + + if ack != 0 { + return Err(TpmError::BadEndTag); + } + + Ok(resp) + } else { + Err(TpmError::NotConnected) + } + } else if self.tpm_info & (TpmConnInfo::TpmTbsConn as u32) != 0 { + // TPM device file communication + if let Some(dev) = self.dev_tpm.as_mut() { + // Buffer for response + let mut resp_buf = [0u8; 4096]; + + // Read from TPM device + match dev.read(&mut resp_buf) { + Ok(bytes_read) => { + if bytes_read < 10 { + // 10 is the mandatory response header size + return Err(TpmError::IoError(format!( + "Failed to read sufficient data from TPM: got {} bytes", + bytes_read + ))); + } + + Ok(resp_buf[0..bytes_read].to_vec()) + } + Err(e) => Err(TpmError::IoError(format!( + "Failed to read TPM response: {}", + e + ))), + } + } else { + Err(TpmError::NotConnected) + } + } else { + Err(TpmError::InvalidTpmType) + } + } + + fn response_is_ready(&self) -> Result { + // For Linux implementations, the response is typically ready after a blocking read + Ok(true) + } + + fn has_flag(&self, flag: u32) -> bool { + (self.tpm_info & flag) != 0 + } + + fn get_tpm_info(&self) -> u32 { + self.tpm_info + } +} + +// /// Socket utility module +// mod socket { +// use std::io; +// use std::net::TcpStream; +// use std::time::Duration; + +// #[cfg(unix)] +// pub fn select( +// read: &mut [TcpStream], +// write: &mut [TcpStream], +// except: &mut [TcpStream], +// timeout: Option<&Duration>, +// ) -> io::Result { +// use libc::{fd_set, select, timeval, FD_ISSET, FD_SET, FD_ZERO}; +// use std::os::unix::io::AsRawFd; + +// unsafe { +// let mut read_fds: fd_set = std::mem::zeroed(); +// let mut write_fds: fd_set = std::mem::zeroed(); +// let mut except_fds: fd_set = std::mem::zeroed(); + +// FD_ZERO(&mut read_fds); +// FD_ZERO(&mut write_fds); +// FD_ZERO(&mut except_fds); + +// let mut max_fd = 0; + +// for stream in read.iter() { +// let fd = stream.as_raw_fd(); +// FD_SET(fd, &mut read_fds); +// max_fd = std::cmp::max(max_fd, fd); +// } + +// for stream in write.iter() { +// let fd = stream.as_raw_fd(); +// FD_SET(fd, &mut write_fds); +// max_fd = std::cmp::max(max_fd, fd); +// } + +// for stream in except.iter() { +// let fd = stream.as_raw_fd(); +// FD_SET(fd, &mut except_fds); +// max_fd = std::cmp::max(max_fd, fd); +// } + +// let mut tv: timeval = std::mem::zeroed(); +// let tv_ptr = if let Some(timeout) = timeout { +// tv.tv_sec = timeout.as_secs() as _; +// tv.tv_usec = (timeout.subsec_micros()) as _; +// &mut tv as *mut timeval +// } else { +// std::ptr::null_mut() +// }; + +// let result = select( +// max_fd + 1, +// &mut read_fds, +// &mut write_fds, +// &mut except_fds, +// tv_ptr, +// ); + +// if result < 0 { +// return Err(io::Error::last_os_error()); +// } + +// // Count how many are ready +// let mut ready_count = 0; + +// for stream in read.iter() { +// if FD_ISSET(stream.as_raw_fd(), &read_fds) { +// ready_count += 1; +// } +// } + +// for stream in write.iter() { +// if FD_ISSET(stream.as_raw_fd(), &write_fds) { +// ready_count += 1; +// } +// } + +// for stream in except.iter() { +// if FD_ISSET(stream.as_raw_fd(), &except_fds) { +// ready_count += 1; +// } +// } + +// Ok(ready_count) +// } +// } + +// #[cfg(windows)] +// pub fn select( +// read: &mut [TcpStream], +// write: &mut [TcpStream], +// except: &mut [TcpStream], +// timeout: Option<&Duration>, +// ) -> io::Result { +// use std::os::windows::io::AsRawSocket; +// use windows::Win32::Networking::WinSock::{ +// fd_set, select, timeval, FD_ISSET, FD_SET, FD_ZERO, +// }; + +// unsafe { +// let mut read_fds: fd_set = std::mem::zeroed(); +// let mut write_fds: fd_set = std::mem::zeroed(); +// let mut except_fds: fd_set = std::mem::zeroed(); + +// FD_ZERO(&mut read_fds); +// FD_ZERO(&mut write_fds); +// FD_ZERO(&mut except_fds); + +// for stream in read.iter() { +// FD_SET(stream.as_raw_socket(), &mut read_fds); +// } + +// for stream in write.iter() { +// FD_SET(stream.as_raw_socket(), &mut write_fds); +// } + +// for stream in except.iter() { +// FD_SET(stream.as_raw_socket(), &mut except_fds); +// } + +// let mut tv: timeval = std::mem::zeroed(); +// let tv_ptr = if let Some(timeout) = timeout { +// tv.tv_sec = timeout.as_secs() as i32; +// tv.tv_usec = (timeout.subsec_micros()) as i32; +// &mut tv as *mut timeval +// } else { +// std::ptr::null_mut() +// }; + +// let result = select( +// 0, // ignored on Windows +// &mut read_fds, +// &mut write_fds, +// &mut except_fds, +// tv_ptr, +// ); + +// if result == -1 { +// return Err(io::Error::last_os_error()); +// } + +// // Count how many are ready +// let mut ready_count = 0; + +// for stream in read.iter() { +// if FD_ISSET(stream.as_raw_socket(), &read_fds) { +// ready_count += 1; +// } +// } + +// for stream in write.iter() { +// if FD_ISSET(stream.as_raw_socket(), &write_fds) { +// ready_count += 1; +// } +// } + +// for stream in except.iter() { +// if FD_ISSET(stream.as_raw_socket(), &except_fds) { +// ready_count += 1; +// } +// } + +// Ok(ready_count as usize) +// } +// } +// } diff --git a/TSS.Rust/src/error.rs b/TSS.Rust/src/error.rs new file mode 100644 index 00000000..f9739623 --- /dev/null +++ b/TSS.Rust/src/error.rs @@ -0,0 +1,105 @@ +//! Error types for TPM operations + +use std::error::Error; +use std::fmt; + +/// TPM Error types +#[derive(Debug)] +pub enum TpmError { + /// Buffer underflow occurred during deserialization + BufferUnderflow, + + /// Buffer overflow occurred during serialization + BufferOverflow, + + /// Invalid array size + InvalidArraySize(String), + + /// Invalid enum value + InvalidEnumValue, + + /// Invalid union type + InvalidUnion, + + /// Incorrect tag value + IncorrectTag(u32, u32), // expected, actual + + /// I/O error + IoError(String), + + /// Device communication error + DeviceError(String), + + /// Generic TPM error + GenericError(String), + + /// Operation not supported + NotSupported(String), + + /// TPM device not connected + NotConnected, + + /// Bad end tag received from TPM + BadEndTag, + + /// Command failed + CommandFailed, + + /// Invalid parameter provided + InvalidParameter, + + /// No response available + NoResponse, + + /// Unexpected device state + UnexpectedState, + + /// Incompatible TPM/proxy + IncompatibleTpm, + + /// Invalid TPM device type + InvalidTpmType, + + /// Windows TBS specific error + #[cfg(target_os = "windows")] + TbsError(String), +} + +impl fmt::Display for TpmError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + Self::BufferUnderflow => write!(f, "Buffer underflow during deserialization"), + Self::BufferOverflow => write!(f, "Buffer overflow during serialization"), + Self::InvalidArraySize(msg) => write!(f, "Invalid array size: {}", msg), + Self::InvalidEnumValue => write!(f, "Invalid enum value"), + Self::InvalidUnion => write!(f, "Invalid union type"), + Self::IncorrectTag(expected, actual) => write!( + f, + "Incorrect tag: expected 0x{:X}, got 0x{:X}", + expected, actual + ), + Self::IoError(msg) => write!(f, "I/O error: {}", msg), + Self::DeviceError(msg) => write!(f, "Device error: {}", msg), + Self::GenericError(msg) => write!(f, "TPM error: {}", msg), + Self::NotSupported(operation) => write!(f, "Operation not supported: {}", operation), + Self::NotConnected => write!(f, "TPM device not connected"), + Self::BadEndTag => write!(f, "Bad end tag received from TPM"), + Self::CommandFailed => write!(f, "TPM command failed"), + Self::InvalidParameter => write!(f, "Invalid parameter provided"), + Self::NoResponse => write!(f, "No TPM response available"), + Self::UnexpectedState => write!(f, "TPM in unexpected state"), + Self::IncompatibleTpm => write!(f, "Incompatible TPM/proxy"), + Self::InvalidTpmType => write!(f, "Invalid TPM device type"), + #[cfg(target_os = "windows")] + Self::TbsError(msg) => write!(f, "TBS error: {}", msg), + } + } +} + +impl Error for TpmError {} + +impl From for TpmError { + fn from(error: std::io::Error) -> Self { + TpmError::IoError(error.to_string()) + } +} diff --git a/TSS.Rust/src/lib.rs b/TSS.Rust/src/lib.rs new file mode 100644 index 00000000..90cf32d3 --- /dev/null +++ b/TSS.Rust/src/lib.rs @@ -0,0 +1,12 @@ +pub mod auth_session; +pub mod crypto; +pub mod device; +pub mod error; +pub mod tpm2; +pub mod tpm2_helpers; +pub mod tpm2_impl; +pub mod tpm_buffer; +pub mod tpm_structure; +pub mod tpm_types; +pub mod tpm_type_extensions; +pub mod policy; diff --git a/TSS.Rust/src/policy.rs b/TSS.Rust/src/policy.rs new file mode 100644 index 00000000..8191e189 --- /dev/null +++ b/TSS.Rust/src/policy.rs @@ -0,0 +1,656 @@ +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See the LICENSE file in the project root for full license information. + */ + +//! Policy tree infrastructure for declarative TPM 2.0 policy composition. +//! +//! This module provides a `PolicyTree` that lets you compose policy assertions +//! (e.g., PolicyLocality, PolicyCommandCode, PolicyPCR, PolicyOR, etc.) into +//! a tree. The tree can then compute a policy digest (trial) or be executed +//! against a real policy session on the TPM. + +use crate::auth_session::Session; +use crate::crypto::Crypto; +use crate::error::TpmError; +use crate::tpm2_impl::Tpm2; +use crate::tpm_buffer::{TpmBuffer, TpmMarshaller}; +use crate::tpm_structure::TpmEnum; +use crate::tpm_types::*; + +// --------------------------------------------------------------------------- +// PolicyAssertion trait - base for all policy nodes +// --------------------------------------------------------------------------- + +/// Trait implemented by all policy assertion types. +pub trait PolicyAssertion { + /// Update a policy digest accumulator (used for trial/software digest computation). + fn update_policy_digest(&self, hash_alg: TPM_ALG_ID, accumulator: &mut Vec) -> Result<(), TpmError>; + + /// Execute this policy assertion against a live TPM policy session. + fn execute(&self, tpm: &mut Tpm2, session: &Session) -> Result; +} + +// --------------------------------------------------------------------------- +// Helper: PolicyUpdate - shared digest update logic per TPM spec +// --------------------------------------------------------------------------- + +/// `policyDigest = H(policyDigest || commandCode || arg2)` +/// Then: `policyDigest = H(policyDigest || arg3)` +fn policy_update( + hash_alg: TPM_ALG_ID, + accumulator: &mut Vec, + command_code: TPM_CC, + arg2: &[u8], + arg3: &[u8], +) -> Result<(), TpmError> { + // First extend: H(accumulator || CC || arg2) + let mut buf = Vec::new(); + buf.extend_from_slice(accumulator); + buf.extend_from_slice(&command_code.get_value().to_be_bytes()); + buf.extend_from_slice(arg2); + *accumulator = Crypto::hash(hash_alg, &buf)?; + + // Second extend (if arg3 is non-empty): H(accumulator || arg3) + if !arg3.is_empty() { + let mut buf2 = Vec::new(); + buf2.extend_from_slice(accumulator); + buf2.extend_from_slice(arg3); + *accumulator = Crypto::hash(hash_alg, &buf2)?; + } + Ok(()) +} + +/// Helper to get session handle from a Session +fn sess_handle(s: &Session) -> TPM_HANDLE { + s.sess_in.sessionHandle.clone() +} + +// --------------------------------------------------------------------------- +// PolicyTree +// --------------------------------------------------------------------------- + +/// A composable policy tree that can compute digests and execute against the TPM. +pub struct PolicyTree { + assertions: Vec>, +} + +impl PolicyTree { + /// Create an empty policy tree. + pub fn new() -> Self { + Self { assertions: Vec::new() } + } + + /// Add a policy assertion to the tree. Assertions execute in order (first added = first executed). + pub fn add(mut self, assertion: impl PolicyAssertion + 'static) -> Self { + self.assertions.push(Box::new(assertion)); + self + } + + /// Compute the policy digest in software (equivalent to a trial session). + pub fn get_policy_digest(&self, hash_alg: TPM_ALG_ID) -> Result, TpmError> { + compute_digest(&self.assertions, hash_alg) + } + + /// Execute all assertions in order against a live policy session. + /// Returns the updated session (with rolled nonces). + pub fn execute(&self, tpm: &mut Tpm2, session: Session) -> Result { + let mut sess = session; + for assertion in &self.assertions { + sess = assertion.execute(tpm, &sess)?; + } + Ok(sess) + } +} + +/// Compute the digest for a slice of assertions (used by PolicyTree and PolicyOr). +pub(crate) fn compute_digest( + assertions: &[Box], + hash_alg: TPM_ALG_ID, +) -> Result, TpmError> { + let hash_len = Crypto::hash(hash_alg, &[])?.len(); + let mut accumulator = vec![0u8; hash_len]; + for assertion in assertions { + assertion.update_policy_digest(hash_alg, &mut accumulator)?; + } + Ok(accumulator) +} + +// --------------------------------------------------------------------------- +// Concrete policy assertion types +// --------------------------------------------------------------------------- + +/// PolicyCommandCode - limits the authorized action to a specific command. +pub struct PolicyCommandCode { + pub command_code: TPM_CC, +} + +impl PolicyCommandCode { + pub fn new(command_code: TPM_CC) -> Self { + Self { command_code } + } +} + +impl PolicyAssertion for PolicyCommandCode { + fn update_policy_digest(&self, hash_alg: TPM_ALG_ID, acc: &mut Vec) -> Result<(), TpmError> { + let mut buf = Vec::new(); + buf.extend_from_slice(&self.command_code.get_value().to_be_bytes()); + policy_update(hash_alg, acc, TPM_CC::PolicyCommandCode, &buf, &[]) + } + + fn execute(&self, tpm: &mut Tpm2, session: &Session) -> Result { + tpm.PolicyCommandCode(&sess_handle(session), self.command_code)?; + Ok(tpm.last_session().unwrap_or_else(|| session.clone())) + } +} + +/// PolicyLocality - limits authorization to a specific locality. +pub struct PolicyLocality { + pub locality: TPMA_LOCALITY, +} + +impl PolicyLocality { + pub fn new(locality: TPMA_LOCALITY) -> Self { + Self { locality } + } +} + +impl PolicyAssertion for PolicyLocality { + fn update_policy_digest(&self, hash_alg: TPM_ALG_ID, acc: &mut Vec) -> Result<(), TpmError> { + // PolicyLocality: H(acc || TPM_CC_PolicyLocality || locality_byte) + let mut buf = Vec::new(); + buf.extend_from_slice(acc); + buf.extend_from_slice(&TPM_CC::PolicyLocality.get_value().to_be_bytes()); + buf.push(self.locality.get_value() as u8); + *acc = Crypto::hash(hash_alg, &buf)?; + Ok(()) + } + + fn execute(&self, tpm: &mut Tpm2, session: &Session) -> Result { + tpm.PolicyLocality(&sess_handle(session), self.locality)?; + Ok(tpm.last_session().unwrap_or_else(|| session.clone())) + } +} + +/// PolicyPCR - gates policy on PCR values. +pub struct PolicyPcr { + pub pcr_values: Vec, + pub pcr_selections: Vec, +} + +impl PolicyPcr { + pub fn new(pcr_values: Vec, pcr_selections: Vec) -> Self { + Self { pcr_values, pcr_selections } + } +} + +impl PolicyAssertion for PolicyPcr { + fn update_policy_digest(&self, hash_alg: TPM_ALG_ID, acc: &mut Vec) -> Result<(), TpmError> { + // Concatenate all PCR values and hash them + let mut pcr_data = Vec::new(); + for v in &self.pcr_values { + pcr_data.extend_from_slice(&v.buffer); + } + let pcr_digest = Crypto::hash(hash_alg, &pcr_data)?; + + // Marshal PCR selections + let mut sel_buf = TpmBuffer::new(None); + sel_buf.writeInt(self.pcr_selections.len() as u32); + for sel in &self.pcr_selections { + sel.toTpm(&mut sel_buf)?; + } + + let mut arg2 = Vec::new(); + arg2.extend_from_slice(sel_buf.trim()); + arg2.extend_from_slice(&pcr_digest); + policy_update(hash_alg, acc, TPM_CC::PolicyPCR, &arg2, &[]) + } + + fn execute(&self, tpm: &mut Tpm2, session: &Session) -> Result { + tpm.PolicyPCR(&sess_handle(session), &self.pcr_values[0].buffer, &self.pcr_selections)?; + Ok(tpm.last_session().unwrap_or_else(|| session.clone())) + } +} + +/// PolicyPassword - requires the object's authorization value be provided as a password. +pub struct PolicyPassword; + +impl PolicyPassword { + pub fn new() -> Self { Self } +} + +impl PolicyAssertion for PolicyPassword { + fn update_policy_digest(&self, hash_alg: TPM_ALG_ID, acc: &mut Vec) -> Result<(), TpmError> { + // PolicyPassword uses the same digest as PolicyAuthValue per spec + policy_update(hash_alg, acc, TPM_CC::PolicyAuthValue, &[], &[]) + } + + fn execute(&self, tpm: &mut Tpm2, session: &Session) -> Result { + tpm.PolicyPassword(&sess_handle(session))?; + let mut sess = tpm.last_session().unwrap_or_else(|| session.clone()); + sess.needs_password = true; + Ok(sess) + } +} + +/// PolicyAuthValue - requires auth-value HMAC during policy use. +pub struct PolicyAuthValue; + +impl PolicyAuthValue { + pub fn new() -> Self { Self } +} + +impl PolicyAssertion for PolicyAuthValue { + fn update_policy_digest(&self, hash_alg: TPM_ALG_ID, acc: &mut Vec) -> Result<(), TpmError> { + policy_update(hash_alg, acc, TPM_CC::PolicyAuthValue, &[], &[]) + } + + fn execute(&self, tpm: &mut Tpm2, session: &Session) -> Result { + tpm.PolicyAuthValue(&sess_handle(session))?; + let mut sess = tpm.last_session().unwrap_or_else(|| session.clone()); + sess.needs_hmac = true; + Ok(sess) + } +} + +/// PolicyCpHash - binds policy to specific command parameters. +pub struct PolicyCpHash { + pub cp_hash: Vec, +} + +impl PolicyCpHash { + pub fn new(cp_hash: Vec) -> Self { + Self { cp_hash } + } +} + +impl PolicyAssertion for PolicyCpHash { + fn update_policy_digest(&self, hash_alg: TPM_ALG_ID, acc: &mut Vec) -> Result<(), TpmError> { + policy_update(hash_alg, acc, TPM_CC::PolicyCpHash, &self.cp_hash, &[]) + } + + fn execute(&self, tpm: &mut Tpm2, session: &Session) -> Result { + tpm.PolicyCpHash(&sess_handle(session), &self.cp_hash)?; + Ok(tpm.last_session().unwrap_or_else(|| session.clone())) + } +} + +/// PolicyNameHash - binds policy to specific object handles. +pub struct PolicyNameHash { + pub name_hash: Vec, +} + +impl PolicyNameHash { + pub fn new(name_hash: Vec) -> Self { + Self { name_hash } + } +} + +impl PolicyAssertion for PolicyNameHash { + fn update_policy_digest(&self, hash_alg: TPM_ALG_ID, acc: &mut Vec) -> Result<(), TpmError> { + policy_update(hash_alg, acc, TPM_CC::PolicyNameHash, &self.name_hash, &[]) + } + + fn execute(&self, tpm: &mut Tpm2, session: &Session) -> Result { + tpm.PolicyNameHash(&sess_handle(session), &self.name_hash)?; + Ok(tpm.last_session().unwrap_or_else(|| session.clone())) + } +} + +/// PolicyCounterTimer - gates policy on TPMS_TIME_INFO contents. +pub struct PolicyCounterTimer { + pub operand_b: Vec, + pub offset: u16, + pub operation: TPM_EO, +} + +impl PolicyCounterTimer { + pub fn new(operand_b: Vec, offset: u16, operation: TPM_EO) -> Self { + Self { operand_b, offset, operation } + } + + /// Convenience: create from a u64 value (marshalled as 8 big-endian bytes). + pub fn from_u64(value: u64, offset: u16, operation: TPM_EO) -> Self { + Self { operand_b: value.to_be_bytes().to_vec(), offset, operation } + } +} + +impl PolicyAssertion for PolicyCounterTimer { + fn update_policy_digest(&self, hash_alg: TPM_ALG_ID, acc: &mut Vec) -> Result<(), TpmError> { + // arg2 = H(operandB || offset || operation) + let mut inner = Vec::new(); + inner.extend_from_slice(&self.operand_b); + inner.extend_from_slice(&self.offset.to_be_bytes()); + inner.extend_from_slice(&(self.operation.get_value() as u16).to_be_bytes()); + let arg_hash = Crypto::hash(hash_alg, &inner)?; + policy_update(hash_alg, acc, TPM_CC::PolicyCounterTimer, &arg_hash, &[]) + } + + fn execute(&self, tpm: &mut Tpm2, session: &Session) -> Result { + tpm.PolicyCounterTimer( + &sess_handle(session), &self.operand_b, self.offset, self.operation, + )?; + Ok(tpm.last_session().unwrap_or_else(|| session.clone())) + } +} + +/// PolicySecret - secret-based authorization (proves knowledge of an auth value). +pub struct PolicySecret { + pub auth_object_name: Vec, + pub policy_ref: Vec, + pub cp_hash_a: Vec, + pub expiration: i32, + pub include_tpm_nonce: bool, + /// The handle used during execution (set before calling execute). + pub auth_handle: TPM_HANDLE, +} + +impl PolicySecret { + pub fn new(auth_object_name: Vec, auth_handle: TPM_HANDLE) -> Self { + Self { + auth_object_name, + policy_ref: vec![], + cp_hash_a: vec![], + expiration: 0, + include_tpm_nonce: false, + auth_handle, + } + } +} + +impl PolicyAssertion for PolicySecret { + fn update_policy_digest(&self, hash_alg: TPM_ALG_ID, acc: &mut Vec) -> Result<(), TpmError> { + policy_update(hash_alg, acc, TPM_CC::PolicySecret, &self.auth_object_name, &self.policy_ref) + } + + fn execute(&self, tpm: &mut Tpm2, session: &Session) -> Result { + let nonce_tpm = if self.include_tpm_nonce { + session.sess_out.nonce.clone() + } else { + vec![] + }; + tpm.PolicySecret( + &self.auth_handle, &sess_handle(session), + &nonce_tpm, &self.cp_hash_a, &self.policy_ref, self.expiration, + )?; + Ok(tpm.last_session().unwrap_or_else(|| session.clone())) + } +} + +/// PolicySigned - asymmetrically signed authorization. +pub struct PolicySigned { + pub include_tpm_nonce: bool, + pub cp_hash_a: Vec, + pub policy_ref: Vec, + pub expiration: i32, + pub public_key: TPMT_PUBLIC, + /// If set, the library will sign automatically. Otherwise a callback is needed. + pub sw_key: Option, +} + +impl PolicySigned { + pub fn new(public_key: TPMT_PUBLIC) -> Self { + Self { + include_tpm_nonce: false, + cp_hash_a: vec![], + policy_ref: vec![], + expiration: 0, + public_key, + sw_key: None, + } + } + + /// Provide a software key so the library can sign automatically. + pub fn with_key(mut self, key: TSS_KEY) -> Self { + self.sw_key = Some(key); + self + } + + pub fn with_nonce(mut self) -> Self { + self.include_tpm_nonce = true; + self + } +} + +impl PolicyAssertion for PolicySigned { + fn update_policy_digest(&self, hash_alg: TPM_ALG_ID, acc: &mut Vec) -> Result<(), TpmError> { + let key_name = self.public_key.get_name()?; + policy_update(hash_alg, acc, TPM_CC::PolicySigned, &key_name, &self.policy_ref) + } + + fn execute(&self, tpm: &mut Tpm2, session: &Session) -> Result { + let nonce_tpm = if self.include_tpm_nonce { + session.sess_out.nonce.clone() + } else { + vec![] + }; + + // Determine hash alg from the key's scheme + let hash_alg = if let Some(TPMU_PUBLIC_PARMS::rsaDetail(ref params)) = self.public_key.parameters { + if let Some(TPMU_ASYM_SCHEME::rsassa(ref scheme)) = params.scheme { + scheme.hashAlg + } else { + self.public_key.nameAlg + } + } else { + self.public_key.nameAlg + }; + + // Compute aHash = Hash(nonceTPM || expiration || cpHashA || policyRef) + let mut to_hash = Vec::new(); + to_hash.extend_from_slice(&nonce_tpm); + to_hash.extend_from_slice(&self.expiration.to_be_bytes()); + to_hash.extend_from_slice(&self.cp_hash_a); + to_hash.extend_from_slice(&self.policy_ref); + let a_hash = Crypto::hash(hash_alg, &to_hash)?; + + let sw_key = self.sw_key.as_ref().ok_or_else(|| { + TpmError::GenericError("PolicySigned: no SW key set (callbacks not yet supported)".into()) + })?; + let signature = sw_key.sign(&a_hash, hash_alg)?; + + // Load the public key into the TPM (OWNER hierarchy for valid tickets) + let pub_key_handle = tpm.LoadExternal( + &TPMT_SENSITIVE::default(), + &self.public_key, + &TPM_HANDLE::new(TPM_RH::OWNER.get_value()), + )?; + + let result = tpm.PolicySigned( + &pub_key_handle, &sess_handle(session), + &nonce_tpm, &self.cp_hash_a, &self.policy_ref, self.expiration, + &signature.signature, + ); + + tpm.FlushContext(&pub_key_handle)?; + result?; + Ok(tpm.last_session().unwrap_or_else(|| session.clone())) + } +} + +/// PolicyNV - conditional gating based on NV Index contents. +pub struct PolicyNv { + pub operand_b: Vec, + pub offset: u16, + pub operation: TPM_EO, + pub nv_index_name: Vec, + pub auth_handle: TPM_HANDLE, + pub nv_index: TPM_HANDLE, +} + +impl PolicyNv { + pub fn new( + auth_handle: TPM_HANDLE, + nv_index: TPM_HANDLE, + nv_index_name: Vec, + operand_b: Vec, + offset: u16, + operation: TPM_EO, + ) -> Self { + Self { operand_b, offset, operation, nv_index_name, auth_handle, nv_index } + } +} + +impl PolicyAssertion for PolicyNv { + fn update_policy_digest(&self, hash_alg: TPM_ALG_ID, acc: &mut Vec) -> Result<(), TpmError> { + // arg2 = H(operandB || offset || operation) + let mut inner = Vec::new(); + inner.extend_from_slice(&self.operand_b); + inner.extend_from_slice(&self.offset.to_be_bytes()); + inner.extend_from_slice(&(self.operation.get_value() as u16).to_be_bytes()); + let args_hash = Crypto::hash(hash_alg, &inner)?; + policy_update(hash_alg, acc, TPM_CC::PolicyNV, &args_hash, &self.nv_index_name) + } + + fn execute(&self, tpm: &mut Tpm2, session: &Session) -> Result { + tpm.PolicyNV( + &self.auth_handle, &self.nv_index, &sess_handle(session), + &self.operand_b, self.offset, self.operation, + )?; + Ok(tpm.last_session().unwrap_or_else(|| session.clone())) + } +} + +/// PolicyOR - allows one of several policy branches to satisfy the policy. +pub struct PolicyOr { + pub branches: Vec>>, +} + +impl PolicyOr { + /// Create from pre-built branches (each branch is a Vec of boxed assertions). + pub fn new(branches: Vec>>) -> Self { + Self { branches } + } + + /// Convenience: create a two-branch PolicyOR from PolicyTrees. + pub fn from_trees(trees: Vec) -> Self { + let branches = trees.into_iter() + .map(|t| t.assertions) + .collect(); + Self { branches } + } +} + +impl PolicyAssertion for PolicyOr { + fn update_policy_digest(&self, hash_alg: TPM_ALG_ID, acc: &mut Vec) -> Result<(), TpmError> { + // PolicyOR: accumulator = H(0...0 || TPM_CC_PolicyOR || digest1 || digest2 || ...) + let hash_len = Crypto::hash(hash_alg, &[])?.len(); + let mut buf = Vec::new(); + buf.extend_from_slice(&vec![0u8; hash_len]); // reset to zero + buf.extend_from_slice(&TPM_CC::PolicyOR.get_value().to_be_bytes()); + for branch in &self.branches { + let branch_digest = compute_digest(branch, hash_alg)?; + buf.extend_from_slice(&branch_digest); + } + *acc = Crypto::hash(hash_alg, &buf)?; + Ok(()) + } + + fn execute(&self, tpm: &mut Tpm2, session: &Session) -> Result { + let hash_alg = session.get_hash_alg(); + let mut hash_list: Vec = Vec::new(); + for branch in &self.branches { + let digest = compute_digest(branch, hash_alg)?; + hash_list.push(TPM2B_DIGEST { buffer: digest }); + } + tpm.PolicyOR(&sess_handle(session), &hash_list)?; + Ok(tpm.last_session().unwrap_or_else(|| session.clone())) + } +} + +/// PolicyAuthorize - transforms a policy digest using a signing key's authorization. +pub struct PolicyAuthorize { + pub approved_policy: Vec, + pub policy_ref: Vec, + pub authorizing_key: TPMT_PUBLIC, + pub signature: TPMT_SIGNATURE, +} + +impl PolicyAuthorize { + pub fn new( + approved_policy: Vec, + policy_ref: Vec, + authorizing_key: TPMT_PUBLIC, + signature: TPMT_SIGNATURE, + ) -> Self { + Self { approved_policy, policy_ref, authorizing_key, signature } + } +} + +impl PolicyAssertion for PolicyAuthorize { + fn update_policy_digest(&self, hash_alg: TPM_ALG_ID, acc: &mut Vec) -> Result<(), TpmError> { + let key_name = self.authorizing_key.get_name()?; + // PolicyAuthorize resets the digest, then does PolicyUpdate + let hash_len = Crypto::hash(hash_alg, &[])?.len(); + *acc = vec![0u8; hash_len]; + policy_update(hash_alg, acc, TPM_CC::PolicyAuthorize, &key_name, &self.policy_ref) + } + + fn execute(&self, tpm: &mut Tpm2, session: &Session) -> Result { + let key_name = self.authorizing_key.get_name()?; + + // Load the authorizing key (OWNER hierarchy for valid tickets) + let key_handle = tpm.LoadExternal( + &TPMT_SENSITIVE::default(), + &self.authorizing_key, + &TPM_HANDLE::new(TPM_RH::OWNER.get_value()), + )?; + + // Compute aHash and get a verification ticket + let mut a_hash_data = Vec::new(); + a_hash_data.extend_from_slice(&self.approved_policy); + a_hash_data.extend_from_slice(&self.policy_ref); + let a_hash = Crypto::hash(self.authorizing_key.nameAlg, &a_hash_data)?; + + let check_ticket = tpm.VerifySignature( + &key_handle, &a_hash, &self.signature.signature, + )?; + + let result = tpm.PolicyAuthorize( + &sess_handle(session), + &self.approved_policy, + &self.policy_ref, + &key_name, + &check_ticket, + ); + + tpm.FlushContext(&key_handle)?; + result?; + Ok(tpm.last_session().unwrap_or_else(|| session.clone())) + } +} + +/// PolicyDuplicationSelect - qualifies duplication to a selected new parent. +pub struct PolicyDuplicationSelect { + pub object_name: Vec, + pub new_parent_name: Vec, + pub include_object: bool, +} + +impl PolicyDuplicationSelect { + pub fn new(object_name: Vec, new_parent_name: Vec, include_object: bool) -> Self { + Self { object_name, new_parent_name, include_object } + } +} + +impl PolicyAssertion for PolicyDuplicationSelect { + fn update_policy_digest(&self, hash_alg: TPM_ALG_ID, acc: &mut Vec) -> Result<(), TpmError> { + let mut arg2 = Vec::new(); + if self.include_object { + arg2.extend_from_slice(&self.object_name); + } + arg2.extend_from_slice(&self.new_parent_name); + arg2.push(if self.include_object { 1 } else { 0 }); + policy_update(hash_alg, acc, TPM_CC::PolicyDuplicationSelect, &arg2, &[]) + } + + fn execute(&self, tpm: &mut Tpm2, session: &Session) -> Result { + tpm.PolicyDuplicationSelect( + &sess_handle(session), + &self.object_name, + &self.new_parent_name, + if self.include_object { 1 } else { 0 }, + )?; + Ok(tpm.last_session().unwrap_or_else(|| session.clone())) + } +} diff --git a/TSS.Rust/src/tpm2.rs b/TSS.Rust/src/tpm2.rs new file mode 100644 index 00000000..5c2b08d7 --- /dev/null +++ b/TSS.Rust/src/tpm2.rs @@ -0,0 +1,7642 @@ +/* + * NOTE: this file is partially auto generated! + * + * All code after the point marked with the '// <>' comment + * is autogenerated from the TPM 2.0 Specification docs. + * + * DO NOT EDIT AUTOGENERATED PART - all manual changes will be lost! + */ + +//! TPM2 command implementations + +#![allow(non_snake_case)] + +use crate::error::TpmError; +use crate::tpm2_impl::*; +use crate::tpm_buffer::TpmBuffer; +use crate::tpm_buffer::TpmMarshaller; +use crate::tpm_structure::*; +use crate::tpm_types::*; + +impl Tpm2 { + pub fn async_methods(&mut self) -> AsyncMethods { + AsyncMethods { tpm: self } + } +} + +#[derive(Debug, Default, Clone)] +struct EmptyTpmResponse {} + +impl TpmMarshaller for EmptyTpmResponse { + fn toTpm(&self, _buf: &mut TpmBuffer) -> Result<(), TpmError> { + Ok(()) + } + + /** Populate this object from the TPM representation in the given marshaling buffer */ + fn initFromTpm(&mut self, _buf: &mut TpmBuffer) -> Result<(), TpmError> { + Ok(()) + } +} + +impl TpmStructure for EmptyTpmResponse { + fn serialize(&self, _buffer: &mut TpmBuffer) -> Result<(), TpmError> { + Ok(()) + } + + fn deserialize(&mut self, _buffer: &mut TpmBuffer) -> Result<(), TpmError> { + Ok(()) + } + + fn fromTpm(&self, _buffer: &mut TpmBuffer) -> Result<(), TpmError> { + Ok(()) + } + + fn fromBytes(&mut self, _buffer: &mut Vec) -> Result<(), TpmError> { + Ok(()) + } +} + +impl CmdStructure for EmptyTpmResponse {} + +impl RespStructure for EmptyTpmResponse { + fn get_handle(&self) -> TPM_HANDLE { + TPM_HANDLE::default() + } +} + +// <> +// ------------------------------------------------------------------------------------------------ +// DO NOT REMOVE the <> comment! +// DO NOT MODIFY any code below this point - all manual changes will be lost! +// ------------------------------------------------------------------------------------------------ + +impl Tpm2 { + /// TPM2_Startup() is always preceded by _TPM_Init, which is the physical indication that TPM + /// initialization is necessary because of a system-wide reset. TPM2_Startup() is only valid + /// after _TPM_Init. Additional TPM2_Startup() commands are not allowed after it has completed + /// successfully. If a TPM requires TPM2_Startup() and another command is received, or if the + /// TPM receives TPM2_Startup() when it is not required, the TPM shall return TPM_RC_INITIALIZE. + /// startupType: TPM_SU_CLEAR or TPM_SU_STATE + pub fn Startup( + &mut self, + startupType: TPM_SU, + ) -> Result<(), TpmError> { + let req = TPM2_Startup_REQUEST::new( + startupType, + ); + + let mut resp = EmptyTpmResponse::default(); + self.dispatch(TPM_CC::Startup, req, &mut resp)?; + Ok(()) + } + + /// This command is used to prepare the TPM for a power cycle. The shutdownType parameter + /// indicates how the subsequent TPM2_Startup() will be processed. + /// shutdownType: TPM_SU_CLEAR or TPM_SU_STATE + pub fn Shutdown( + &mut self, + shutdownType: TPM_SU, + ) -> Result<(), TpmError> { + let req = TPM2_Shutdown_REQUEST::new( + shutdownType, + ); + + let mut resp = EmptyTpmResponse::default(); + self.dispatch(TPM_CC::Shutdown, req, &mut resp)?; + Ok(()) + } + + /// This command causes the TPM to perform a test of its capabilities. If the fullTest is YES, + /// the TPM will test all functions. If fullTest = NO, the TPM will only test those functions + /// that have not previously been tested. + /// fullTest: YES if full test to be performed + /// NO if only test of untested functions required + pub fn SelfTest( + &mut self, + fullTest: u8, + ) -> Result<(), TpmError> { + let req = TPM2_SelfTest_REQUEST::new( + fullTest, + ); + + let mut resp = EmptyTpmResponse::default(); + self.dispatch(TPM_CC::SelfTest, req, &mut resp)?; + Ok(()) + } + + /// This command causes the TPM to perform a test of the selected algorithms. + /// toTest: List of algorithms that should be tested + /// toDoList - List of algorithms that need testing + pub fn IncrementalSelfTest( + &mut self, + toTest: &Vec, + ) -> Result, TpmError> { + let req = TPM2_IncrementalSelfTest_REQUEST::new( + toTest, + ); + + let mut resp = IncrementalSelfTestResponse::default(); + self.dispatch(TPM_CC::IncrementalSelfTest, req, &mut resp)?; + Ok(resp.toDoList) + } + + /// This command returns manufacturer-specific information regarding the results of a + /// self-test and an indication of the test status. + /// outData - Test result data + /// contains manufacturer-specific information + /// testResult - TBD + pub fn GetTestResult( + &mut self, + ) -> Result { + let req = TPM2_GetTestResult_REQUEST::default(); + + let mut resp = GetTestResultResponse::default(); + self.dispatch(TPM_CC::GetTestResult, req, &mut resp)?; + Ok(resp) + } + + /// This command is used to start an authorization session using alternative methods of + /// establishing the session key (sessionKey). The session key is then used to derive values + /// used for authorization and for encrypting parameters. + /// tpmKey: Handle of a loaded decrypt key used to encrypt salt + /// may be TPM_RH_NULL + /// Auth Index: None + /// bind: Entity providing the authValue + /// may be TPM_RH_NULL + /// Auth Index: None + /// nonceCaller: Initial nonceCaller, sets nonceTPM size for the session + /// shall be at least 16 octets + /// encryptedSalt: Value encrypted according to the type of tpmKey + /// If tpmKey is TPM_RH_NULL, this shall be the Empty Buffer. + /// sessionType: Indicates the type of the session; simple HMAC or policy (including a trial policy) + /// symmetric: The algorithm and key size for parameter encryption + /// may select TPM_ALG_NULL + /// authHash: Hash algorithm to use for the session + /// Shall be a hash algorithm supported by the TPM and not TPM_ALG_NULL + /// handle - Handle for the newly created session + /// nonceTPM - The initial nonce from the TPM, used in the computation of the sessionKey + pub fn StartAuthSession( + &mut self, + tpmKey: &TPM_HANDLE, + bind: &TPM_HANDLE, + nonceCaller: &Vec, + encryptedSalt: &Vec, + sessionType: TPM_SE, + symmetric: &TPMT_SYM_DEF, + authHash: TPM_ALG_ID, + ) -> Result { + let req = TPM2_StartAuthSession_REQUEST::new( + tpmKey, + bind, + nonceCaller, + encryptedSalt, + sessionType, + symmetric, + authHash, + ); + + let mut resp = StartAuthSessionResponse::default(); + self.dispatch(TPM_CC::StartAuthSession, req, &mut resp)?; + Ok(resp) + } + + /// This command allows a policy authorization session to be returned to its initial state. + /// This command is used after the TPM returns TPM_RC_PCR_CHANGED. That response code + /// indicates that a policy will fail because the PCR have changed after TPM2_PolicyPCR() was + /// executed. Restarting the session allows the authorizations to be replayed because the + /// session restarts with the same nonceTPM. If the PCR are valid for the policy, the policy + /// may then succeed. + /// sessionHandle: The handle for the policy session + pub fn PolicyRestart( + &mut self, + sessionHandle: &TPM_HANDLE, + ) -> Result<(), TpmError> { + let req = TPM2_PolicyRestart_REQUEST::new( + sessionHandle, + ); + + let mut resp = EmptyTpmResponse::default(); + self.dispatch(TPM_CC::PolicyRestart, req, &mut resp)?; + Ok(()) + } + + /// This command is used to create an object that can be loaded into a TPM using TPM2_Load(). + /// If the command completes successfully, the TPM will create the new object and return the + /// objects creation data (creationData), its public area (outPublic), and its encrypted + /// sensitive area (outPrivate). Preservation of the returned data is the responsibility of + /// the caller. The object will need to be loaded (TPM2_Load()) before it may be used. The + /// only difference between the inPublic TPMT_PUBLIC template and the outPublic TPMT_PUBLIC + /// object is in the unique field. + /// parentHandle: Handle of parent for new object + /// Auth Index: 1 + /// Auth Role: USER + /// inSensitive: The sensitive data + /// inPublic: The public template + /// outsideInfo: Data that will be included in the creation data for this object to provide + /// permanent, verifiable linkage between this object and some object owner data + /// creationPCR: PCR that will be used in creation data + /// outPrivate - The private portion of the object + /// outPublic - The public portion of the created object + /// creationData - Contains a TPMS_CREATION_DATA + /// creationHash - Digest of creationData using nameAlg of outPublic + /// creationTicket - Ticket used by TPM2_CertifyCreation() to validate that the creation + /// data was produced by the TPM + pub fn Create( + &mut self, + parentHandle: &TPM_HANDLE, + inSensitive: &TPMS_SENSITIVE_CREATE, + inPublic: &TPMT_PUBLIC, + outsideInfo: &Vec, + creationPCR: &Vec, + ) -> Result { + let req = TPM2_Create_REQUEST::new( + parentHandle, + inSensitive, + inPublic, + outsideInfo, + creationPCR, + ); + + let mut resp = CreateResponse::default(); + self.dispatch(TPM_CC::Create, req, &mut resp)?; + Ok(resp) + } + + /// This command is used to load objects into the TPM. This command is used when both a + /// TPM2B_PUBLIC and TPM2B_PRIVATE are to be loaded. If only a TPM2B_PUBLIC is to be loaded, + /// the TPM2_LoadExternal command is used. + /// parentHandle: TPM handle of parent key; shall not be a reserved handle + /// Auth Index: 1 + /// Auth Role: USER + /// inPrivate: The private portion of the object + /// inPublic: The public portion of the object + /// handle - Handle of type TPM_HT_TRANSIENT for the loaded object + /// name - Name of the loaded object + pub fn Load( + &mut self, + parentHandle: &TPM_HANDLE, + inPrivate: &TPM2B_PRIVATE, + inPublic: &TPMT_PUBLIC, + ) -> Result { + let req = TPM2_Load_REQUEST::new( + parentHandle, + inPrivate, + inPublic, + ); + + let mut resp = LoadResponse::default(); + self.dispatch(TPM_CC::Load, req, &mut resp)?; + Ok(resp.handle) + } + + /// This command is used to load an object that is not a Protected Object into the TPM. The + /// command allows loading of a public area or both a public and sensitive area. + /// inPrivate: The sensitive portion of the object (optional) + /// inPublic: The public portion of the object + /// hierarchy: Hierarchy with which the object area is associated + /// handle - Handle of type TPM_HT_TRANSIENT for the loaded object + /// name - Name of the loaded object + pub fn LoadExternal( + &mut self, + inPrivate: &TPMT_SENSITIVE, + inPublic: &TPMT_PUBLIC, + hierarchy: &TPM_HANDLE, + ) -> Result { + let req = TPM2_LoadExternal_REQUEST::new( + inPrivate, + inPublic, + hierarchy, + ); + + let mut resp = LoadExternalResponse::default(); + self.dispatch(TPM_CC::LoadExternal, req, &mut resp)?; + Ok(resp.handle) + } + + /// This command allows access to the public area of a loaded object. + /// objectHandle: TPM handle of an object + /// Auth Index: None + /// outPublic - Structure containing the public area of an object + /// name - Name of the object + /// qualifiedName - The Qualified Name of the object + pub fn ReadPublic( + &mut self, + objectHandle: &TPM_HANDLE, + ) -> Result { + let req = TPM2_ReadPublic_REQUEST::new( + objectHandle, + ); + + let mut resp = ReadPublicResponse::default(); + self.dispatch(TPM_CC::ReadPublic, req, &mut resp)?; + Ok(resp) + } + + /// This command enables the association of a credential with an object in a way that ensures + /// that the TPM has validated the parameters of the credentialed object. + /// activateHandle: Handle of the object associated with certificate in credentialBlob + /// Auth Index: 1 + /// Auth Role: ADMIN + /// keyHandle: Loaded key used to decrypt the TPMS_SENSITIVE in credentialBlob + /// Auth Index: 2 + /// Auth Role: USER + /// credentialBlob: The credential + /// secret: KeyHandle algorithm-dependent encrypted seed that protects credentialBlob + /// certInfo - The decrypted certificate information + /// the data should be no larger than the size of the digest of the nameAlg + /// associated with keyHandle + pub fn ActivateCredential( + &mut self, + activateHandle: &TPM_HANDLE, + keyHandle: &TPM_HANDLE, + credentialBlob: &TPMS_ID_OBJECT, + secret: &Vec, + ) -> Result, TpmError> { + let req = TPM2_ActivateCredential_REQUEST::new( + activateHandle, + keyHandle, + credentialBlob, + secret, + ); + + let mut resp = ActivateCredentialResponse::default(); + self.dispatch(TPM_CC::ActivateCredential, req, &mut resp)?; + Ok(resp.certInfo) + } + + /// This command allows the TPM to perform the actions required of a Certificate Authority + /// (CA) in creating a TPM2B_ID_OBJECT containing an activation credential. + /// handle: Loaded public area, used to encrypt the sensitive area containing the credential key + /// Auth Index: None + /// credential: The credential information + /// objectName: Name of the object to which the credential applies + /// credentialBlob - The credential + /// secret - Handle algorithm-dependent data that wraps the key that encrypts credentialBlob + pub fn MakeCredential( + &mut self, + handle: &TPM_HANDLE, + credential: &Vec, + objectName: &Vec, + ) -> Result { + let req = TPM2_MakeCredential_REQUEST::new( + handle, + credential, + objectName, + ); + + let mut resp = MakeCredentialResponse::default(); + self.dispatch(TPM_CC::MakeCredential, req, &mut resp)?; + Ok(resp) + } + + /// This command returns the data in a loaded Sealed Data Object. + /// itemHandle: Handle of a loaded data object + /// Auth Index: 1 + /// Auth Role: USER + /// outData - Unsealed data + /// Size of outData is limited to be no more than 128 octets. + pub fn Unseal( + &mut self, + itemHandle: &TPM_HANDLE, + ) -> Result, TpmError> { + let req = TPM2_Unseal_REQUEST::new( + itemHandle, + ); + + let mut resp = UnsealResponse::default(); + self.dispatch(TPM_CC::Unseal, req, &mut resp)?; + Ok(resp.outData) + } + + /// This command is used to change the authorization secret for a TPM-resident object. + /// objectHandle: Handle of the object + /// Auth Index: 1 + /// Auth Role: ADMIN + /// parentHandle: Handle of the parent + /// Auth Index: None + /// newAuth: New authorization value + /// outPrivate - Private area containing the new authorization value + pub fn ObjectChangeAuth( + &mut self, + objectHandle: &TPM_HANDLE, + parentHandle: &TPM_HANDLE, + newAuth: &Vec, + ) -> Result { + let req = TPM2_ObjectChangeAuth_REQUEST::new( + objectHandle, + parentHandle, + newAuth, + ); + + let mut resp = ObjectChangeAuthResponse::default(); + self.dispatch(TPM_CC::ObjectChangeAuth, req, &mut resp)?; + Ok(resp.outPrivate) + } + + /// This command creates an object and loads it in the TPM. This command allows creation of + /// any type of object (Primary, Ordinary, or Derived) depending on the type of parentHandle. + /// If parentHandle references a Primary Seed, then a Primary Object is created; if + /// parentHandle references a Storage Parent, then an Ordinary Object is created; and if + /// parentHandle references a Derivation Parent, then a Derived Object is generated. + /// parentHandle: Handle of a transient storage key, a persistent storage key, + /// TPM_RH_ENDORSEMENT, TPM_RH_OWNER, TPM_RH_PLATFORM+{PP}, or TPM_RH_NULL + /// Auth Index: 1 + /// Auth Role: USER + /// inSensitive: The sensitive data, see TPM 2.0 Part 1 Sensitive Values + /// inPublic: The public template + /// handle - Handle of type TPM_HT_TRANSIENT for created object + /// outPrivate - The sensitive area of the object (optional) + /// outPublic - The public portion of the created object + /// name - The name of the created object + pub fn CreateLoaded( + &mut self, + parentHandle: &TPM_HANDLE, + inSensitive: &TPMS_SENSITIVE_CREATE, + inPublic: &Vec, + ) -> Result { + let req = TPM2_CreateLoaded_REQUEST::new( + parentHandle, + inSensitive, + inPublic, + ); + + let mut resp = CreateLoadedResponse::default(); + self.dispatch(TPM_CC::CreateLoaded, req, &mut resp)?; + Ok(resp) + } + + /// This command duplicates a loaded object so that it may be used in a different hierarchy. + /// The new parent key for the duplicate may be on the same or different TPM or TPM_RH_NULL. + /// Only the public area of newParentHandle is required to be loaded. + /// objectHandle: Loaded object to duplicate + /// Auth Index: 1 + /// Auth Role: DUP + /// newParentHandle: Shall reference the public area of an asymmetric key + /// Auth Index: None + /// encryptionKeyIn: Optional symmetric encryption key + /// The size for this key is set to zero when the TPM is to generate the key. This + /// parameter may be encrypted. + /// symmetricAlg: Definition for the symmetric algorithm to be used for the inner wrapper + /// may be TPM_ALG_NULL if no inner wrapper is applied + /// encryptionKeyOut - If the caller provided an encryption key or if symmetricAlg was + /// TPM_ALG_NULL, then this will be the Empty Buffer; otherwise, it + /// shall contain the TPM-generated, symmetric encryption key for the + /// inner wrapper. + /// duplicate - Private area that may be encrypted by encryptionKeyIn; and may be doubly encrypted + /// outSymSeed - Seed protected by the asymmetric algorithms of new parent (NP) + pub fn Duplicate( + &mut self, + objectHandle: &TPM_HANDLE, + newParentHandle: &TPM_HANDLE, + encryptionKeyIn: &Vec, + symmetricAlg: &TPMT_SYM_DEF_OBJECT, + ) -> Result { + let req = TPM2_Duplicate_REQUEST::new( + objectHandle, + newParentHandle, + encryptionKeyIn, + symmetricAlg, + ); + + let mut resp = DuplicateResponse::default(); + self.dispatch(TPM_CC::Duplicate, req, &mut resp)?; + Ok(resp) + } + + /// This command allows the TPM to serve in the role as a Duplication Authority. If proper + /// authorization for use of the oldParent is provided, then an HMAC key and a symmetric key + /// are recovered from inSymSeed and used to integrity check and decrypt inDuplicate. A new + /// protection seed value is generated according to the methods appropriate for newParent and + /// the blob is re-encrypted and a new integrity value is computed. The re-encrypted blob is + /// returned in outDuplicate and the symmetric key returned in outSymKey. + /// oldParent: Parent of object + /// Auth Index: 1 + /// Auth Role: User + /// newParent: New parent of the object + /// Auth Index: None + /// inDuplicate: An object encrypted using symmetric key derived from inSymSeed + /// name: The Name of the object being rewrapped + /// inSymSeed: The seed for the symmetric key and HMAC key + /// needs oldParent private key to recover the seed and generate the symmetric key + /// outDuplicate - An object encrypted using symmetric key derived from outSymSeed + /// outSymSeed - Seed for a symmetric key protected by newParent asymmetric key + pub fn Rewrap( + &mut self, + oldParent: &TPM_HANDLE, + newParent: &TPM_HANDLE, + inDuplicate: &TPM2B_PRIVATE, + name: &Vec, + inSymSeed: &Vec, + ) -> Result { + let req = TPM2_Rewrap_REQUEST::new( + oldParent, + newParent, + inDuplicate, + name, + inSymSeed, + ); + + let mut resp = RewrapResponse::default(); + self.dispatch(TPM_CC::Rewrap, req, &mut resp)?; + Ok(resp) + } + + /// This command allows an object to be encrypted using the symmetric encryption values of a + /// Storage Key. After encryption, the object may be loaded and used in the new hierarchy. The + /// imported object (duplicate) may be singly encrypted, multiply encrypted, or unencrypted. + /// parentHandle: The handle of the new parent for the object + /// Auth Index: 1 + /// Auth Role: USER + /// encryptionKey: The optional symmetric encryption key used as the inner wrapper for duplicate + /// If symmetricAlg is TPM_ALG_NULL, then this parameter shall be the Empty Buffer. + /// objectPublic: The public area of the object to be imported + /// This is provided so that the integrity value for duplicate and the object + /// attributes can be checked. + /// NOTE Even if the integrity value of the object is not checked on input, the object + /// Name is required to create the integrity value for the imported object. + /// duplicate: The symmetrically encrypted duplicate object that may contain an inner + /// symmetric wrapper + /// inSymSeed: The seed for the symmetric key and HMAC key + /// inSymSeed is encrypted/encoded using the algorithms of newParent. + /// symmetricAlg: Definition for the symmetric algorithm to use for the inner wrapper + /// If this algorithm is TPM_ALG_NULL, no inner wrapper is present and encryptionKey + /// shall be the Empty Buffer. + /// outPrivate - The sensitive area encrypted with the symmetric key of parentHandle + pub fn Import( + &mut self, + parentHandle: &TPM_HANDLE, + encryptionKey: &Vec, + objectPublic: &TPMT_PUBLIC, + duplicate: &TPM2B_PRIVATE, + inSymSeed: &Vec, + symmetricAlg: &TPMT_SYM_DEF_OBJECT, + ) -> Result { + let req = TPM2_Import_REQUEST::new( + parentHandle, + encryptionKey, + objectPublic, + duplicate, + inSymSeed, + symmetricAlg, + ); + + let mut resp = ImportResponse::default(); + self.dispatch(TPM_CC::Import, req, &mut resp)?; + Ok(resp.outPrivate) + } + + /// This command performs RSA encryption using the indicated padding scheme according to IETF + /// RFC 8017. If the scheme of keyHandle is TPM_ALG_NULL, then the caller may use inScheme to + /// specify the padding scheme. If scheme of keyHandle is not TPM_ALG_NULL, then inScheme + /// shall either be TPM_ALG_NULL or be the same as scheme (TPM_RC_SCHEME). + /// keyHandle: Reference to public portion of RSA key to use for encryption + /// Auth Index: None + /// message: Message to be encrypted + /// NOTE 1 The data type was chosen because it limits the overall size of the input to + /// no greater than the size of the largest RSA public key. This may be larger than + /// allowed for keyHandle. + /// inScheme: The padding scheme to use if scheme associated with keyHandle is TPM_ALG_NULL + /// One of: TPMS_KEY_SCHEME_ECDH, TPMS_KEY_SCHEME_ECMQV, TPMS_SIG_SCHEME_RSASSA, + /// TPMS_SIG_SCHEME_RSAPSS, TPMS_SIG_SCHEME_ECDSA, TPMS_SIG_SCHEME_ECDAA, + /// TPMS_SIG_SCHEME_SM2, TPMS_SIG_SCHEME_ECSCHNORR, TPMS_ENC_SCHEME_RSAES, + /// TPMS_ENC_SCHEME_OAEP, TPMS_SCHEME_HASH, TPMS_NULL_ASYM_SCHEME. + /// label: Optional label L to be associated with the message + /// Size of the buffer is zero if no label is present + /// NOTE 2 See description of label above. + /// outData - Encrypted output + pub fn RSA_Encrypt( + &mut self, + keyHandle: &TPM_HANDLE, + message: &Vec, + inScheme: &Option, + label: &Vec, + ) -> Result, TpmError> { + let req = TPM2_RSA_Encrypt_REQUEST::new( + keyHandle, + message, + inScheme, + label, + ); + + let mut resp = RSA_EncryptResponse::default(); + self.dispatch(TPM_CC::RSA_Encrypt, req, &mut resp)?; + Ok(resp.outData) + } + + /// This command performs RSA decryption using the indicated padding scheme according to IETF + /// RFC 8017 ((PKCS#1). + /// keyHandle: RSA key to use for decryption + /// Auth Index: 1 + /// Auth Role: USER + /// cipherText: Cipher text to be decrypted + /// NOTE An encrypted RSA data block is the size of the public modulus. + /// inScheme: The padding scheme to use if scheme associated with keyHandle is TPM_ALG_NULL + /// One of: TPMS_KEY_SCHEME_ECDH, TPMS_KEY_SCHEME_ECMQV, TPMS_SIG_SCHEME_RSASSA, + /// TPMS_SIG_SCHEME_RSAPSS, TPMS_SIG_SCHEME_ECDSA, TPMS_SIG_SCHEME_ECDAA, + /// TPMS_SIG_SCHEME_SM2, TPMS_SIG_SCHEME_ECSCHNORR, TPMS_ENC_SCHEME_RSAES, + /// TPMS_ENC_SCHEME_OAEP, TPMS_SCHEME_HASH, TPMS_NULL_ASYM_SCHEME. + /// label: Label whose association with the message is to be verified + /// message - Decrypted output + pub fn RSA_Decrypt( + &mut self, + keyHandle: &TPM_HANDLE, + cipherText: &Vec, + inScheme: &Option, + label: &Vec, + ) -> Result, TpmError> { + let req = TPM2_RSA_Decrypt_REQUEST::new( + keyHandle, + cipherText, + inScheme, + label, + ); + + let mut resp = RSA_DecryptResponse::default(); + self.dispatch(TPM_CC::RSA_Decrypt, req, &mut resp)?; + Ok(resp.message) + } + + /// This command uses the TPM to generate an ephemeral key pair (de, Qe where Qe [de]G). It + /// uses the private ephemeral key and a loaded public key (QS) to compute the shared secret + /// value (P [hde]QS). + /// keyHandle: Handle of a loaded ECC key public area. + /// Auth Index: None + /// zPoint - Results of P h[de]Qs + /// pubPoint - Generated ephemeral public point (Qe) + pub fn ECDH_KeyGen( + &mut self, + keyHandle: &TPM_HANDLE, + ) -> Result { + let req = TPM2_ECDH_KeyGen_REQUEST::new( + keyHandle, + ); + + let mut resp = ECDH_KeyGenResponse::default(); + self.dispatch(TPM_CC::ECDH_KeyGen, req, &mut resp)?; + Ok(resp) + } + + /// This command uses the TPM to recover the Z value from a public point (QB) and a private + /// key (ds). It will perform the multiplication of the provided inPoint (QB) with the private + /// key (ds) and return the coordinates of the resultant point (Z = (xZ , yZ) [hds]QB; where h + /// is the cofactor of the curve). + /// keyHandle: Handle of a loaded ECC key + /// Auth Index: 1 + /// Auth Role: USER + /// inPoint: A public key + /// outPoint - X and Y coordinates of the product of the multiplication Z = (xZ , yZ) [hdS]QB + pub fn ECDH_ZGen( + &mut self, + keyHandle: &TPM_HANDLE, + inPoint: &TPMS_ECC_POINT, + ) -> Result { + let req = TPM2_ECDH_ZGen_REQUEST::new( + keyHandle, + inPoint, + ); + + let mut resp = ECDH_ZGenResponse::default(); + self.dispatch(TPM_CC::ECDH_ZGen, req, &mut resp)?; + Ok(resp.outPoint) + } + + /// This command returns the parameters of an ECC curve identified by its TCG-assigned curveID. + /// curveID: Parameter set selector + /// parameters - ECC parameters for the selected curve + pub fn ECC_Parameters( + &mut self, + curveID: TPM_ECC_CURVE, + ) -> Result { + let req = TPM2_ECC_Parameters_REQUEST::new( + curveID, + ); + + let mut resp = ECC_ParametersResponse::default(); + self.dispatch(TPM_CC::ECC_Parameters, req, &mut resp)?; + Ok(resp.parameters) + } + + /// This command supports two-phase key exchange protocols. The command is used in combination + /// with TPM2_EC_Ephemeral(). TPM2_EC_Ephemeral() generates an ephemeral key and returns the + /// public point of that ephemeral key along with a numeric value that allows the TPM to + /// regenerate the associated private key. + /// keyA: Handle of an unrestricted decryption key ECC + /// The private key referenced by this handle is used as dS,A + /// Auth Index: 1 + /// Auth Role: USER + /// inQsB: Other partys static public key (Qs,B = (Xs,B, Ys,B)) + /// inQeB: Other party's ephemeral public key (Qe,B = (Xe,B, Ye,B)) + /// inScheme: The key exchange scheme + /// counter: Value returned by TPM2_EC_Ephemeral() + /// outZ1 - X and Y coordinates of the computed value (scheme dependent) + /// outZ2 - X and Y coordinates of the second computed value (scheme dependent) + pub fn ZGen_2Phase( + &mut self, + keyA: &TPM_HANDLE, + inQsB: &TPMS_ECC_POINT, + inQeB: &TPMS_ECC_POINT, + inScheme: TPM_ALG_ID, + counter: u16, + ) -> Result { + let req = TPM2_ZGen_2Phase_REQUEST::new( + keyA, + inQsB, + inQeB, + inScheme, + counter, + ); + + let mut resp = ZGen_2PhaseResponse::default(); + self.dispatch(TPM_CC::ZGen_2Phase, req, &mut resp)?; + Ok(resp) + } + + /// This command performs ECC encryption as described in Part 1, Annex D. + /// keyHandle: Reference to public portion of ECC key to use for encryption + /// Auth Index: None + /// plainText: Plaintext to be encrypted + /// inScheme: The KDF to use if scheme associated with keyHandle is TPM_ALG_NULL + /// One of: TPMS_KDF_SCHEME_MGF1, TPMS_KDF_SCHEME_KDF1_SP800_56A, TPMS_KDF_SCHEME_KDF2, + /// TPMS_KDF_SCHEME_KDF1_SP800_108, TPMS_SCHEME_HASH, TPMS_NULL_KDF_SCHEME. + /// C1 - The public ephemeral key used for ECDH + /// C2 - The data block produced by the XOR process + /// C3 - The integrity value + pub fn ECC_Encrypt( + &mut self, + keyHandle: &TPM_HANDLE, + plainText: &Vec, + inScheme: &Option, + ) -> Result { + let req = TPM2_ECC_Encrypt_REQUEST::new( + keyHandle, + plainText, + inScheme, + ); + + let mut resp = ECC_EncryptResponse::default(); + self.dispatch(TPM_CC::ECC_Encrypt, req, &mut resp)?; + Ok(resp) + } + + /// This command performs ECC decryption. + /// keyHandle: ECC key to use for decryption + /// Auth Index: 1 + /// Auth Role: USER + /// C1: The public ephemeral key used for ECDH + /// C2: The data block produced by the XOR process + /// C3: The integrity value + /// inScheme: The KDF to use if scheme associated with keyHandle is TPM_ALG_NULL + /// One of: TPMS_KDF_SCHEME_MGF1, TPMS_KDF_SCHEME_KDF1_SP800_56A, TPMS_KDF_SCHEME_KDF2, + /// TPMS_KDF_SCHEME_KDF1_SP800_108, TPMS_SCHEME_HASH, TPMS_NULL_KDF_SCHEME. + /// plainText - Decrypted output + pub fn ECC_Decrypt( + &mut self, + keyHandle: &TPM_HANDLE, + C1: &TPMS_ECC_POINT, + C2: &Vec, + C3: &Vec, + inScheme: &Option, + ) -> Result, TpmError> { + let req = TPM2_ECC_Decrypt_REQUEST::new( + keyHandle, + C1, + C2, + C3, + inScheme, + ); + + let mut resp = ECC_DecryptResponse::default(); + self.dispatch(TPM_CC::ECC_Decrypt, req, &mut resp)?; + Ok(resp.plainText) + } + + /// NOTE 1 This command is deprecated, and TPM2_EncryptDecrypt2() is preferred. This should be + /// reflected in platform-specific specifications. + /// keyHandle: The symmetric key used for the operation + /// Auth Index: 1 + /// Auth Role: USER + /// decrypt: If YES, then the operation is decryption; if NO, the operation is encryption + /// mode: Symmetric encryption/decryption mode + /// this field shall match the default mode of the key or be TPM_ALG_NULL. + /// ivIn: An initial value as required by the algorithm + /// inData: The data to be encrypted/decrypted + /// outData - Encrypted or decrypted output + /// ivOut - Chaining value to use for IV in next round + pub fn EncryptDecrypt( + &mut self, + keyHandle: &TPM_HANDLE, + decrypt: u8, + mode: TPM_ALG_ID, + ivIn: &Vec, + inData: &Vec, + ) -> Result { + let req = TPM2_EncryptDecrypt_REQUEST::new( + keyHandle, + decrypt, + mode, + ivIn, + inData, + ); + + let mut resp = EncryptDecryptResponse::default(); + self.dispatch(TPM_CC::EncryptDecrypt, req, &mut resp)?; + Ok(resp) + } + + /// This command is identical to TPM2_EncryptDecrypt(), except that the inData parameter is + /// the first parameter. This permits inData to be parameter encrypted. + /// keyHandle: The symmetric key used for the operation + /// Auth Index: 1 + /// Auth Role: USER + /// inData: The data to be encrypted/decrypted + /// decrypt: If YES, then the operation is decryption; if NO, the operation is encryption + /// mode: Symmetric mode + /// this field shall match the default mode of the key or be TPM_ALG_NULL. + /// ivIn: An initial value as required by the algorithm + /// outData - Encrypted or decrypted output + /// ivOut - Chaining value to use for IV in next round + pub fn EncryptDecrypt2( + &mut self, + keyHandle: &TPM_HANDLE, + inData: &Vec, + decrypt: u8, + mode: TPM_ALG_ID, + ivIn: &Vec, + ) -> Result { + let req = TPM2_EncryptDecrypt2_REQUEST::new( + keyHandle, + inData, + decrypt, + mode, + ivIn, + ); + + let mut resp = EncryptDecrypt2Response::default(); + self.dispatch(TPM_CC::EncryptDecrypt2, req, &mut resp)?; + Ok(resp) + } + + /// This command performs a hash operation on a data buffer and returns the results. + /// data: Data to be hashed + /// hashAlg: Algorithm for the hash being computed shall not be TPM_ALG_NULL + /// hierarchy: Hierarchy to use for the ticket (TPM_RH_NULL allowed) + /// outHash - Results + /// validation - Ticket indicating that the sequence of octets used to compute outDigest + /// did not start with TPM_GENERATED_VALUE + /// will be a NULL ticket if the digest may not be signed with a restricted key + pub fn Hash( + &mut self, + data: &Vec, + hashAlg: TPM_ALG_ID, + hierarchy: &TPM_HANDLE, + ) -> Result { + let req = TPM2_Hash_REQUEST::new( + data, + hashAlg, + hierarchy, + ); + + let mut resp = HashResponse::default(); + self.dispatch(TPM_CC::Hash, req, &mut resp)?; + Ok(resp) + } + + /// This command performs an HMAC on the supplied data using the indicated hash algorithm. + /// handle: Handle for the symmetric signing key providing the HMAC key + /// Auth Index: 1 + /// Auth Role: USER + /// buffer: HMAC data + /// hashAlg: Algorithm to use for HMAC + /// outHMAC - The returned HMAC in a sized buffer + pub fn HMAC( + &mut self, + handle: &TPM_HANDLE, + buffer: &Vec, + hashAlg: TPM_ALG_ID, + ) -> Result, TpmError> { + let req = TPM2_HMAC_REQUEST::new( + handle, + buffer, + hashAlg, + ); + + let mut resp = HMACResponse::default(); + self.dispatch(TPM_CC::HMAC, req, &mut resp)?; + Ok(resp.outHMAC) + } + + /// This command performs an HMAC or a block cipher MAC on the supplied data using the + /// indicated algorithm. + /// handle: Handle for the symmetric signing key providing the MAC key + /// Auth Index: 1 + /// Auth Role: USER + /// buffer: MAC data + /// inScheme: Algorithm to use for MAC + /// outMAC - The returned MAC in a sized buffer + pub fn MAC( + &mut self, + handle: &TPM_HANDLE, + buffer: &Vec, + inScheme: TPM_ALG_ID, + ) -> Result, TpmError> { + let req = TPM2_MAC_REQUEST::new( + handle, + buffer, + inScheme, + ); + + let mut resp = MACResponse::default(); + self.dispatch(TPM_CC::MAC, req, &mut resp)?; + Ok(resp.outMAC) + } + + /// This command returns the next bytesRequested octets from the random number generator (RNG). + /// bytesRequested: Number of octets to return + /// randomBytes - The random octets + pub fn GetRandom( + &mut self, + bytesRequested: u16, + ) -> Result, TpmError> { + let req = TPM2_GetRandom_REQUEST::new( + bytesRequested, + ); + + let mut resp = GetRandomResponse::default(); + self.dispatch(TPM_CC::GetRandom, req, &mut resp)?; + Ok(resp.randomBytes) + } + + /// This command is used to add "additional information" to the RNG state. + /// inData: Additional information + pub fn StirRandom( + &mut self, + inData: &Vec, + ) -> Result<(), TpmError> { + let req = TPM2_StirRandom_REQUEST::new( + inData, + ); + + let mut resp = EmptyTpmResponse::default(); + self.dispatch(TPM_CC::StirRandom, req, &mut resp)?; + Ok(()) + } + + /// This command starts an HMAC sequence. The TPM will create and initialize an HMAC sequence + /// structure, assign a handle to the sequence, and set the authValue of the sequence object + /// to the value in auth. + /// handle: Handle of an HMAC key + /// Auth Index: 1 + /// Auth Role: USER + /// auth: Authorization value for subsequent use of the sequence + /// hashAlg: The hash algorithm to use for the HMAC + /// handle - A handle to reference the sequence + pub fn HMAC_Start( + &mut self, + handle: &TPM_HANDLE, + auth: &Vec, + hashAlg: TPM_ALG_ID, + ) -> Result { + let req = TPM2_HMAC_Start_REQUEST::new( + handle, + auth, + hashAlg, + ); + + let mut resp = HMAC_StartResponse::default(); + self.dispatch(TPM_CC::HMAC_Start, req, &mut resp)?; + Ok(resp.handle) + } + + /// This command starts a MAC sequence. The TPM will create and initialize a MAC sequence + /// structure, assign a handle to the sequence, and set the authValue of the sequence object + /// to the value in auth. + /// handle: Handle of a MAC key + /// Auth Index: 1 + /// Auth Role: USER + /// auth: Authorization value for subsequent use of the sequence + /// inScheme: The algorithm to use for the MAC + /// handle - A handle to reference the sequence + pub fn MAC_Start( + &mut self, + handle: &TPM_HANDLE, + auth: &Vec, + inScheme: TPM_ALG_ID, + ) -> Result { + let req = TPM2_MAC_Start_REQUEST::new( + handle, + auth, + inScheme, + ); + + let mut resp = MAC_StartResponse::default(); + self.dispatch(TPM_CC::MAC_Start, req, &mut resp)?; + Ok(resp.handle) + } + + /// This command starts a hash or an Event Sequence. If hashAlg is an implemented hash, then a + /// hash sequence is started. If hashAlg is TPM_ALG_NULL, then an Event Sequence is started. + /// If hashAlg is neither an implemented algorithm nor TPM_ALG_NULL, then the TPM shall return + /// TPM_RC_HASH. + /// auth: Authorization value for subsequent use of the sequence + /// hashAlg: The hash algorithm to use for the hash sequence + /// An Event Sequence starts if this is TPM_ALG_NULL. + /// handle - A handle to reference the sequence + pub fn HashSequenceStart( + &mut self, + auth: &Vec, + hashAlg: TPM_ALG_ID, + ) -> Result { + let req = TPM2_HashSequenceStart_REQUEST::new( + auth, + hashAlg, + ); + + let mut resp = HashSequenceStartResponse::default(); + self.dispatch(TPM_CC::HashSequenceStart, req, &mut resp)?; + Ok(resp.handle) + } + + /// This command is used to add data to a hash or HMAC sequence. The amount of data in buffer + /// may be any size up to the limits of the TPM. + /// sequenceHandle: Handle for the sequence object + /// Auth Index: 1 + /// Auth Role: USER + /// buffer: Data to be added to hash + pub fn SequenceUpdate( + &mut self, + sequenceHandle: &TPM_HANDLE, + buffer: &Vec, + ) -> Result<(), TpmError> { + let req = TPM2_SequenceUpdate_REQUEST::new( + sequenceHandle, + buffer, + ); + + let mut resp = EmptyTpmResponse::default(); + self.dispatch(TPM_CC::SequenceUpdate, req, &mut resp)?; + Ok(()) + } + + /// This command adds the last part of data, if any, to a hash/HMAC sequence and returns the result. + /// sequenceHandle: Authorization for the sequence + /// Auth Index: 1 + /// Auth Role: USER + /// buffer: Data to be added to the hash/HMAC + /// hierarchy: Hierarchy of the ticket for a hash + /// result - The returned HMAC or digest in a sized buffer + /// validation - Ticket indicating that the sequence of octets used to compute outDigest + /// did not start with TPM_GENERATED_VALUE + /// This is a NULL Ticket when the sequence is HMAC. + pub fn SequenceComplete( + &mut self, + sequenceHandle: &TPM_HANDLE, + buffer: &Vec, + hierarchy: &TPM_HANDLE, + ) -> Result { + let req = TPM2_SequenceComplete_REQUEST::new( + sequenceHandle, + buffer, + hierarchy, + ); + + let mut resp = SequenceCompleteResponse::default(); + self.dispatch(TPM_CC::SequenceComplete, req, &mut resp)?; + Ok(resp) + } + + /// This command adds the last part of data, if any, to an Event Sequence and returns the + /// result in a digest list. If pcrHandle references a PCR and not TPM_RH_NULL, then the + /// returned digest list is processed in the same manner as the digest list input parameter to + /// TPM2_PCR_Extend(). That is, if a bank contains a PCR associated with pcrHandle, it is + /// extended with the associated digest value from the list. + /// pcrHandle: PCR to be extended with the Event data + /// Auth Index: 1 + /// Auth Role: USER + /// sequenceHandle: Authorization for the sequence + /// Auth Index: 2 + /// Auth Role: USER + /// buffer: Data to be added to the Event + /// results - List of digests computed for the PCR + pub fn EventSequenceComplete( + &mut self, + pcrHandle: &TPM_HANDLE, + sequenceHandle: &TPM_HANDLE, + buffer: &Vec, + ) -> Result, TpmError> { + let req = TPM2_EventSequenceComplete_REQUEST::new( + pcrHandle, + sequenceHandle, + buffer, + ); + + let mut resp = EventSequenceCompleteResponse::default(); + self.dispatch(TPM_CC::EventSequenceComplete, req, &mut resp)?; + Ok(resp.results) + } + + /// The purpose of this command is to prove that an object with a specific Name is loaded in + /// the TPM. By certifying that the object is loaded, the TPM warrants that a public area with + /// a given Name is self-consistent and associated with a valid sensitive area. If a relying + /// party has a public area that has the same Name as a Name certified with this command, then + /// the values in that public area are correct. + /// objectHandle: Handle of the object to be certified + /// Auth Index: 1 + /// Auth Role: ADMIN + /// signHandle: Handle of the key used to sign the attestation structure + /// Auth Index: 2 + /// Auth Role: USER + /// qualifyingData: User provided qualifying data + /// inScheme: Signing scheme to use if the scheme for signHandle is TPM_ALG_NULL + /// One of: TPMS_SIG_SCHEME_RSASSA, TPMS_SIG_SCHEME_RSAPSS, TPMS_SIG_SCHEME_ECDSA, + /// TPMS_SIG_SCHEME_ECDAA, TPMS_SIG_SCHEME_SM2, TPMS_SIG_SCHEME_ECSCHNORR, + /// TPMS_SCHEME_HMAC, TPMS_SCHEME_HASH, TPMS_NULL_SIG_SCHEME. + /// certifyInfo - The structure that was signed + /// signature - The asymmetric signature over certifyInfo using the key referenced by signHandle + pub fn Certify( + &mut self, + objectHandle: &TPM_HANDLE, + signHandle: &TPM_HANDLE, + qualifyingData: &Vec, + inScheme: &Option, + ) -> Result { + let req = TPM2_Certify_REQUEST::new( + objectHandle, + signHandle, + qualifyingData, + inScheme, + ); + + let mut resp = CertifyResponse::default(); + self.dispatch(TPM_CC::Certify, req, &mut resp)?; + Ok(resp) + } + + /// This command is used to prove the association between an object and its creation data. The + /// TPM will validate that the ticket was produced by the TPM and that the ticket validates + /// the association between a loaded public area and the provided hash of the creation data + /// (creationHash). + /// signHandle: Handle of the key that will sign the attestation block + /// Auth Index: 1 + /// Auth Role: USER + /// objectHandle: The object associated with the creation data + /// Auth Index: None + /// qualifyingData: User-provided qualifying data + /// creationHash: Hash of the creation data produced by TPM2_Create() or TPM2_CreatePrimary() + /// inScheme: Signing scheme to use if the scheme for signHandle is TPM_ALG_NULL + /// One of: TPMS_SIG_SCHEME_RSASSA, TPMS_SIG_SCHEME_RSAPSS, TPMS_SIG_SCHEME_ECDSA, + /// TPMS_SIG_SCHEME_ECDAA, TPMS_SIG_SCHEME_SM2, TPMS_SIG_SCHEME_ECSCHNORR, + /// TPMS_SCHEME_HMAC, TPMS_SCHEME_HASH, TPMS_NULL_SIG_SCHEME. + /// creationTicket: Ticket produced by TPM2_Create() or TPM2_CreatePrimary() + /// certifyInfo - The structure that was signed + /// signature - The signature over certifyInfo + pub fn CertifyCreation( + &mut self, + signHandle: &TPM_HANDLE, + objectHandle: &TPM_HANDLE, + qualifyingData: &Vec, + creationHash: &Vec, + inScheme: &Option, + creationTicket: &TPMT_TK_CREATION, + ) -> Result { + let req = TPM2_CertifyCreation_REQUEST::new( + signHandle, + objectHandle, + qualifyingData, + creationHash, + inScheme, + creationTicket, + ); + + let mut resp = CertifyCreationResponse::default(); + self.dispatch(TPM_CC::CertifyCreation, req, &mut resp)?; + Ok(resp) + } + + /// This command is used to quote PCR values. + /// signHandle: Handle of key that will perform signature + /// Auth Index: 1 + /// Auth Role: USER + /// qualifyingData: Data supplied by the caller + /// inScheme: Signing scheme to use if the scheme for signHandle is TPM_ALG_NULL + /// One of: TPMS_SIG_SCHEME_RSASSA, TPMS_SIG_SCHEME_RSAPSS, TPMS_SIG_SCHEME_ECDSA, + /// TPMS_SIG_SCHEME_ECDAA, TPMS_SIG_SCHEME_SM2, TPMS_SIG_SCHEME_ECSCHNORR, + /// TPMS_SCHEME_HMAC, TPMS_SCHEME_HASH, TPMS_NULL_SIG_SCHEME. + /// PCRselect: PCR set to quote + /// quoted - The quoted information + /// signature - The signature over quoted + pub fn Quote( + &mut self, + signHandle: &TPM_HANDLE, + qualifyingData: &Vec, + inScheme: &Option, + PCRselect: &Vec, + ) -> Result { + let req = TPM2_Quote_REQUEST::new( + signHandle, + qualifyingData, + inScheme, + PCRselect, + ); + + let mut resp = QuoteResponse::default(); + self.dispatch(TPM_CC::Quote, req, &mut resp)?; + Ok(resp) + } + + /// This command returns a digital signature of the audit session digest. + /// privacyAdminHandle: Handle of the privacy administrator (TPM_RH_ENDORSEMENT) + /// Auth Index: 1 + /// Auth Role: USER + /// signHandle: Handle of the signing key + /// Auth Index: 2 + /// Auth Role: USER + /// sessionHandle: Handle of the audit session + /// Auth Index: None + /// qualifyingData: User-provided qualifying data may be zero-length + /// inScheme: Signing scheme to use if the scheme for signHandle is TPM_ALG_NULL + /// One of: TPMS_SIG_SCHEME_RSASSA, TPMS_SIG_SCHEME_RSAPSS, TPMS_SIG_SCHEME_ECDSA, + /// TPMS_SIG_SCHEME_ECDAA, TPMS_SIG_SCHEME_SM2, TPMS_SIG_SCHEME_ECSCHNORR, + /// TPMS_SCHEME_HMAC, TPMS_SCHEME_HASH, TPMS_NULL_SIG_SCHEME. + /// auditInfo - The audit information that was signed + /// signature - The signature over auditInfo + pub fn GetSessionAuditDigest( + &mut self, + privacyAdminHandle: &TPM_HANDLE, + signHandle: &TPM_HANDLE, + sessionHandle: &TPM_HANDLE, + qualifyingData: &Vec, + inScheme: &Option, + ) -> Result { + let req = TPM2_GetSessionAuditDigest_REQUEST::new( + privacyAdminHandle, + signHandle, + sessionHandle, + qualifyingData, + inScheme, + ); + + let mut resp = GetSessionAuditDigestResponse::default(); + self.dispatch(TPM_CC::GetSessionAuditDigest, req, &mut resp)?; + Ok(resp) + } + + /// This command returns the current value of the command audit digest, a digest of the + /// commands being audited, and the audit hash algorithm. These values are placed in an + /// attestation structure and signed with the key referenced by signHandle. + /// privacyHandle: Handle of the privacy administrator (TPM_RH_ENDORSEMENT) + /// Auth Index: 1 + /// Auth Role: USER + /// signHandle: The handle of the signing key + /// Auth Index: 2 + /// Auth Role: USER + /// qualifyingData: Other data to associate with this audit digest + /// inScheme: Signing scheme to use if the scheme for signHandle is TPM_ALG_NULL + /// One of: TPMS_SIG_SCHEME_RSASSA, TPMS_SIG_SCHEME_RSAPSS, TPMS_SIG_SCHEME_ECDSA, + /// TPMS_SIG_SCHEME_ECDAA, TPMS_SIG_SCHEME_SM2, TPMS_SIG_SCHEME_ECSCHNORR, + /// TPMS_SCHEME_HMAC, TPMS_SCHEME_HASH, TPMS_NULL_SIG_SCHEME. + /// auditInfo - The auditInfo that was signed + /// signature - The signature over auditInfo + pub fn GetCommandAuditDigest( + &mut self, + privacyHandle: &TPM_HANDLE, + signHandle: &TPM_HANDLE, + qualifyingData: &Vec, + inScheme: &Option, + ) -> Result { + let req = TPM2_GetCommandAuditDigest_REQUEST::new( + privacyHandle, + signHandle, + qualifyingData, + inScheme, + ); + + let mut resp = GetCommandAuditDigestResponse::default(); + self.dispatch(TPM_CC::GetCommandAuditDigest, req, &mut resp)?; + Ok(resp) + } + + /// This command returns the current values of Time and Clock. + /// privacyAdminHandle: Handle of the privacy administrator (TPM_RH_ENDORSEMENT) + /// Auth Index: 1 + /// Auth Role: USER + /// signHandle: The keyHandle identifier of a loaded key that can perform digital signatures + /// Auth Index: 2 + /// Auth Role: USER + /// qualifyingData: Data to tick stamp + /// inScheme: Signing scheme to use if the scheme for signHandle is TPM_ALG_NULL + /// One of: TPMS_SIG_SCHEME_RSASSA, TPMS_SIG_SCHEME_RSAPSS, TPMS_SIG_SCHEME_ECDSA, + /// TPMS_SIG_SCHEME_ECDAA, TPMS_SIG_SCHEME_SM2, TPMS_SIG_SCHEME_ECSCHNORR, + /// TPMS_SCHEME_HMAC, TPMS_SCHEME_HASH, TPMS_NULL_SIG_SCHEME. + /// timeInfo - Standard TPM-generated attestation block + /// signature - The signature over timeInfo + pub fn GetTime( + &mut self, + privacyAdminHandle: &TPM_HANDLE, + signHandle: &TPM_HANDLE, + qualifyingData: &Vec, + inScheme: &Option, + ) -> Result { + let req = TPM2_GetTime_REQUEST::new( + privacyAdminHandle, + signHandle, + qualifyingData, + inScheme, + ); + + let mut resp = GetTimeResponse::default(); + self.dispatch(TPM_CC::GetTime, req, &mut resp)?; + Ok(resp) + } + + /// The purpose of this command is to generate an X.509 certificate that proves an object with + /// a specific public key and attributes is loaded in the TPM. In contrast to TPM2_Certify, + /// which uses a TCG-defined data structure to convey attestation information, + /// TPM2_CertifyX509 encodes the attestation information in a DER-encoded X.509 certificate + /// that is compliant with RFC5280 Internet X.509 Public Key Infrastructure Certificate and + /// Certificate Revocation List (CRL) Profile. + /// objectHandle: Handle of the object to be certified + /// Auth Index: 1 + /// Auth Role: ADMIN + /// signHandle: Handle of the key used to sign the attestation structure + /// Auth Index: 2 + /// Auth Role: USER + /// reserved: Shall be an Empty Buffer + /// inScheme: Signing scheme to use if the scheme for signHandle is TPM_ALG_NULL + /// One of: TPMS_SIG_SCHEME_RSASSA, TPMS_SIG_SCHEME_RSAPSS, TPMS_SIG_SCHEME_ECDSA, + /// TPMS_SIG_SCHEME_ECDAA, TPMS_SIG_SCHEME_SM2, TPMS_SIG_SCHEME_ECSCHNORR, + /// TPMS_SCHEME_HMAC, TPMS_SCHEME_HASH, TPMS_NULL_SIG_SCHEME. + /// partialCertificate: A DER encoded partial certificate + /// addedToCertificate - A DER encoded SEQUENCE containing the DER encoded fields added to + /// partialCertificate to make it a complete RFC5280 TBSCertificate. + /// tbsDigest - The digest that was signed + /// signature - The signature over tbsDigest + pub fn CertifyX509( + &mut self, + objectHandle: &TPM_HANDLE, + signHandle: &TPM_HANDLE, + reserved: &Vec, + inScheme: &Option, + partialCertificate: &Vec, + ) -> Result { + let req = TPM2_CertifyX509_REQUEST::new( + objectHandle, + signHandle, + reserved, + inScheme, + partialCertificate, + ); + + let mut resp = CertifyX509Response::default(); + self.dispatch(TPM_CC::CertifyX509, req, &mut resp)?; + Ok(resp) + } + + /// TPM2_Commit() performs the first part of an ECC anonymous signing operation. The TPM will + /// perform the point multiplications on the provided points and return intermediate signing + /// values. The signHandle parameter shall refer to an ECC key and the signing scheme must be + /// anonymous (TPM_RC_SCHEME). + /// signHandle: Handle of the key that will be used in the signing operation + /// Auth Index: 1 + /// Auth Role: USER + /// P1: A point (M) on the curve used by signHandle + /// s2: Octet array used to derive x-coordinate of a base point + /// y2: Y coordinate of the point associated with s2 + /// K - ECC point K [ds](x2, y2) + /// L - ECC point L [r](x2, y2) + /// E - ECC point E [r]P1 + /// counter - Least-significant 16 bits of commitCount + pub fn Commit( + &mut self, + signHandle: &TPM_HANDLE, + P1: &TPMS_ECC_POINT, + s2: &Vec, + y2: &Vec, + ) -> Result { + let req = TPM2_Commit_REQUEST::new( + signHandle, + P1, + s2, + y2, + ); + + let mut resp = CommitResponse::default(); + self.dispatch(TPM_CC::Commit, req, &mut resp)?; + Ok(resp) + } + + /// TPM2_EC_Ephemeral() creates an ephemeral key for use in a two-phase key exchange protocol. + /// curveID: The curve for the computed ephemeral point + /// Q - Ephemeral public key Q [r]G + /// counter - Least-significant 16 bits of commitCount + pub fn EC_Ephemeral( + &mut self, + curveID: TPM_ECC_CURVE, + ) -> Result { + let req = TPM2_EC_Ephemeral_REQUEST::new( + curveID, + ); + + let mut resp = EC_EphemeralResponse::default(); + self.dispatch(TPM_CC::EC_Ephemeral, req, &mut resp)?; + Ok(resp) + } + + /// This command uses loaded keys to validate a signature on a message with the message digest + /// passed to the TPM. + /// keyHandle: Handle of public key that will be used in the validation + /// Auth Index: None + /// digest: Digest of the signed message + /// signature: Signature to be tested + /// One of: TPMS_SIGNATURE_RSASSA, TPMS_SIGNATURE_RSAPSS, TPMS_SIGNATURE_ECDSA, + /// TPMS_SIGNATURE_ECDAA, TPMS_SIGNATURE_SM2, TPMS_SIGNATURE_ECSCHNORR, TPMT_HA, + /// TPMS_SCHEME_HASH, TPMS_NULL_SIGNATURE. + /// validation - This ticket is produced by TPM2_VerifySignature(). This formulation is + /// used for multiple ticket uses. The ticket provides evidence that the TPM + /// has validated that a digest was signed by a key with the Name of keyName. + /// The ticket is computed by + pub fn VerifySignature( + &mut self, + keyHandle: &TPM_HANDLE, + digest: &Vec, + signature: &Option, + ) -> Result { + let req = TPM2_VerifySignature_REQUEST::new( + keyHandle, + digest, + signature, + ); + + let mut resp = VerifySignatureResponse::default(); + self.dispatch(TPM_CC::VerifySignature, req, &mut resp)?; + Ok(resp.validation) + } + + /// This command causes the TPM to sign an externally provided hash with the specified + /// symmetric or asymmetric signing key. + /// keyHandle: Handle of key that will perform signing + /// Auth Index: 1 + /// Auth Role: USER + /// digest: Digest to be signed + /// inScheme: Signing scheme to use if the scheme for keyHandle is TPM_ALG_NULL + /// One of: TPMS_SIG_SCHEME_RSASSA, TPMS_SIG_SCHEME_RSAPSS, TPMS_SIG_SCHEME_ECDSA, + /// TPMS_SIG_SCHEME_ECDAA, TPMS_SIG_SCHEME_SM2, TPMS_SIG_SCHEME_ECSCHNORR, + /// TPMS_SCHEME_HMAC, TPMS_SCHEME_HASH, TPMS_NULL_SIG_SCHEME. + /// validation: Proof that digest was created by the TPM + /// If keyHandle is not a restricted signing key, then this may be a NULL Ticket with + /// tag = TPM_ST_CHECKHASH. + /// signature - The signature + pub fn Sign( + &mut self, + keyHandle: &TPM_HANDLE, + digest: &Vec, + inScheme: &Option, + validation: &TPMT_TK_HASHCHECK, + ) -> Result, TpmError> { + let req = TPM2_Sign_REQUEST::new( + keyHandle, + digest, + inScheme, + validation, + ); + + let mut resp = SignResponse::default(); + self.dispatch(TPM_CC::Sign, req, &mut resp)?; + Ok(resp.signature) + } + + /// This command may be used by the Privacy Administrator or platform to change the audit + /// status of a command or to set the hash algorithm used for the audit digest, but not both + /// at the same time. + /// auth: TPM_RH_OWNER or TPM_RH_PLATFORM+{PP} + /// Auth Index: 1 + /// Auth Role: USER + /// auditAlg: Hash algorithm for the audit digest; if TPM_ALG_NULL, then the hash is not changed + /// setList: List of commands that will be added to those that will be audited + /// clearList: List of commands that will no longer be audited + pub fn SetCommandCodeAuditStatus( + &mut self, + auth: &TPM_HANDLE, + auditAlg: TPM_ALG_ID, + setList: &Vec, + clearList: &Vec, + ) -> Result<(), TpmError> { + let req = TPM2_SetCommandCodeAuditStatus_REQUEST::new( + auth, + auditAlg, + setList, + clearList, + ); + + let mut resp = EmptyTpmResponse::default(); + self.dispatch(TPM_CC::SetCommandCodeAuditStatus, req, &mut resp)?; + Ok(()) + } + + /// This command is used to cause an update to the indicated PCR. The digests parameter + /// contains one or more tagged digest values identified by an algorithm ID. For each digest, + /// the PCR associated with pcrHandle is Extended into the bank identified by the tag (hashAlg). + /// pcrHandle: Handle of the PCR + /// Auth Handle: 1 + /// Auth Role: USER + /// digests: List of tagged digest values to be extended + pub fn PCR_Extend( + &mut self, + pcrHandle: &TPM_HANDLE, + digests: &Vec, + ) -> Result<(), TpmError> { + let req = TPM2_PCR_Extend_REQUEST::new( + pcrHandle, + digests, + ); + + let mut resp = EmptyTpmResponse::default(); + self.dispatch(TPM_CC::PCR_Extend, req, &mut resp)?; + Ok(()) + } + + /// This command is used to cause an update to the indicated PCR. + /// pcrHandle: Handle of the PCR + /// Auth Handle: 1 + /// Auth Role: USER + /// eventData: Event data in sized buffer + /// digests - Table 80 shows the basic hash-agile structure used in this specification. To + /// handle hash agility, this structure uses the hashAlg parameter to indicate + /// the algorithm used to compute the digest and, by implication, the size of + /// the digest. + pub fn PCR_Event( + &mut self, + pcrHandle: &TPM_HANDLE, + eventData: &Vec, + ) -> Result, TpmError> { + let req = TPM2_PCR_Event_REQUEST::new( + pcrHandle, + eventData, + ); + + let mut resp = PCR_EventResponse::default(); + self.dispatch(TPM_CC::PCR_Event, req, &mut resp)?; + Ok(resp.digests) + } + + /// This command returns the values of all PCR specified in pcrSelectionIn. + /// pcrSelectionIn: The selection of PCR to read + /// pcrUpdateCounter - The current value of the PCR update counter + /// pcrSelectionOut - The PCR in the returned list + /// pcrValues - The contents of the PCR indicated in pcrSelectOut-˃ pcrSelection[] as + /// tagged digests + pub fn PCR_Read( + &mut self, + pcrSelectionIn: &Vec, + ) -> Result { + let req = TPM2_PCR_Read_REQUEST::new( + pcrSelectionIn, + ); + + let mut resp = PCR_ReadResponse::default(); + self.dispatch(TPM_CC::PCR_Read, req, &mut resp)?; + Ok(resp) + } + + /// This command is used to set the desired PCR allocation of PCR and algorithms. This command + /// requires Platform Authorization. + /// authHandle: TPM_RH_PLATFORM+{PP} + /// Auth Index: 1 + /// Auth Role: USER + /// pcrAllocation: The requested allocation + /// allocationSuccess - YES if the allocation succeeded + /// maxPCR - Maximum number of PCR that may be in a bank + /// sizeNeeded - Number of octets required to satisfy the request + /// sizeAvailable - Number of octets available. Computed before the allocation. + pub fn PCR_Allocate( + &mut self, + authHandle: &TPM_HANDLE, + pcrAllocation: &Vec, + ) -> Result { + let req = TPM2_PCR_Allocate_REQUEST::new( + authHandle, + pcrAllocation, + ); + + let mut resp = PCR_AllocateResponse::default(); + self.dispatch(TPM_CC::PCR_Allocate, req, &mut resp)?; + Ok(resp) + } + + /// This command is used to associate a policy with a PCR or group of PCR. The policy + /// determines the conditions under which a PCR may be extended or reset. + /// authHandle: TPM_RH_PLATFORM+{PP} + /// Auth Index: 1 + /// Auth Role: USER + /// authPolicy: The desired authPolicy + /// hashAlg: The hash algorithm of the policy + /// pcrNum: The PCR for which the policy is to be set + pub fn PCR_SetAuthPolicy( + &mut self, + authHandle: &TPM_HANDLE, + authPolicy: &Vec, + hashAlg: TPM_ALG_ID, + pcrNum: &TPM_HANDLE, + ) -> Result<(), TpmError> { + let req = TPM2_PCR_SetAuthPolicy_REQUEST::new( + authHandle, + authPolicy, + hashAlg, + pcrNum, + ); + + let mut resp = EmptyTpmResponse::default(); + self.dispatch(TPM_CC::PCR_SetAuthPolicy, req, &mut resp)?; + Ok(()) + } + + /// This command changes the authValue of a PCR or group of PCR. + /// pcrHandle: Handle for a PCR that may have an authorization value set + /// Auth Index: 1 + /// Auth Role: USER + /// auth: The desired authorization value + pub fn PCR_SetAuthValue( + &mut self, + pcrHandle: &TPM_HANDLE, + auth: &Vec, + ) -> Result<(), TpmError> { + let req = TPM2_PCR_SetAuthValue_REQUEST::new( + pcrHandle, + auth, + ); + + let mut resp = EmptyTpmResponse::default(); + self.dispatch(TPM_CC::PCR_SetAuthValue, req, &mut resp)?; + Ok(()) + } + + /// If the attribute of a PCR allows the PCR to be reset and proper authorization is provided, + /// then this command may be used to set the PCR in all banks to zero. The attributes of the + /// PCR may restrict the locality that can perform the reset operation. + /// pcrHandle: The PCR to reset + /// Auth Index: 1 + /// Auth Role: USER + pub fn PCR_Reset( + &mut self, + pcrHandle: &TPM_HANDLE, + ) -> Result<(), TpmError> { + let req = TPM2_PCR_Reset_REQUEST::new( + pcrHandle, + ); + + let mut resp = EmptyTpmResponse::default(); + self.dispatch(TPM_CC::PCR_Reset, req, &mut resp)?; + Ok(()) + } + + /// This command includes a signed authorization in a policy. The command ties the policy to a + /// signing key by including the Name of the signing key in the policyDigest + /// authObject: Handle for a key that will validate the signature + /// Auth Index: None + /// policySession: Handle for the policy session being extended + /// Auth Index: None + /// nonceTPM: The policy nonce for the session + /// This can be the Empty Buffer. + /// cpHashA: Digest of the command parameters to which this authorization is limited + /// This is not the cpHash for this command but the cpHash for the command to which + /// this policy session will be applied. If it is not limited, the parameter will be + /// the Empty Buffer. + /// policyRef: A reference to a policy relating to the authorization may be the Empty Buffer + /// Size is limited to be no larger than the nonce size supported on the TPM. + /// expiration: Time when authorization will expire, measured in seconds from the time that + /// nonceTPM was generated + /// If expiration is non-negative, a NULL Ticket is returned. See 23.2.5. + /// auth: Signed authorization (not optional) + /// One of: TPMS_SIGNATURE_RSASSA, TPMS_SIGNATURE_RSAPSS, TPMS_SIGNATURE_ECDSA, + /// TPMS_SIGNATURE_ECDAA, TPMS_SIGNATURE_SM2, TPMS_SIGNATURE_ECSCHNORR, TPMT_HA, + /// TPMS_SCHEME_HASH, TPMS_NULL_SIGNATURE. + /// timeout - Implementation-specific time value, used to indicate to the TPM when the + /// ticket expires + /// NOTE If policyTicket is a NULL Ticket, then this shall be the Empty Buffer. + /// policyTicket - Produced if the command succeeds and expiration in the command was + /// non-zero; this ticket will use the TPMT_ST_AUTH_SIGNED structure tag. + /// See 23.2.5 + pub fn PolicySigned( + &mut self, + authObject: &TPM_HANDLE, + policySession: &TPM_HANDLE, + nonceTPM: &Vec, + cpHashA: &Vec, + policyRef: &Vec, + expiration: i32, + auth: &Option, + ) -> Result { + let req = TPM2_PolicySigned_REQUEST::new( + authObject, + policySession, + nonceTPM, + cpHashA, + policyRef, + expiration, + auth, + ); + + let mut resp = PolicySignedResponse::default(); + self.dispatch(TPM_CC::PolicySigned, req, &mut resp)?; + Ok(resp) + } + + /// This command includes a secret-based authorization to a policy. The caller proves + /// knowledge of the secret value using an authorization session using the authValue + /// associated with authHandle. A password session, an HMAC session, or a policy session + /// containing TPM2_PolicyAuthValue() or TPM2_PolicyPassword() will satisfy this requirement. + /// authHandle: Handle for an entity providing the authorization + /// Auth Index: 1 + /// Auth Role: USER + /// policySession: Handle for the policy session being extended + /// Auth Index: None + /// nonceTPM: The policy nonce for the session + /// This can be the Empty Buffer. + /// cpHashA: Digest of the command parameters to which this authorization is limited + /// This not the cpHash for this command but the cpHash for the command to which this + /// policy session will be applied. If it is not limited, the parameter will be the + /// Empty Buffer. + /// policyRef: A reference to a policy relating to the authorization may be the Empty Buffer + /// Size is limited to be no larger than the nonce size supported on the TPM. + /// expiration: Time when authorization will expire, measured in seconds from the time that + /// nonceTPM was generated + /// If expiration is non-negative, a NULL Ticket is returned. See 23.2.5. + /// timeout - Implementation-specific time value used to indicate to the TPM when the + /// ticket expires + /// policyTicket - Produced if the command succeeds and expiration in the command was + /// non-zero ( See 23.2.5). This ticket will use the TPMT_ST_AUTH_SECRET + /// structure tag + pub fn PolicySecret( + &mut self, + authHandle: &TPM_HANDLE, + policySession: &TPM_HANDLE, + nonceTPM: &Vec, + cpHashA: &Vec, + policyRef: &Vec, + expiration: i32, + ) -> Result { + let req = TPM2_PolicySecret_REQUEST::new( + authHandle, + policySession, + nonceTPM, + cpHashA, + policyRef, + expiration, + ); + + let mut resp = PolicySecretResponse::default(); + self.dispatch(TPM_CC::PolicySecret, req, &mut resp)?; + Ok(resp) + } + + /// This command is similar to TPM2_PolicySigned() except that it takes a ticket instead of a + /// signed authorization. The ticket represents a validated authorization that had an + /// expiration time associated with it. + /// policySession: Handle for the policy session being extended + /// Auth Index: None + /// timeout: Time when authorization will expire + /// The contents are TPM specific. This shall be the value returned when ticket was produced. + /// cpHashA: Digest of the command parameters to which this authorization is limited + /// If it is not limited, the parameter will be the Empty Buffer. + /// policyRef: Reference to a qualifier for the policy may be the Empty Buffer + /// authName: Name of the object that provided the authorization + /// ticket: An authorization ticket returned by the TPM in response to a TPM2_PolicySigned() + /// or TPM2_PolicySecret() + pub fn PolicyTicket( + &mut self, + policySession: &TPM_HANDLE, + timeout: &Vec, + cpHashA: &Vec, + policyRef: &Vec, + authName: &Vec, + ticket: &TPMT_TK_AUTH, + ) -> Result<(), TpmError> { + let req = TPM2_PolicyTicket_REQUEST::new( + policySession, + timeout, + cpHashA, + policyRef, + authName, + ticket, + ); + + let mut resp = EmptyTpmResponse::default(); + self.dispatch(TPM_CC::PolicyTicket, req, &mut resp)?; + Ok(()) + } + + /// This command allows options in authorizations without requiring that the TPM evaluate all + /// of the options. If a policy may be satisfied by different sets of conditions, the TPM need + /// only evaluate one set that satisfies the policy. This command will indicate that one of + /// the required sets of conditions has been satisfied. + /// policySession: Handle for the policy session being extended + /// Auth Index: None + /// pHashList: The list of hashes to check for a match + pub fn PolicyOR( + &mut self, + policySession: &TPM_HANDLE, + pHashList: &Vec, + ) -> Result<(), TpmError> { + let req = TPM2_PolicyOR_REQUEST::new( + policySession, + pHashList, + ); + + let mut resp = EmptyTpmResponse::default(); + self.dispatch(TPM_CC::PolicyOR, req, &mut resp)?; + Ok(()) + } + + /// This command is used to cause conditional gating of a policy based on PCR. This command + /// together with TPM2_PolicyOR() allows one group of authorizations to occur when PCR are in + /// one state and a different set of authorizations when the PCR are in a different state. + /// policySession: Handle for the policy session being extended + /// Auth Index: None + /// pcrDigest: Expected digest value of the selected PCR using the hash algorithm of the + /// session; may be zero length + /// pcrs: The PCR to include in the check digest + pub fn PolicyPCR( + &mut self, + policySession: &TPM_HANDLE, + pcrDigest: &Vec, + pcrs: &Vec, + ) -> Result<(), TpmError> { + let req = TPM2_PolicyPCR_REQUEST::new( + policySession, + pcrDigest, + pcrs, + ); + + let mut resp = EmptyTpmResponse::default(); + self.dispatch(TPM_CC::PolicyPCR, req, &mut resp)?; + Ok(()) + } + + /// This command indicates that the authorization will be limited to a specific locality. + /// policySession: Handle for the policy session being extended + /// Auth Index: None + /// locality: The allowed localities for the policy + pub fn PolicyLocality( + &mut self, + policySession: &TPM_HANDLE, + locality: TPMA_LOCALITY, + ) -> Result<(), TpmError> { + let req = TPM2_PolicyLocality_REQUEST::new( + policySession, + locality, + ); + + let mut resp = EmptyTpmResponse::default(); + self.dispatch(TPM_CC::PolicyLocality, req, &mut resp)?; + Ok(()) + } + + /// This command is used to cause conditional gating of a policy based on the contents of an + /// NV Index. It is an immediate assertion. The NV index is validated during the + /// TPM2_PolicyNV() command, not when the session is used for authorization. + /// authHandle: Handle indicating the source of the authorization value + /// Auth Index: 1 + /// Auth Role: USER + /// nvIndex: The NV Index of the area to read + /// Auth Index: None + /// policySession: Handle for the policy session being extended + /// Auth Index: None + /// operandB: The second operand + /// offset: The octet offset in the NV Index for the start of operand A + /// operation: The comparison to make + pub fn PolicyNV( + &mut self, + authHandle: &TPM_HANDLE, + nvIndex: &TPM_HANDLE, + policySession: &TPM_HANDLE, + operandB: &Vec, + offset: u16, + operation: TPM_EO, + ) -> Result<(), TpmError> { + let req = TPM2_PolicyNV_REQUEST::new( + authHandle, + nvIndex, + policySession, + operandB, + offset, + operation, + ); + + let mut resp = EmptyTpmResponse::default(); + self.dispatch(TPM_CC::PolicyNV, req, &mut resp)?; + Ok(()) + } + + /// This command is used to cause conditional gating of a policy based on the contents of the + /// TPMS_TIME_INFO structure. + /// policySession: Handle for the policy session being extended + /// Auth Index: None + /// operandB: The second operand + /// offset: The octet offset in the TPMS_TIME_INFO structure for the start of operand A + /// operation: The comparison to make + pub fn PolicyCounterTimer( + &mut self, + policySession: &TPM_HANDLE, + operandB: &Vec, + offset: u16, + operation: TPM_EO, + ) -> Result<(), TpmError> { + let req = TPM2_PolicyCounterTimer_REQUEST::new( + policySession, + operandB, + offset, + operation, + ); + + let mut resp = EmptyTpmResponse::default(); + self.dispatch(TPM_CC::PolicyCounterTimer, req, &mut resp)?; + Ok(()) + } + + /// This command indicates that the authorization will be limited to a specific command code. + /// policySession: Handle for the policy session being extended + /// Auth Index: None + /// code: The allowed commandCode + pub fn PolicyCommandCode( + &mut self, + policySession: &TPM_HANDLE, + code: TPM_CC, + ) -> Result<(), TpmError> { + let req = TPM2_PolicyCommandCode_REQUEST::new( + policySession, + code, + ); + + let mut resp = EmptyTpmResponse::default(); + self.dispatch(TPM_CC::PolicyCommandCode, req, &mut resp)?; + Ok(()) + } + + /// This command indicates that physical presence will need to be asserted at the time the + /// authorization is performed. + /// policySession: Handle for the policy session being extended + /// Auth Index: None + pub fn PolicyPhysicalPresence( + &mut self, + policySession: &TPM_HANDLE, + ) -> Result<(), TpmError> { + let req = TPM2_PolicyPhysicalPresence_REQUEST::new( + policySession, + ); + + let mut resp = EmptyTpmResponse::default(); + self.dispatch(TPM_CC::PolicyPhysicalPresence, req, &mut resp)?; + Ok(()) + } + + /// This command is used to allow a policy to be bound to a specific command and command parameters. + /// policySession: Handle for the policy session being extended + /// Auth Index: None + /// cpHashA: The cpHash added to the policy + pub fn PolicyCpHash( + &mut self, + policySession: &TPM_HANDLE, + cpHashA: &Vec, + ) -> Result<(), TpmError> { + let req = TPM2_PolicyCpHash_REQUEST::new( + policySession, + cpHashA, + ); + + let mut resp = EmptyTpmResponse::default(); + self.dispatch(TPM_CC::PolicyCpHash, req, &mut resp)?; + Ok(()) + } + + /// This command allows a policy to be bound to a specific set of TPM entities without being + /// bound to the parameters of the command. This is most useful for commands such as + /// TPM2_Duplicate() and for TPM2_PCR_Event() when the referenced PCR requires a policy. + /// policySession: Handle for the policy session being extended + /// Auth Index: None + /// nameHash: The digest to be added to the policy + pub fn PolicyNameHash( + &mut self, + policySession: &TPM_HANDLE, + nameHash: &Vec, + ) -> Result<(), TpmError> { + let req = TPM2_PolicyNameHash_REQUEST::new( + policySession, + nameHash, + ); + + let mut resp = EmptyTpmResponse::default(); + self.dispatch(TPM_CC::PolicyNameHash, req, &mut resp)?; + Ok(()) + } + + /// This command allows qualification of duplication to allow duplication to a selected new parent. + /// policySession: Handle for the policy session being extended + /// Auth Index: None + /// objectName: The Name of the object to be duplicated + /// newParentName: The Name of the new parent + /// includeObject: If YES, the objectName will be included in the value in policySessionpolicyDigest + pub fn PolicyDuplicationSelect( + &mut self, + policySession: &TPM_HANDLE, + objectName: &Vec, + newParentName: &Vec, + includeObject: u8, + ) -> Result<(), TpmError> { + let req = TPM2_PolicyDuplicationSelect_REQUEST::new( + policySession, + objectName, + newParentName, + includeObject, + ); + + let mut resp = EmptyTpmResponse::default(); + self.dispatch(TPM_CC::PolicyDuplicationSelect, req, &mut resp)?; + Ok(()) + } + + /// This command allows policies to change. If a policy were static, then it would be + /// difficult to add users to a policy. This command lets a policy authority sign a new policy + /// so that it may be used in an existing policy. + /// policySession: Handle for the policy session being extended + /// Auth Index: None + /// approvedPolicy: Digest of the policy being approved + /// policyRef: A policy qualifier + /// keySign: Name of a key that can sign a policy addition + /// checkTicket: Ticket validating that approvedPolicy and policyRef were signed by keySign + pub fn PolicyAuthorize( + &mut self, + policySession: &TPM_HANDLE, + approvedPolicy: &Vec, + policyRef: &Vec, + keySign: &Vec, + checkTicket: &TPMT_TK_VERIFIED, + ) -> Result<(), TpmError> { + let req = TPM2_PolicyAuthorize_REQUEST::new( + policySession, + approvedPolicy, + policyRef, + keySign, + checkTicket, + ); + + let mut resp = EmptyTpmResponse::default(); + self.dispatch(TPM_CC::PolicyAuthorize, req, &mut resp)?; + Ok(()) + } + + /// This command allows a policy to be bound to the authorization value of the authorized entity. + /// policySession: Handle for the policy session being extended + /// Auth Index: None + pub fn PolicyAuthValue( + &mut self, + policySession: &TPM_HANDLE, + ) -> Result<(), TpmError> { + let req = TPM2_PolicyAuthValue_REQUEST::new( + policySession, + ); + + let mut resp = EmptyTpmResponse::default(); + self.dispatch(TPM_CC::PolicyAuthValue, req, &mut resp)?; + Ok(()) + } + + /// This command allows a policy to be bound to the authorization value of the authorized object. + /// policySession: Handle for the policy session being extended + /// Auth Index: None + pub fn PolicyPassword( + &mut self, + policySession: &TPM_HANDLE, + ) -> Result<(), TpmError> { + let req = TPM2_PolicyPassword_REQUEST::new( + policySession, + ); + + let mut resp = EmptyTpmResponse::default(); + self.dispatch(TPM_CC::PolicyPassword, req, &mut resp)?; + Ok(()) + } + + /// This command returns the current policyDigest of the session. This command allows the TPM + /// to be used to perform the actions required to pre-compute the authPolicy for an object. + /// policySession: Handle for the policy session + /// Auth Index: None + /// policyDigest - The current value of the policySessionpolicyDigest + pub fn PolicyGetDigest( + &mut self, + policySession: &TPM_HANDLE, + ) -> Result, TpmError> { + let req = TPM2_PolicyGetDigest_REQUEST::new( + policySession, + ); + + let mut resp = PolicyGetDigestResponse::default(); + self.dispatch(TPM_CC::PolicyGetDigest, req, &mut resp)?; + Ok(resp.policyDigest) + } + + /// This command allows a policy to be bound to the TPMA_NV_WRITTEN attributes. This is a + /// deferred assertion. Values are stored in the policy session context and checked when the + /// policy is used for authorization. + /// policySession: Handle for the policy session being extended + /// Auth Index: None + /// writtenSet: YES if NV Index is required to have been written + /// NO if NV Index is required not to have been written + pub fn PolicyNvWritten( + &mut self, + policySession: &TPM_HANDLE, + writtenSet: u8, + ) -> Result<(), TpmError> { + let req = TPM2_PolicyNvWritten_REQUEST::new( + policySession, + writtenSet, + ); + + let mut resp = EmptyTpmResponse::default(); + self.dispatch(TPM_CC::PolicyNvWritten, req, &mut resp)?; + Ok(()) + } + + /// This command allows a policy to be bound to a specific creation template. This is most + /// useful for an object creation command such as TPM2_Create(), TPM2_CreatePrimary(), or + /// TPM2_CreateLoaded(). + /// policySession: Handle for the policy session being extended + /// Auth Index: None + /// templateHash: The digest to be added to the policy + pub fn PolicyTemplate( + &mut self, + policySession: &TPM_HANDLE, + templateHash: &Vec, + ) -> Result<(), TpmError> { + let req = TPM2_PolicyTemplate_REQUEST::new( + policySession, + templateHash, + ); + + let mut resp = EmptyTpmResponse::default(); + self.dispatch(TPM_CC::PolicyTemplate, req, &mut resp)?; + Ok(()) + } + + /// This command provides a capability that is the equivalent of a revocable policy. With + /// TPM2_PolicyAuthorize(), the authorization ticket never expires, so the authorization may + /// not be withdrawn. With this command, the approved policy is kept in an NV Index location + /// so that the policy may be changed as needed to render the old policy unusable. + /// authHandle: Handle indicating the source of the authorization value + /// Auth Index: 1 + /// Auth Role: USER + /// nvIndex: The NV Index of the area to read + /// Auth Index: None + /// policySession: Handle for the policy session being extended + /// Auth Index: None + pub fn PolicyAuthorizeNV( + &mut self, + authHandle: &TPM_HANDLE, + nvIndex: &TPM_HANDLE, + policySession: &TPM_HANDLE, + ) -> Result<(), TpmError> { + let req = TPM2_PolicyAuthorizeNV_REQUEST::new( + authHandle, + nvIndex, + policySession, + ); + + let mut resp = EmptyTpmResponse::default(); + self.dispatch(TPM_CC::PolicyAuthorizeNV, req, &mut resp)?; + Ok(()) + } + + /// This command is used to create a Primary Object under one of the Primary Seeds or a + /// Temporary Object under TPM_RH_NULL. The command uses a TPM2B_PUBLIC as a template for the + /// object to be created. The size of the unique field shall not be checked for consistency + /// with the other object parameters. The command will create and load a Primary Object. The + /// sensitive area is not returned. + /// primaryHandle: TPM_RH_ENDORSEMENT, TPM_RH_OWNER, TPM_RH_PLATFORM+{PP}, or TPM_RH_NULL + /// Auth Index: 1 + /// Auth Role: USER + /// inSensitive: The sensitive data, see TPM 2.0 Part 1 Sensitive Values + /// inPublic: The public template + /// outsideInfo: Data that will be included in the creation data for this object to provide + /// permanent, verifiable linkage between this object and some object owner data + /// creationPCR: PCR that will be used in creation data + /// handle - Handle of type TPM_HT_TRANSIENT for created Primary Object + /// outPublic - The public portion of the created object + /// creationData - Contains a TPMT_CREATION_DATA + /// creationHash - Digest of creationData using nameAlg of outPublic + /// creationTicket - Ticket used by TPM2_CertifyCreation() to validate that the creation + /// data was produced by the TPM + /// name - The name of the created object + pub fn CreatePrimary( + &mut self, + primaryHandle: &TPM_HANDLE, + inSensitive: &TPMS_SENSITIVE_CREATE, + inPublic: &TPMT_PUBLIC, + outsideInfo: &Vec, + creationPCR: &Vec, + ) -> Result { + let req = TPM2_CreatePrimary_REQUEST::new( + primaryHandle, + inSensitive, + inPublic, + outsideInfo, + creationPCR, + ); + + let mut resp = CreatePrimaryResponse::default(); + self.dispatch(TPM_CC::CreatePrimary, req, &mut resp)?; + Ok(resp) + } + + /// This command enables and disables use of a hierarchy and its associated NV storage. The + /// command allows phEnable, phEnableNV, shEnable, and ehEnable to be changed when the proper + /// authorization is provided. + /// authHandle: TPM_RH_ENDORSEMENT, TPM_RH_OWNER or TPM_RH_PLATFORM+{PP} + /// Auth Index: 1 + /// Auth Role: USER + /// enable: The enable being modified + /// TPM_RH_ENDORSEMENT, TPM_RH_OWNER, TPM_RH_PLATFORM, or TPM_RH_PLATFORM_NV + /// state: YES if the enable should be SET, NO if the enable should be CLEAR + pub fn HierarchyControl( + &mut self, + authHandle: &TPM_HANDLE, + enable: &TPM_HANDLE, + state: u8, + ) -> Result<(), TpmError> { + let req = TPM2_HierarchyControl_REQUEST::new( + authHandle, + enable, + state, + ); + + let mut resp = EmptyTpmResponse::default(); + self.dispatch(TPM_CC::HierarchyControl, req, &mut resp)?; + Ok(()) + } + + /// This command allows setting of the authorization policy for the lockout (lockoutPolicy), + /// the platform hierarchy (platformPolicy), the storage hierarchy (ownerPolicy), and the + /// endorsement hierarchy (endorsementPolicy). On TPMs implementing Authenticated Countdown + /// Timers (ACT), this command may also be used to set the authorization policy for an ACT. + /// authHandle: TPM_RH_LOCKOUT, TPM_RH_ENDORSEMENT, TPM_RH_OWNER, TPMI_RH_ACT or TPM_RH_PLATFORM+{PP} + /// Auth Index: 1 + /// Auth Role: USER + /// authPolicy: An authorization policy digest; may be the Empty Buffer + /// If hashAlg is TPM_ALG_NULL, then this shall be an Empty Buffer. + /// hashAlg: The hash algorithm to use for the policy + /// If the authPolicy is an Empty Buffer, then this field shall be TPM_ALG_NULL. + pub fn SetPrimaryPolicy( + &mut self, + authHandle: &TPM_HANDLE, + authPolicy: &Vec, + hashAlg: TPM_ALG_ID, + ) -> Result<(), TpmError> { + let req = TPM2_SetPrimaryPolicy_REQUEST::new( + authHandle, + authPolicy, + hashAlg, + ); + + let mut resp = EmptyTpmResponse::default(); + self.dispatch(TPM_CC::SetPrimaryPolicy, req, &mut resp)?; + Ok(()) + } + + /// This replaces the current platform primary seed (PPS) with a value from the RNG and sets + /// platformPolicy to the default initialization value (the Empty Buffer). + /// authHandle: TPM_RH_PLATFORM+{PP} + /// Auth Index: 1 + /// Auth Role: USER + pub fn ChangePPS( + &mut self, + authHandle: &TPM_HANDLE, + ) -> Result<(), TpmError> { + let req = TPM2_ChangePPS_REQUEST::new( + authHandle, + ); + + let mut resp = EmptyTpmResponse::default(); + self.dispatch(TPM_CC::ChangePPS, req, &mut resp)?; + Ok(()) + } + + /// This replaces the current endorsement primary seed (EPS) with a value from the RNG and + /// sets the Endorsement hierarchy controls to their default initialization values: ehEnable + /// is SET, endorsementAuth and endorsementPolicy are both set to the Empty Buffer. It will + /// flush any resident objects (transient or persistent) in the Endorsement hierarchy and not + /// allow objects in the hierarchy associated with the previous EPS to be loaded. + /// authHandle: TPM_RH_PLATFORM+{PP} + /// Auth Handle: 1 + /// Auth Role: USER + pub fn ChangeEPS( + &mut self, + authHandle: &TPM_HANDLE, + ) -> Result<(), TpmError> { + let req = TPM2_ChangeEPS_REQUEST::new( + authHandle, + ); + + let mut resp = EmptyTpmResponse::default(); + self.dispatch(TPM_CC::ChangeEPS, req, &mut resp)?; + Ok(()) + } + + /// This command removes all TPM context associated with a specific Owner. + /// authHandle: TPM_RH_LOCKOUT or TPM_RH_PLATFORM+{PP} + /// Auth Handle: 1 + /// Auth Role: USER + pub fn Clear( + &mut self, + authHandle: &TPM_HANDLE, + ) -> Result<(), TpmError> { + let req = TPM2_Clear_REQUEST::new( + authHandle, + ); + + let mut resp = EmptyTpmResponse::default(); + self.dispatch(TPM_CC::Clear, req, &mut resp)?; + Ok(()) + } + + /// TPM2_ClearControl() disables and enables the execution of TPM2_Clear(). + /// auth: TPM_RH_LOCKOUT or TPM_RH_PLATFORM+{PP} + /// Auth Handle: 1 + /// Auth Role: USER + /// disable: YES if the disableOwnerClear flag is to be SET, NO if the flag is to be CLEAR. + pub fn ClearControl( + &mut self, + auth: &TPM_HANDLE, + disable: u8, + ) -> Result<(), TpmError> { + let req = TPM2_ClearControl_REQUEST::new( + auth, + disable, + ); + + let mut resp = EmptyTpmResponse::default(); + self.dispatch(TPM_CC::ClearControl, req, &mut resp)?; + Ok(()) + } + + /// This command allows the authorization secret for a hierarchy or lockout to be changed + /// using the current authorization value as the command authorization. + /// authHandle: TPM_RH_LOCKOUT, TPM_RH_ENDORSEMENT, TPM_RH_OWNER or TPM_RH_PLATFORM+{PP} + /// Auth Index: 1 + /// Auth Role: USER + /// newAuth: New authorization value + pub fn HierarchyChangeAuth( + &mut self, + authHandle: &TPM_HANDLE, + newAuth: &Vec, + ) -> Result<(), TpmError> { + let req = TPM2_HierarchyChangeAuth_REQUEST::new( + authHandle, + newAuth, + ); + + let mut resp = EmptyTpmResponse::default(); + self.dispatch(TPM_CC::HierarchyChangeAuth, req, &mut resp)?; + Ok(()) + } + + /// This command cancels the effect of a TPM lockout due to a number of successive + /// authorization failures. If this command is properly authorized, the lockout counter is set + /// to zero. + /// lockHandle: TPM_RH_LOCKOUT + /// Auth Index: 1 + /// Auth Role: USER + pub fn DictionaryAttackLockReset( + &mut self, + lockHandle: &TPM_HANDLE, + ) -> Result<(), TpmError> { + let req = TPM2_DictionaryAttackLockReset_REQUEST::new( + lockHandle, + ); + + let mut resp = EmptyTpmResponse::default(); + self.dispatch(TPM_CC::DictionaryAttackLockReset, req, &mut resp)?; + Ok(()) + } + + /// This command changes the lockout parameters. + /// lockHandle: TPM_RH_LOCKOUT + /// Auth Index: 1 + /// Auth Role: USER + /// newMaxTries: Count of authorization failures before the lockout is imposed + /// newRecoveryTime: Time in seconds before the authorization failure count is automatically decremented + /// A value of zero indicates that DA protection is disabled. + /// lockoutRecovery: Time in seconds after a lockoutAuth failure before use of lockoutAuth is allowed + /// A value of zero indicates that a reboot is required. + pub fn DictionaryAttackParameters( + &mut self, + lockHandle: &TPM_HANDLE, + newMaxTries: u32, + newRecoveryTime: u32, + lockoutRecovery: u32, + ) -> Result<(), TpmError> { + let req = TPM2_DictionaryAttackParameters_REQUEST::new( + lockHandle, + newMaxTries, + newRecoveryTime, + lockoutRecovery, + ); + + let mut resp = EmptyTpmResponse::default(); + self.dispatch(TPM_CC::DictionaryAttackParameters, req, &mut resp)?; + Ok(()) + } + + /// This command is used to determine which commands require assertion of Physical Presence + /// (PP) in addition to platformAuth/platformPolicy. + /// auth: TPM_RH_PLATFORM+PP + /// Auth Index: 1 + /// Auth Role: USER + Physical Presence + /// setList: List of commands to be added to those that will require that Physical Presence be + /// asserted + /// clearList: List of commands that will no longer require that Physical Presence be asserted + pub fn PP_Commands( + &mut self, + auth: &TPM_HANDLE, + setList: &Vec, + clearList: &Vec, + ) -> Result<(), TpmError> { + let req = TPM2_PP_Commands_REQUEST::new( + auth, + setList, + clearList, + ); + + let mut resp = EmptyTpmResponse::default(); + self.dispatch(TPM_CC::PP_Commands, req, &mut resp)?; + Ok(()) + } + + /// This command allows the platform to change the set of algorithms that are used by the TPM. + /// The algorithmSet setting is a vendor-dependent value. + /// authHandle: TPM_RH_PLATFORM + /// Auth Index: 1 + /// Auth Role: USER + /// algorithmSet: A TPM vendor-dependent value indicating the algorithm set selection + pub fn SetAlgorithmSet( + &mut self, + authHandle: &TPM_HANDLE, + algorithmSet: u32, + ) -> Result<(), TpmError> { + let req = TPM2_SetAlgorithmSet_REQUEST::new( + authHandle, + algorithmSet, + ); + + let mut resp = EmptyTpmResponse::default(); + self.dispatch(TPM_CC::SetAlgorithmSet, req, &mut resp)?; + Ok(()) + } + + /// This command uses platformPolicy and a TPM Vendor Authorization Key to authorize a Field + /// Upgrade Manifest. + /// authorization: TPM_RH_PLATFORM+{PP} + /// Auth Index:1 + /// Auth Role: ADMIN + /// keyHandle: Handle of a public area that contains the TPM Vendor Authorization Key that + /// will be used to validate manifestSignature + /// Auth Index: None + /// fuDigest: Digest of the first block in the field upgrade sequence + /// manifestSignature: Signature over fuDigest using the key associated with keyHandle (not optional) + /// One of: TPMS_SIGNATURE_RSASSA, TPMS_SIGNATURE_RSAPSS, TPMS_SIGNATURE_ECDSA, + /// TPMS_SIGNATURE_ECDAA, TPMS_SIGNATURE_SM2, TPMS_SIGNATURE_ECSCHNORR, TPMT_HA, + /// TPMS_SCHEME_HASH, TPMS_NULL_SIGNATURE. + pub fn FieldUpgradeStart( + &mut self, + authorization: &TPM_HANDLE, + keyHandle: &TPM_HANDLE, + fuDigest: &Vec, + manifestSignature: &Option, + ) -> Result<(), TpmError> { + let req = TPM2_FieldUpgradeStart_REQUEST::new( + authorization, + keyHandle, + fuDigest, + manifestSignature, + ); + + let mut resp = EmptyTpmResponse::default(); + self.dispatch(TPM_CC::FieldUpgradeStart, req, &mut resp)?; + Ok(()) + } + + /// This command will take the actual field upgrade image to be installed on the TPM. The + /// exact format of fuData is vendor-specific. This command is only possible following a + /// successful TPM2_FieldUpgradeStart(). If the TPM has not received a properly authorized + /// TPM2_FieldUpgradeStart(), then the TPM shall return TPM_RC_FIELDUPGRADE. + /// fuData: Field upgrade image data + /// nextDigest - Tagged digest of the next block + /// TPM_ALG_NULL if field update is complete + /// firstDigest - Tagged digest of the first block of the sequence + pub fn FieldUpgradeData( + &mut self, + fuData: &Vec, + ) -> Result { + let req = TPM2_FieldUpgradeData_REQUEST::new( + fuData, + ); + + let mut resp = FieldUpgradeDataResponse::default(); + self.dispatch(TPM_CC::FieldUpgradeData, req, &mut resp)?; + Ok(resp) + } + + /// This command is used to read a copy of the current firmware installed in the TPM. + /// sequenceNumber: The number of previous calls to this command in this sequence + /// set to 0 on the first call + /// fuData - Field upgrade image data + pub fn FirmwareRead( + &mut self, + sequenceNumber: u32, + ) -> Result, TpmError> { + let req = TPM2_FirmwareRead_REQUEST::new( + sequenceNumber, + ); + + let mut resp = FirmwareReadResponse::default(); + self.dispatch(TPM_CC::FirmwareRead, req, &mut resp)?; + Ok(resp.fuData) + } + + /// This command saves a session context, object context, or sequence object context outside + /// the TPM. + /// saveHandle: Handle of the resource to save + /// Auth Index: None + /// context - This structure is used in TPM2_ContextLoad() and TPM2_ContextSave(). If the + /// values of the TPMS_CONTEXT structure in TPM2_ContextLoad() are not the same + /// as the values when the context was saved (TPM2_ContextSave()), then the TPM + /// shall not load the context. + pub fn ContextSave( + &mut self, + saveHandle: &TPM_HANDLE, + ) -> Result { + let req = TPM2_ContextSave_REQUEST::new( + saveHandle, + ); + + let mut resp = ContextSaveResponse::default(); + self.dispatch(TPM_CC::ContextSave, req, &mut resp)?; + Ok(resp.context) + } + + /// This command is used to reload a context that has been saved by TPM2_ContextSave(). + /// context: The context blob + /// handle - The handle assigned to the resource after it has been successfully loaded + pub fn ContextLoad( + &mut self, + context: &TPMS_CONTEXT, + ) -> Result { + let req = TPM2_ContextLoad_REQUEST::new( + context, + ); + + let mut resp = ContextLoadResponse::default(); + self.dispatch(TPM_CC::ContextLoad, req, &mut resp)?; + Ok(resp.handle) + } + + /// This command causes all context associated with a loaded object, sequence object, or + /// session to be removed from TPM memory. + /// flushHandle: The handle of the item to flush + /// NOTE This is a use of a handle as a parameter. + pub fn FlushContext( + &mut self, + flushHandle: &TPM_HANDLE, + ) -> Result<(), TpmError> { + let req = TPM2_FlushContext_REQUEST::new( + flushHandle, + ); + + let mut resp = EmptyTpmResponse::default(); + self.dispatch(TPM_CC::FlushContext, req, &mut resp)?; + Ok(()) + } + + /// This command allows certain Transient Objects to be made persistent or a persistent object + /// to be evicted. + /// auth: TPM_RH_OWNER or TPM_RH_PLATFORM+{PP} + /// Auth Handle: 1 + /// Auth Role: USER + /// objectHandle: The handle of a loaded object + /// Auth Index: None + /// persistentHandle: If objectHandle is a transient object handle, then this is the + /// persistent handle for the object + /// if objectHandle is a persistent object handle, then it shall be the same value as + /// persistentHandle + pub fn EvictControl( + &mut self, + auth: &TPM_HANDLE, + objectHandle: &TPM_HANDLE, + persistentHandle: &TPM_HANDLE, + ) -> Result<(), TpmError> { + let req = TPM2_EvictControl_REQUEST::new( + auth, + objectHandle, + persistentHandle, + ); + + let mut resp = EmptyTpmResponse::default(); + self.dispatch(TPM_CC::EvictControl, req, &mut resp)?; + Ok(()) + } + + /// This command reads the current TPMS_TIME_INFO structure that contains the current setting + /// of Time, Clock, resetCount, and restartCount. + /// currentTime - This structure is used in, e.g., the TPM2_GetTime() attestation and + /// TPM2_ReadClock(). + pub fn ReadClock( + &mut self, + ) -> Result { + let req = TPM2_ReadClock_REQUEST::default(); + + let mut resp = ReadClockResponse::default(); + self.dispatch(TPM_CC::ReadClock, req, &mut resp)?; + Ok(resp.currentTime) + } + + /// This command is used to advance the value of the TPMs Clock. The command will fail if + /// newTime is less than the current value of Clock or if the new time is greater than + /// FFFF00000000000016. If both of these checks succeed, Clock is set to newTime. If either of + /// these checks fails, the TPM shall return TPM_RC_VALUE and make no change to Clock. + /// auth: TPM_RH_OWNER or TPM_RH_PLATFORM+{PP} + /// Auth Handle: 1 + /// Auth Role: USER + /// newTime: New Clock setting in milliseconds + pub fn ClockSet( + &mut self, + auth: &TPM_HANDLE, + newTime: u64, + ) -> Result<(), TpmError> { + let req = TPM2_ClockSet_REQUEST::new( + auth, + newTime, + ); + + let mut resp = EmptyTpmResponse::default(); + self.dispatch(TPM_CC::ClockSet, req, &mut resp)?; + Ok(()) + } + + /// This command adjusts the rate of advance of Clock and Time to provide a better + /// approximation to real time. + /// auth: TPM_RH_OWNER or TPM_RH_PLATFORM+{PP} + /// Auth Handle: 1 + /// Auth Role: USER + /// rateAdjust: Adjustment to current Clock update rate + pub fn ClockRateAdjust( + &mut self, + auth: &TPM_HANDLE, + rateAdjust: TPM_CLOCK_ADJUST, + ) -> Result<(), TpmError> { + let req = TPM2_ClockRateAdjust_REQUEST::new( + auth, + rateAdjust, + ); + + let mut resp = EmptyTpmResponse::default(); + self.dispatch(TPM_CC::ClockRateAdjust, req, &mut resp)?; + Ok(()) + } + + /// This command returns various information regarding the TPM and its current state. + /// capability: Group selection; determines the format of the response + /// property: Further definition of information + /// propertyCount: Number of properties of the indicated type to return + /// moreData - Flag to indicate if there are more values of this type + /// capabilityData - The capability data + pub fn GetCapability( + &mut self, + capability: TPM_CAP, + property: u32, + propertyCount: u32, + ) -> Result { + let req = TPM2_GetCapability_REQUEST::new( + capability, + property, + propertyCount, + ); + + let mut resp = GetCapabilityResponse::default(); + self.dispatch(TPM_CC::GetCapability, req, &mut resp)?; + Ok(resp) + } + + /// This command is used to check to see if specific combinations of algorithm parameters are supported. + /// parameters: Algorithm parameters to be validated + /// One of: TPMS_KEYEDHASH_PARMS, TPMS_SYMCIPHER_PARMS, TPMS_RSA_PARMS, TPMS_ECC_PARMS, + /// TPMS_ASYM_PARMS. + pub fn TestParms( + &mut self, + parameters: &Option, + ) -> Result<(), TpmError> { + let req = TPM2_TestParms_REQUEST::new( + parameters, + ); + + let mut resp = EmptyTpmResponse::default(); + self.dispatch(TPM_CC::TestParms, req, &mut resp)?; + Ok(()) + } + + /// This command defines the attributes of an NV Index and causes the TPM to reserve space to + /// hold the data associated with the NV Index. If a definition already exists at the NV + /// Index, the TPM will return TPM_RC_NV_DEFINED. + /// authHandle: TPM_RH_OWNER or TPM_RH_PLATFORM+{PP} + /// Auth Index: 1 + /// Auth Role: USER + /// auth: The authorization value + /// publicInfo: The public parameters of the NV area + pub fn NV_DefineSpace( + &mut self, + authHandle: &TPM_HANDLE, + auth: &Vec, + publicInfo: &TPMS_NV_PUBLIC, + ) -> Result<(), TpmError> { + let req = TPM2_NV_DefineSpace_REQUEST::new( + authHandle, + auth, + publicInfo, + ); + + let mut resp = EmptyTpmResponse::default(); + self.dispatch(TPM_CC::NV_DefineSpace, req, &mut resp)?; + Ok(()) + } + + /// This command removes an Index from the TPM. + /// authHandle: TPM_RH_OWNER or TPM_RH_PLATFORM+{PP} + /// Auth Index: 1 + /// Auth Role: USER + /// nvIndex: The NV Index to remove from NV space + /// Auth Index: None + pub fn NV_UndefineSpace( + &mut self, + authHandle: &TPM_HANDLE, + nvIndex: &TPM_HANDLE, + ) -> Result<(), TpmError> { + let req = TPM2_NV_UndefineSpace_REQUEST::new( + authHandle, + nvIndex, + ); + + let mut resp = EmptyTpmResponse::default(); + self.dispatch(TPM_CC::NV_UndefineSpace, req, &mut resp)?; + Ok(()) + } + + /// This command allows removal of a platform-created NV Index that has TPMA_NV_POLICY_DELETE SET. + /// nvIndex: Index to be deleted + /// Auth Index: 1 + /// Auth Role: ADMIN + /// platform: TPM_RH_PLATFORM + {PP} + /// Auth Index: 2 + /// Auth Role: USER + pub fn NV_UndefineSpaceSpecial( + &mut self, + nvIndex: &TPM_HANDLE, + platform: &TPM_HANDLE, + ) -> Result<(), TpmError> { + let req = TPM2_NV_UndefineSpaceSpecial_REQUEST::new( + nvIndex, + platform, + ); + + let mut resp = EmptyTpmResponse::default(); + self.dispatch(TPM_CC::NV_UndefineSpaceSpecial, req, &mut resp)?; + Ok(()) + } + + /// This command is used to read the public area and Name of an NV Index. The public area of + /// an Index is not privacy-sensitive and no authorization is required to read this data. + /// nvIndex: The NV Index + /// Auth Index: None + /// nvPublic - The public area of the NV Index + /// nvName - The Name of the nvIndex + pub fn NV_ReadPublic( + &mut self, + nvIndex: &TPM_HANDLE, + ) -> Result { + let req = TPM2_NV_ReadPublic_REQUEST::new( + nvIndex, + ); + + let mut resp = NV_ReadPublicResponse::default(); + self.dispatch(TPM_CC::NV_ReadPublic, req, &mut resp)?; + Ok(resp) + } + + /// This command writes a value to an area in NV memory that was previously defined by + /// TPM2_NV_DefineSpace(). + /// authHandle: Handle indicating the source of the authorization value + /// Auth Index: 1 + /// Auth Role: USER + /// nvIndex: The NV Index of the area to write + /// Auth Index: None + /// data: The data to write + /// offset: The octet offset into the NV Area + pub fn NV_Write( + &mut self, + authHandle: &TPM_HANDLE, + nvIndex: &TPM_HANDLE, + data: &Vec, + offset: u16, + ) -> Result<(), TpmError> { + let req = TPM2_NV_Write_REQUEST::new( + authHandle, + nvIndex, + data, + offset, + ); + + let mut resp = EmptyTpmResponse::default(); + self.dispatch(TPM_CC::NV_Write, req, &mut resp)?; + Ok(()) + } + + /// This command is used to increment the value in an NV Index that has the TPM_NT_COUNTER + /// attribute. The data value of the NV Index is incremented by one. + /// authHandle: Handle indicating the source of the authorization value + /// Auth Index: 1 + /// Auth Role: USER + /// nvIndex: The NV Index to increment + /// Auth Index: None + pub fn NV_Increment( + &mut self, + authHandle: &TPM_HANDLE, + nvIndex: &TPM_HANDLE, + ) -> Result<(), TpmError> { + let req = TPM2_NV_Increment_REQUEST::new( + authHandle, + nvIndex, + ); + + let mut resp = EmptyTpmResponse::default(); + self.dispatch(TPM_CC::NV_Increment, req, &mut resp)?; + Ok(()) + } + + /// This command extends a value to an area in NV memory that was previously defined by + /// TPM2_NV_DefineSpace. + /// authHandle: Handle indicating the source of the authorization value + /// Auth Index: 1 + /// Auth Role: USER + /// nvIndex: The NV Index to extend + /// Auth Index: None + /// data: The data to extend + pub fn NV_Extend( + &mut self, + authHandle: &TPM_HANDLE, + nvIndex: &TPM_HANDLE, + data: &Vec, + ) -> Result<(), TpmError> { + let req = TPM2_NV_Extend_REQUEST::new( + authHandle, + nvIndex, + data, + ); + + let mut resp = EmptyTpmResponse::default(); + self.dispatch(TPM_CC::NV_Extend, req, &mut resp)?; + Ok(()) + } + + /// This command is used to SET bits in an NV Index that was created as a bit field. Any + /// number of bits from 0 to 64 may be SET. The contents of bits are ORed with the current + /// contents of the NV Index. + /// authHandle: Handle indicating the source of the authorization value + /// Auth Index: 1 + /// Auth Role: USER + /// nvIndex: NV Index of the area in which the bit is to be set + /// Auth Index: None + /// bits: The data to OR with the current contents + pub fn NV_SetBits( + &mut self, + authHandle: &TPM_HANDLE, + nvIndex: &TPM_HANDLE, + bits: u64, + ) -> Result<(), TpmError> { + let req = TPM2_NV_SetBits_REQUEST::new( + authHandle, + nvIndex, + bits, + ); + + let mut resp = EmptyTpmResponse::default(); + self.dispatch(TPM_CC::NV_SetBits, req, &mut resp)?; + Ok(()) + } + + /// If the TPMA_NV_WRITEDEFINE or TPMA_NV_WRITE_STCLEAR attributes of an NV location are SET, + /// then this command may be used to inhibit further writes of the NV Index. + /// authHandle: Handle indicating the source of the authorization value + /// Auth Index: 1 + /// Auth Role: USER + /// nvIndex: The NV Index of the area to lock + /// Auth Index: None + pub fn NV_WriteLock( + &mut self, + authHandle: &TPM_HANDLE, + nvIndex: &TPM_HANDLE, + ) -> Result<(), TpmError> { + let req = TPM2_NV_WriteLock_REQUEST::new( + authHandle, + nvIndex, + ); + + let mut resp = EmptyTpmResponse::default(); + self.dispatch(TPM_CC::NV_WriteLock, req, &mut resp)?; + Ok(()) + } + + /// The command will SET TPMA_NV_WRITELOCKED for all indexes that have their + /// TPMA_NV_GLOBALLOCK attribute SET. + /// authHandle: TPM_RH_OWNER or TPM_RH_PLATFORM+{PP} + /// Auth Index: 1 + /// Auth Role: USER + pub fn NV_GlobalWriteLock( + &mut self, + authHandle: &TPM_HANDLE, + ) -> Result<(), TpmError> { + let req = TPM2_NV_GlobalWriteLock_REQUEST::new( + authHandle, + ); + + let mut resp = EmptyTpmResponse::default(); + self.dispatch(TPM_CC::NV_GlobalWriteLock, req, &mut resp)?; + Ok(()) + } + + /// This command reads a value from an area in NV memory previously defined by TPM2_NV_DefineSpace(). + /// authHandle: The handle indicating the source of the authorization value + /// Auth Index: 1 + /// Auth Role: USER + /// nvIndex: The NV Index to be read + /// Auth Index: None + /// size: Number of octets to read + /// offset: Octet offset into the NV area + /// This value shall be less than or equal to the size of the nvIndex data. + /// data - The data read + pub fn NV_Read( + &mut self, + authHandle: &TPM_HANDLE, + nvIndex: &TPM_HANDLE, + size: u16, + offset: u16, + ) -> Result, TpmError> { + let req = TPM2_NV_Read_REQUEST::new( + authHandle, + nvIndex, + size, + offset, + ); + + let mut resp = NV_ReadResponse::default(); + self.dispatch(TPM_CC::NV_Read, req, &mut resp)?; + Ok(resp.data) + } + + /// If TPMA_NV_READ_STCLEAR is SET in an Index, then this command may be used to prevent + /// further reads of the NV Index until the next TPM2_Startup (TPM_SU_CLEAR). + /// authHandle: The handle indicating the source of the authorization value + /// Auth Index: 1 + /// Auth Role: USER + /// nvIndex: The NV Index to be locked + /// Auth Index: None + pub fn NV_ReadLock( + &mut self, + authHandle: &TPM_HANDLE, + nvIndex: &TPM_HANDLE, + ) -> Result<(), TpmError> { + let req = TPM2_NV_ReadLock_REQUEST::new( + authHandle, + nvIndex, + ); + + let mut resp = EmptyTpmResponse::default(); + self.dispatch(TPM_CC::NV_ReadLock, req, &mut resp)?; + Ok(()) + } + + /// This command allows the authorization secret for an NV Index to be changed. + /// nvIndex: Handle of the entity + /// Auth Index: 1 + /// Auth Role: ADMIN + /// newAuth: New authorization value + pub fn NV_ChangeAuth( + &mut self, + nvIndex: &TPM_HANDLE, + newAuth: &Vec, + ) -> Result<(), TpmError> { + let req = TPM2_NV_ChangeAuth_REQUEST::new( + nvIndex, + newAuth, + ); + + let mut resp = EmptyTpmResponse::default(); + self.dispatch(TPM_CC::NV_ChangeAuth, req, &mut resp)?; + Ok(()) + } + + /// The purpose of this command is to certify the contents of an NV Index or portion of an NV Index. + /// signHandle: Handle of the key used to sign the attestation structure + /// Auth Index: 1 + /// Auth Role: USER + /// authHandle: Handle indicating the source of the authorization value for the NV Index + /// Auth Index: 2 + /// Auth Role: USER + /// nvIndex: Index for the area to be certified + /// Auth Index: None + /// qualifyingData: User-provided qualifying data + /// inScheme: Signing scheme to use if the scheme for signHandle is TPM_ALG_NULL + /// One of: TPMS_SIG_SCHEME_RSASSA, TPMS_SIG_SCHEME_RSAPSS, TPMS_SIG_SCHEME_ECDSA, + /// TPMS_SIG_SCHEME_ECDAA, TPMS_SIG_SCHEME_SM2, TPMS_SIG_SCHEME_ECSCHNORR, + /// TPMS_SCHEME_HMAC, TPMS_SCHEME_HASH, TPMS_NULL_SIG_SCHEME. + /// size: Number of octets to certify + /// offset: Octet offset into the NV area + /// This value shall be less than or equal to the size of the nvIndex data. + /// certifyInfo - The structure that was signed + /// signature - The asymmetric signature over certifyInfo using the key referenced by signHandle + pub fn NV_Certify( + &mut self, + signHandle: &TPM_HANDLE, + authHandle: &TPM_HANDLE, + nvIndex: &TPM_HANDLE, + qualifyingData: &Vec, + inScheme: &Option, + size: u16, + offset: u16, + ) -> Result { + let req = TPM2_NV_Certify_REQUEST::new( + signHandle, + authHandle, + nvIndex, + qualifyingData, + inScheme, + size, + offset, + ); + + let mut resp = NV_CertifyResponse::default(); + self.dispatch(TPM_CC::NV_Certify, req, &mut resp)?; + Ok(resp) + } + + /// The purpose of this command is to obtain information about an Attached Component + /// referenced by an AC handle. + /// ac: Handle indicating the Attached Component + /// Auth Index: None + /// capability: Starting info type + /// count: Maximum number of values to return + /// moreData - Flag to indicate whether there are more values + /// capabilitiesData - List of capabilities + pub fn AC_GetCapability( + &mut self, + ac: &TPM_HANDLE, + capability: TPM_AT, + count: u32, + ) -> Result { + let req = TPM2_AC_GetCapability_REQUEST::new( + ac, + capability, + count, + ); + + let mut resp = AC_GetCapabilityResponse::default(); + self.dispatch(TPM_CC::AC_GetCapability, req, &mut resp)?; + Ok(resp) + } + + /// The purpose of this command is to send (copy) a loaded object from the TPM to an Attached Component. + /// sendObject: Handle of the object being sent to ac + /// Auth Index: 1 + /// Auth Role: DUP + /// authHandle: The handle indicating the source of the authorization value + /// Auth Index: 2 + /// Auth Role: USER + /// ac: Handle indicating the Attached Component to which the object will be sent + /// Auth Index: None + /// acDataIn: Optional non sensitive information related to the object + /// acDataOut - May include AC specific data or information about an error. + pub fn AC_Send( + &mut self, + sendObject: &TPM_HANDLE, + authHandle: &TPM_HANDLE, + ac: &TPM_HANDLE, + acDataIn: &Vec, + ) -> Result { + let req = TPM2_AC_Send_REQUEST::new( + sendObject, + authHandle, + ac, + acDataIn, + ); + + let mut resp = AC_SendResponse::default(); + self.dispatch(TPM_CC::AC_Send, req, &mut resp)?; + Ok(resp.acDataOut) + } + + /// This command allows qualification of the sending (copying) of an Object to an Attached + /// Component (AC). Qualification includes selection of the receiving AC and the method of + /// authentication for the AC, and, in certain circumstances, the Object to be sent may be specified. + /// policySession: Handle for the policy session being extended + /// Auth Index: None + /// objectName: The Name of the Object to be sent + /// authHandleName: The Name associated with authHandle used in the TPM2_AC_Send() command + /// acName: The Name of the Attached Component to which the Object will be sent + /// includeObject: If SET, objectName will be included in the value in policySessionpolicyDigest + pub fn Policy_AC_SendSelect( + &mut self, + policySession: &TPM_HANDLE, + objectName: &Vec, + authHandleName: &Vec, + acName: &Vec, + includeObject: u8, + ) -> Result<(), TpmError> { + let req = TPM2_Policy_AC_SendSelect_REQUEST::new( + policySession, + objectName, + authHandleName, + acName, + includeObject, + ); + + let mut resp = EmptyTpmResponse::default(); + self.dispatch(TPM_CC::Policy_AC_SendSelect, req, &mut resp)?; + Ok(()) + } + + /// This command is used to set the time remaining before an Authenticated Countdown Timer + /// (ACT) expires. + /// actHandle: Handle of the selected ACT + /// Auth Index: 1 + /// Auth Role: USER + /// startTimeout: The start timeout value for the ACT in seconds + pub fn ACT_SetTimeout( + &mut self, + actHandle: &TPM_HANDLE, + startTimeout: u32, + ) -> Result<(), TpmError> { + let req = TPM2_ACT_SetTimeout_REQUEST::new( + actHandle, + startTimeout, + ); + + let mut resp = EmptyTpmResponse::default(); + self.dispatch(TPM_CC::ACT_SetTimeout, req, &mut resp)?; + Ok(()) + } + + /// This is a placeholder to allow testing of the dispatch code. + /// inputData: Dummy data + /// outputData - Dummy data + pub fn Vendor_TCG_Test( + &mut self, + inputData: &Vec, + ) -> Result, TpmError> { + let req = TPM2_Vendor_TCG_Test_REQUEST::new( + inputData, + ); + + let mut resp = Vendor_TCG_TestResponse::default(); + self.dispatch(TPM_CC::Vendor_TCG_Test, req, &mut resp)?; + Ok(resp.outputData) + } + +} + +/// Asynchronous TPM2 command methods +pub struct AsyncMethods<'a> { + tpm: &'a mut Tpm2, +} + +impl<'a> AsyncMethods<'a> { + /// TPM2_Startup() is always preceded by _TPM_Init, which is the physical indication that TPM + /// initialization is necessary because of a system-wide reset. TPM2_Startup() is only valid + /// after _TPM_Init. Additional TPM2_Startup() commands are not allowed after it has completed + /// successfully. If a TPM requires TPM2_Startup() and another command is received, or if the + /// TPM receives TPM2_Startup() when it is not required, the TPM shall return TPM_RC_INITIALIZE. + /// startupType: TPM_SU_CLEAR or TPM_SU_STATE + pub fn Startup_async( + &mut self, + startupType: TPM_SU, + ) -> Result<(), TpmError> { + let req = TPM2_Startup_REQUEST::new( + startupType, + ); + + self.tpm.dispatch_command(TPM_CC::Startup, &req)?; + Ok(()) + } + + /// This command is used to prepare the TPM for a power cycle. The shutdownType parameter + /// indicates how the subsequent TPM2_Startup() will be processed. + /// shutdownType: TPM_SU_CLEAR or TPM_SU_STATE + pub fn Shutdown_async( + &mut self, + shutdownType: TPM_SU, + ) -> Result<(), TpmError> { + let req = TPM2_Shutdown_REQUEST::new( + shutdownType, + ); + + self.tpm.dispatch_command(TPM_CC::Shutdown, &req)?; + Ok(()) + } + + /// This command causes the TPM to perform a test of its capabilities. If the fullTest is YES, + /// the TPM will test all functions. If fullTest = NO, the TPM will only test those functions + /// that have not previously been tested. + /// fullTest: YES if full test to be performed + /// NO if only test of untested functions required + pub fn SelfTest_async( + &mut self, + fullTest: u8, + ) -> Result<(), TpmError> { + let req = TPM2_SelfTest_REQUEST::new( + fullTest, + ); + + self.tpm.dispatch_command(TPM_CC::SelfTest, &req)?; + Ok(()) + } + + /// This command causes the TPM to perform a test of the selected algorithms. + /// toTest: List of algorithms that should be tested + /// toDoList - List of algorithms that need testing + pub fn IncrementalSelfTest_async( + &mut self, + toTest: &Vec, + ) -> Result<(), TpmError> { + let req = TPM2_IncrementalSelfTest_REQUEST::new( + toTest, + ); + + self.tpm.dispatch_command(TPM_CC::IncrementalSelfTest, &req)?; + Ok(()) + } + + /// This command returns manufacturer-specific information regarding the results of a + /// self-test and an indication of the test status. + /// outData - Test result data + /// contains manufacturer-specific information + /// testResult - TBD + pub fn GetTestResult_async( + &mut self, + ) -> Result<(), TpmError> { + let req = TPM2_GetTestResult_REQUEST::default(); + + self.tpm.dispatch_command(TPM_CC::GetTestResult, &req)?; + Ok(()) + } + + /// This command is used to start an authorization session using alternative methods of + /// establishing the session key (sessionKey). The session key is then used to derive values + /// used for authorization and for encrypting parameters. + /// tpmKey: Handle of a loaded decrypt key used to encrypt salt + /// may be TPM_RH_NULL + /// Auth Index: None + /// bind: Entity providing the authValue + /// may be TPM_RH_NULL + /// Auth Index: None + /// nonceCaller: Initial nonceCaller, sets nonceTPM size for the session + /// shall be at least 16 octets + /// encryptedSalt: Value encrypted according to the type of tpmKey + /// If tpmKey is TPM_RH_NULL, this shall be the Empty Buffer. + /// sessionType: Indicates the type of the session; simple HMAC or policy (including a trial policy) + /// symmetric: The algorithm and key size for parameter encryption + /// may select TPM_ALG_NULL + /// authHash: Hash algorithm to use for the session + /// Shall be a hash algorithm supported by the TPM and not TPM_ALG_NULL + /// handle - Handle for the newly created session + /// nonceTPM - The initial nonce from the TPM, used in the computation of the sessionKey + pub fn StartAuthSession_async( + &mut self, + tpmKey: &TPM_HANDLE, + bind: &TPM_HANDLE, + nonceCaller: &Vec, + encryptedSalt: &Vec, + sessionType: TPM_SE, + symmetric: &TPMT_SYM_DEF, + authHash: TPM_ALG_ID, + ) -> Result<(), TpmError> { + let req = TPM2_StartAuthSession_REQUEST::new( + tpmKey, + bind, + nonceCaller, + encryptedSalt, + sessionType, + symmetric, + authHash, + ); + + self.tpm.dispatch_command(TPM_CC::StartAuthSession, &req)?; + Ok(()) + } + + /// This command allows a policy authorization session to be returned to its initial state. + /// This command is used after the TPM returns TPM_RC_PCR_CHANGED. That response code + /// indicates that a policy will fail because the PCR have changed after TPM2_PolicyPCR() was + /// executed. Restarting the session allows the authorizations to be replayed because the + /// session restarts with the same nonceTPM. If the PCR are valid for the policy, the policy + /// may then succeed. + /// sessionHandle: The handle for the policy session + pub fn PolicyRestart_async( + &mut self, + sessionHandle: &TPM_HANDLE, + ) -> Result<(), TpmError> { + let req = TPM2_PolicyRestart_REQUEST::new( + sessionHandle, + ); + + self.tpm.dispatch_command(TPM_CC::PolicyRestart, &req)?; + Ok(()) + } + + /// This command is used to create an object that can be loaded into a TPM using TPM2_Load(). + /// If the command completes successfully, the TPM will create the new object and return the + /// objects creation data (creationData), its public area (outPublic), and its encrypted + /// sensitive area (outPrivate). Preservation of the returned data is the responsibility of + /// the caller. The object will need to be loaded (TPM2_Load()) before it may be used. The + /// only difference between the inPublic TPMT_PUBLIC template and the outPublic TPMT_PUBLIC + /// object is in the unique field. + /// parentHandle: Handle of parent for new object + /// Auth Index: 1 + /// Auth Role: USER + /// inSensitive: The sensitive data + /// inPublic: The public template + /// outsideInfo: Data that will be included in the creation data for this object to provide + /// permanent, verifiable linkage between this object and some object owner data + /// creationPCR: PCR that will be used in creation data + /// outPrivate - The private portion of the object + /// outPublic - The public portion of the created object + /// creationData - Contains a TPMS_CREATION_DATA + /// creationHash - Digest of creationData using nameAlg of outPublic + /// creationTicket - Ticket used by TPM2_CertifyCreation() to validate that the creation + /// data was produced by the TPM + pub fn Create_async( + &mut self, + parentHandle: &TPM_HANDLE, + inSensitive: &TPMS_SENSITIVE_CREATE, + inPublic: &TPMT_PUBLIC, + outsideInfo: &Vec, + creationPCR: &Vec, + ) -> Result<(), TpmError> { + let req = TPM2_Create_REQUEST::new( + parentHandle, + inSensitive, + inPublic, + outsideInfo, + creationPCR, + ); + + self.tpm.dispatch_command(TPM_CC::Create, &req)?; + Ok(()) + } + + /// This command is used to load objects into the TPM. This command is used when both a + /// TPM2B_PUBLIC and TPM2B_PRIVATE are to be loaded. If only a TPM2B_PUBLIC is to be loaded, + /// the TPM2_LoadExternal command is used. + /// parentHandle: TPM handle of parent key; shall not be a reserved handle + /// Auth Index: 1 + /// Auth Role: USER + /// inPrivate: The private portion of the object + /// inPublic: The public portion of the object + /// handle - Handle of type TPM_HT_TRANSIENT for the loaded object + /// name - Name of the loaded object + pub fn Load_async( + &mut self, + parentHandle: &TPM_HANDLE, + inPrivate: &TPM2B_PRIVATE, + inPublic: &TPMT_PUBLIC, + ) -> Result<(), TpmError> { + let req = TPM2_Load_REQUEST::new( + parentHandle, + inPrivate, + inPublic, + ); + + self.tpm.dispatch_command(TPM_CC::Load, &req)?; + Ok(()) + } + + /// This command is used to load an object that is not a Protected Object into the TPM. The + /// command allows loading of a public area or both a public and sensitive area. + /// inPrivate: The sensitive portion of the object (optional) + /// inPublic: The public portion of the object + /// hierarchy: Hierarchy with which the object area is associated + /// handle - Handle of type TPM_HT_TRANSIENT for the loaded object + /// name - Name of the loaded object + pub fn LoadExternal_async( + &mut self, + inPrivate: &TPMT_SENSITIVE, + inPublic: &TPMT_PUBLIC, + hierarchy: &TPM_HANDLE, + ) -> Result<(), TpmError> { + let req = TPM2_LoadExternal_REQUEST::new( + inPrivate, + inPublic, + hierarchy, + ); + + self.tpm.dispatch_command(TPM_CC::LoadExternal, &req)?; + Ok(()) + } + + /// This command allows access to the public area of a loaded object. + /// objectHandle: TPM handle of an object + /// Auth Index: None + /// outPublic - Structure containing the public area of an object + /// name - Name of the object + /// qualifiedName - The Qualified Name of the object + pub fn ReadPublic_async( + &mut self, + objectHandle: &TPM_HANDLE, + ) -> Result<(), TpmError> { + let req = TPM2_ReadPublic_REQUEST::new( + objectHandle, + ); + + self.tpm.dispatch_command(TPM_CC::ReadPublic, &req)?; + Ok(()) + } + + /// This command enables the association of a credential with an object in a way that ensures + /// that the TPM has validated the parameters of the credentialed object. + /// activateHandle: Handle of the object associated with certificate in credentialBlob + /// Auth Index: 1 + /// Auth Role: ADMIN + /// keyHandle: Loaded key used to decrypt the TPMS_SENSITIVE in credentialBlob + /// Auth Index: 2 + /// Auth Role: USER + /// credentialBlob: The credential + /// secret: KeyHandle algorithm-dependent encrypted seed that protects credentialBlob + /// certInfo - The decrypted certificate information + /// the data should be no larger than the size of the digest of the nameAlg + /// associated with keyHandle + pub fn ActivateCredential_async( + &mut self, + activateHandle: &TPM_HANDLE, + keyHandle: &TPM_HANDLE, + credentialBlob: &TPMS_ID_OBJECT, + secret: &Vec, + ) -> Result<(), TpmError> { + let req = TPM2_ActivateCredential_REQUEST::new( + activateHandle, + keyHandle, + credentialBlob, + secret, + ); + + self.tpm.dispatch_command(TPM_CC::ActivateCredential, &req)?; + Ok(()) + } + + /// This command allows the TPM to perform the actions required of a Certificate Authority + /// (CA) in creating a TPM2B_ID_OBJECT containing an activation credential. + /// handle: Loaded public area, used to encrypt the sensitive area containing the credential key + /// Auth Index: None + /// credential: The credential information + /// objectName: Name of the object to which the credential applies + /// credentialBlob - The credential + /// secret - Handle algorithm-dependent data that wraps the key that encrypts credentialBlob + pub fn MakeCredential_async( + &mut self, + handle: &TPM_HANDLE, + credential: &Vec, + objectName: &Vec, + ) -> Result<(), TpmError> { + let req = TPM2_MakeCredential_REQUEST::new( + handle, + credential, + objectName, + ); + + self.tpm.dispatch_command(TPM_CC::MakeCredential, &req)?; + Ok(()) + } + + /// This command returns the data in a loaded Sealed Data Object. + /// itemHandle: Handle of a loaded data object + /// Auth Index: 1 + /// Auth Role: USER + /// outData - Unsealed data + /// Size of outData is limited to be no more than 128 octets. + pub fn Unseal_async( + &mut self, + itemHandle: &TPM_HANDLE, + ) -> Result<(), TpmError> { + let req = TPM2_Unseal_REQUEST::new( + itemHandle, + ); + + self.tpm.dispatch_command(TPM_CC::Unseal, &req)?; + Ok(()) + } + + /// This command is used to change the authorization secret for a TPM-resident object. + /// objectHandle: Handle of the object + /// Auth Index: 1 + /// Auth Role: ADMIN + /// parentHandle: Handle of the parent + /// Auth Index: None + /// newAuth: New authorization value + /// outPrivate - Private area containing the new authorization value + pub fn ObjectChangeAuth_async( + &mut self, + objectHandle: &TPM_HANDLE, + parentHandle: &TPM_HANDLE, + newAuth: &Vec, + ) -> Result<(), TpmError> { + let req = TPM2_ObjectChangeAuth_REQUEST::new( + objectHandle, + parentHandle, + newAuth, + ); + + self.tpm.dispatch_command(TPM_CC::ObjectChangeAuth, &req)?; + Ok(()) + } + + /// This command creates an object and loads it in the TPM. This command allows creation of + /// any type of object (Primary, Ordinary, or Derived) depending on the type of parentHandle. + /// If parentHandle references a Primary Seed, then a Primary Object is created; if + /// parentHandle references a Storage Parent, then an Ordinary Object is created; and if + /// parentHandle references a Derivation Parent, then a Derived Object is generated. + /// parentHandle: Handle of a transient storage key, a persistent storage key, + /// TPM_RH_ENDORSEMENT, TPM_RH_OWNER, TPM_RH_PLATFORM+{PP}, or TPM_RH_NULL + /// Auth Index: 1 + /// Auth Role: USER + /// inSensitive: The sensitive data, see TPM 2.0 Part 1 Sensitive Values + /// inPublic: The public template + /// handle - Handle of type TPM_HT_TRANSIENT for created object + /// outPrivate - The sensitive area of the object (optional) + /// outPublic - The public portion of the created object + /// name - The name of the created object + pub fn CreateLoaded_async( + &mut self, + parentHandle: &TPM_HANDLE, + inSensitive: &TPMS_SENSITIVE_CREATE, + inPublic: &Vec, + ) -> Result<(), TpmError> { + let req = TPM2_CreateLoaded_REQUEST::new( + parentHandle, + inSensitive, + inPublic, + ); + + self.tpm.dispatch_command(TPM_CC::CreateLoaded, &req)?; + Ok(()) + } + + /// This command duplicates a loaded object so that it may be used in a different hierarchy. + /// The new parent key for the duplicate may be on the same or different TPM or TPM_RH_NULL. + /// Only the public area of newParentHandle is required to be loaded. + /// objectHandle: Loaded object to duplicate + /// Auth Index: 1 + /// Auth Role: DUP + /// newParentHandle: Shall reference the public area of an asymmetric key + /// Auth Index: None + /// encryptionKeyIn: Optional symmetric encryption key + /// The size for this key is set to zero when the TPM is to generate the key. This + /// parameter may be encrypted. + /// symmetricAlg: Definition for the symmetric algorithm to be used for the inner wrapper + /// may be TPM_ALG_NULL if no inner wrapper is applied + /// encryptionKeyOut - If the caller provided an encryption key or if symmetricAlg was + /// TPM_ALG_NULL, then this will be the Empty Buffer; otherwise, it + /// shall contain the TPM-generated, symmetric encryption key for the + /// inner wrapper. + /// duplicate - Private area that may be encrypted by encryptionKeyIn; and may be doubly encrypted + /// outSymSeed - Seed protected by the asymmetric algorithms of new parent (NP) + pub fn Duplicate_async( + &mut self, + objectHandle: &TPM_HANDLE, + newParentHandle: &TPM_HANDLE, + encryptionKeyIn: &Vec, + symmetricAlg: &TPMT_SYM_DEF_OBJECT, + ) -> Result<(), TpmError> { + let req = TPM2_Duplicate_REQUEST::new( + objectHandle, + newParentHandle, + encryptionKeyIn, + symmetricAlg, + ); + + self.tpm.dispatch_command(TPM_CC::Duplicate, &req)?; + Ok(()) + } + + /// This command allows the TPM to serve in the role as a Duplication Authority. If proper + /// authorization for use of the oldParent is provided, then an HMAC key and a symmetric key + /// are recovered from inSymSeed and used to integrity check and decrypt inDuplicate. A new + /// protection seed value is generated according to the methods appropriate for newParent and + /// the blob is re-encrypted and a new integrity value is computed. The re-encrypted blob is + /// returned in outDuplicate and the symmetric key returned in outSymKey. + /// oldParent: Parent of object + /// Auth Index: 1 + /// Auth Role: User + /// newParent: New parent of the object + /// Auth Index: None + /// inDuplicate: An object encrypted using symmetric key derived from inSymSeed + /// name: The Name of the object being rewrapped + /// inSymSeed: The seed for the symmetric key and HMAC key + /// needs oldParent private key to recover the seed and generate the symmetric key + /// outDuplicate - An object encrypted using symmetric key derived from outSymSeed + /// outSymSeed - Seed for a symmetric key protected by newParent asymmetric key + pub fn Rewrap_async( + &mut self, + oldParent: &TPM_HANDLE, + newParent: &TPM_HANDLE, + inDuplicate: &TPM2B_PRIVATE, + name: &Vec, + inSymSeed: &Vec, + ) -> Result<(), TpmError> { + let req = TPM2_Rewrap_REQUEST::new( + oldParent, + newParent, + inDuplicate, + name, + inSymSeed, + ); + + self.tpm.dispatch_command(TPM_CC::Rewrap, &req)?; + Ok(()) + } + + /// This command allows an object to be encrypted using the symmetric encryption values of a + /// Storage Key. After encryption, the object may be loaded and used in the new hierarchy. The + /// imported object (duplicate) may be singly encrypted, multiply encrypted, or unencrypted. + /// parentHandle: The handle of the new parent for the object + /// Auth Index: 1 + /// Auth Role: USER + /// encryptionKey: The optional symmetric encryption key used as the inner wrapper for duplicate + /// If symmetricAlg is TPM_ALG_NULL, then this parameter shall be the Empty Buffer. + /// objectPublic: The public area of the object to be imported + /// This is provided so that the integrity value for duplicate and the object + /// attributes can be checked. + /// NOTE Even if the integrity value of the object is not checked on input, the object + /// Name is required to create the integrity value for the imported object. + /// duplicate: The symmetrically encrypted duplicate object that may contain an inner + /// symmetric wrapper + /// inSymSeed: The seed for the symmetric key and HMAC key + /// inSymSeed is encrypted/encoded using the algorithms of newParent. + /// symmetricAlg: Definition for the symmetric algorithm to use for the inner wrapper + /// If this algorithm is TPM_ALG_NULL, no inner wrapper is present and encryptionKey + /// shall be the Empty Buffer. + /// outPrivate - The sensitive area encrypted with the symmetric key of parentHandle + pub fn Import_async( + &mut self, + parentHandle: &TPM_HANDLE, + encryptionKey: &Vec, + objectPublic: &TPMT_PUBLIC, + duplicate: &TPM2B_PRIVATE, + inSymSeed: &Vec, + symmetricAlg: &TPMT_SYM_DEF_OBJECT, + ) -> Result<(), TpmError> { + let req = TPM2_Import_REQUEST::new( + parentHandle, + encryptionKey, + objectPublic, + duplicate, + inSymSeed, + symmetricAlg, + ); + + self.tpm.dispatch_command(TPM_CC::Import, &req)?; + Ok(()) + } + + /// This command performs RSA encryption using the indicated padding scheme according to IETF + /// RFC 8017. If the scheme of keyHandle is TPM_ALG_NULL, then the caller may use inScheme to + /// specify the padding scheme. If scheme of keyHandle is not TPM_ALG_NULL, then inScheme + /// shall either be TPM_ALG_NULL or be the same as scheme (TPM_RC_SCHEME). + /// keyHandle: Reference to public portion of RSA key to use for encryption + /// Auth Index: None + /// message: Message to be encrypted + /// NOTE 1 The data type was chosen because it limits the overall size of the input to + /// no greater than the size of the largest RSA public key. This may be larger than + /// allowed for keyHandle. + /// inScheme: The padding scheme to use if scheme associated with keyHandle is TPM_ALG_NULL + /// One of: TPMS_KEY_SCHEME_ECDH, TPMS_KEY_SCHEME_ECMQV, TPMS_SIG_SCHEME_RSASSA, + /// TPMS_SIG_SCHEME_RSAPSS, TPMS_SIG_SCHEME_ECDSA, TPMS_SIG_SCHEME_ECDAA, + /// TPMS_SIG_SCHEME_SM2, TPMS_SIG_SCHEME_ECSCHNORR, TPMS_ENC_SCHEME_RSAES, + /// TPMS_ENC_SCHEME_OAEP, TPMS_SCHEME_HASH, TPMS_NULL_ASYM_SCHEME. + /// label: Optional label L to be associated with the message + /// Size of the buffer is zero if no label is present + /// NOTE 2 See description of label above. + /// outData - Encrypted output + pub fn RSA_Encrypt_async( + &mut self, + keyHandle: &TPM_HANDLE, + message: &Vec, + inScheme: &Option, + label: &Vec, + ) -> Result<(), TpmError> { + let req = TPM2_RSA_Encrypt_REQUEST::new( + keyHandle, + message, + inScheme, + label, + ); + + self.tpm.dispatch_command(TPM_CC::RSA_Encrypt, &req)?; + Ok(()) + } + + /// This command performs RSA decryption using the indicated padding scheme according to IETF + /// RFC 8017 ((PKCS#1). + /// keyHandle: RSA key to use for decryption + /// Auth Index: 1 + /// Auth Role: USER + /// cipherText: Cipher text to be decrypted + /// NOTE An encrypted RSA data block is the size of the public modulus. + /// inScheme: The padding scheme to use if scheme associated with keyHandle is TPM_ALG_NULL + /// One of: TPMS_KEY_SCHEME_ECDH, TPMS_KEY_SCHEME_ECMQV, TPMS_SIG_SCHEME_RSASSA, + /// TPMS_SIG_SCHEME_RSAPSS, TPMS_SIG_SCHEME_ECDSA, TPMS_SIG_SCHEME_ECDAA, + /// TPMS_SIG_SCHEME_SM2, TPMS_SIG_SCHEME_ECSCHNORR, TPMS_ENC_SCHEME_RSAES, + /// TPMS_ENC_SCHEME_OAEP, TPMS_SCHEME_HASH, TPMS_NULL_ASYM_SCHEME. + /// label: Label whose association with the message is to be verified + /// message - Decrypted output + pub fn RSA_Decrypt_async( + &mut self, + keyHandle: &TPM_HANDLE, + cipherText: &Vec, + inScheme: &Option, + label: &Vec, + ) -> Result<(), TpmError> { + let req = TPM2_RSA_Decrypt_REQUEST::new( + keyHandle, + cipherText, + inScheme, + label, + ); + + self.tpm.dispatch_command(TPM_CC::RSA_Decrypt, &req)?; + Ok(()) + } + + /// This command uses the TPM to generate an ephemeral key pair (de, Qe where Qe [de]G). It + /// uses the private ephemeral key and a loaded public key (QS) to compute the shared secret + /// value (P [hde]QS). + /// keyHandle: Handle of a loaded ECC key public area. + /// Auth Index: None + /// zPoint - Results of P h[de]Qs + /// pubPoint - Generated ephemeral public point (Qe) + pub fn ECDH_KeyGen_async( + &mut self, + keyHandle: &TPM_HANDLE, + ) -> Result<(), TpmError> { + let req = TPM2_ECDH_KeyGen_REQUEST::new( + keyHandle, + ); + + self.tpm.dispatch_command(TPM_CC::ECDH_KeyGen, &req)?; + Ok(()) + } + + /// This command uses the TPM to recover the Z value from a public point (QB) and a private + /// key (ds). It will perform the multiplication of the provided inPoint (QB) with the private + /// key (ds) and return the coordinates of the resultant point (Z = (xZ , yZ) [hds]QB; where h + /// is the cofactor of the curve). + /// keyHandle: Handle of a loaded ECC key + /// Auth Index: 1 + /// Auth Role: USER + /// inPoint: A public key + /// outPoint - X and Y coordinates of the product of the multiplication Z = (xZ , yZ) [hdS]QB + pub fn ECDH_ZGen_async( + &mut self, + keyHandle: &TPM_HANDLE, + inPoint: &TPMS_ECC_POINT, + ) -> Result<(), TpmError> { + let req = TPM2_ECDH_ZGen_REQUEST::new( + keyHandle, + inPoint, + ); + + self.tpm.dispatch_command(TPM_CC::ECDH_ZGen, &req)?; + Ok(()) + } + + /// This command returns the parameters of an ECC curve identified by its TCG-assigned curveID. + /// curveID: Parameter set selector + /// parameters - ECC parameters for the selected curve + pub fn ECC_Parameters_async( + &mut self, + curveID: TPM_ECC_CURVE, + ) -> Result<(), TpmError> { + let req = TPM2_ECC_Parameters_REQUEST::new( + curveID, + ); + + self.tpm.dispatch_command(TPM_CC::ECC_Parameters, &req)?; + Ok(()) + } + + /// This command supports two-phase key exchange protocols. The command is used in combination + /// with TPM2_EC_Ephemeral(). TPM2_EC_Ephemeral() generates an ephemeral key and returns the + /// public point of that ephemeral key along with a numeric value that allows the TPM to + /// regenerate the associated private key. + /// keyA: Handle of an unrestricted decryption key ECC + /// The private key referenced by this handle is used as dS,A + /// Auth Index: 1 + /// Auth Role: USER + /// inQsB: Other partys static public key (Qs,B = (Xs,B, Ys,B)) + /// inQeB: Other party's ephemeral public key (Qe,B = (Xe,B, Ye,B)) + /// inScheme: The key exchange scheme + /// counter: Value returned by TPM2_EC_Ephemeral() + /// outZ1 - X and Y coordinates of the computed value (scheme dependent) + /// outZ2 - X and Y coordinates of the second computed value (scheme dependent) + pub fn ZGen_2Phase_async( + &mut self, + keyA: &TPM_HANDLE, + inQsB: &TPMS_ECC_POINT, + inQeB: &TPMS_ECC_POINT, + inScheme: TPM_ALG_ID, + counter: u16, + ) -> Result<(), TpmError> { + let req = TPM2_ZGen_2Phase_REQUEST::new( + keyA, + inQsB, + inQeB, + inScheme, + counter, + ); + + self.tpm.dispatch_command(TPM_CC::ZGen_2Phase, &req)?; + Ok(()) + } + + /// This command performs ECC encryption as described in Part 1, Annex D. + /// keyHandle: Reference to public portion of ECC key to use for encryption + /// Auth Index: None + /// plainText: Plaintext to be encrypted + /// inScheme: The KDF to use if scheme associated with keyHandle is TPM_ALG_NULL + /// One of: TPMS_KDF_SCHEME_MGF1, TPMS_KDF_SCHEME_KDF1_SP800_56A, TPMS_KDF_SCHEME_KDF2, + /// TPMS_KDF_SCHEME_KDF1_SP800_108, TPMS_SCHEME_HASH, TPMS_NULL_KDF_SCHEME. + /// C1 - The public ephemeral key used for ECDH + /// C2 - The data block produced by the XOR process + /// C3 - The integrity value + pub fn ECC_Encrypt_async( + &mut self, + keyHandle: &TPM_HANDLE, + plainText: &Vec, + inScheme: &Option, + ) -> Result<(), TpmError> { + let req = TPM2_ECC_Encrypt_REQUEST::new( + keyHandle, + plainText, + inScheme, + ); + + self.tpm.dispatch_command(TPM_CC::ECC_Encrypt, &req)?; + Ok(()) + } + + /// This command performs ECC decryption. + /// keyHandle: ECC key to use for decryption + /// Auth Index: 1 + /// Auth Role: USER + /// C1: The public ephemeral key used for ECDH + /// C2: The data block produced by the XOR process + /// C3: The integrity value + /// inScheme: The KDF to use if scheme associated with keyHandle is TPM_ALG_NULL + /// One of: TPMS_KDF_SCHEME_MGF1, TPMS_KDF_SCHEME_KDF1_SP800_56A, TPMS_KDF_SCHEME_KDF2, + /// TPMS_KDF_SCHEME_KDF1_SP800_108, TPMS_SCHEME_HASH, TPMS_NULL_KDF_SCHEME. + /// plainText - Decrypted output + pub fn ECC_Decrypt_async( + &mut self, + keyHandle: &TPM_HANDLE, + C1: &TPMS_ECC_POINT, + C2: &Vec, + C3: &Vec, + inScheme: &Option, + ) -> Result<(), TpmError> { + let req = TPM2_ECC_Decrypt_REQUEST::new( + keyHandle, + C1, + C2, + C3, + inScheme, + ); + + self.tpm.dispatch_command(TPM_CC::ECC_Decrypt, &req)?; + Ok(()) + } + + /// NOTE 1 This command is deprecated, and TPM2_EncryptDecrypt2() is preferred. This should be + /// reflected in platform-specific specifications. + /// keyHandle: The symmetric key used for the operation + /// Auth Index: 1 + /// Auth Role: USER + /// decrypt: If YES, then the operation is decryption; if NO, the operation is encryption + /// mode: Symmetric encryption/decryption mode + /// this field shall match the default mode of the key or be TPM_ALG_NULL. + /// ivIn: An initial value as required by the algorithm + /// inData: The data to be encrypted/decrypted + /// outData - Encrypted or decrypted output + /// ivOut - Chaining value to use for IV in next round + pub fn EncryptDecrypt_async( + &mut self, + keyHandle: &TPM_HANDLE, + decrypt: u8, + mode: TPM_ALG_ID, + ivIn: &Vec, + inData: &Vec, + ) -> Result<(), TpmError> { + let req = TPM2_EncryptDecrypt_REQUEST::new( + keyHandle, + decrypt, + mode, + ivIn, + inData, + ); + + self.tpm.dispatch_command(TPM_CC::EncryptDecrypt, &req)?; + Ok(()) + } + + /// This command is identical to TPM2_EncryptDecrypt(), except that the inData parameter is + /// the first parameter. This permits inData to be parameter encrypted. + /// keyHandle: The symmetric key used for the operation + /// Auth Index: 1 + /// Auth Role: USER + /// inData: The data to be encrypted/decrypted + /// decrypt: If YES, then the operation is decryption; if NO, the operation is encryption + /// mode: Symmetric mode + /// this field shall match the default mode of the key or be TPM_ALG_NULL. + /// ivIn: An initial value as required by the algorithm + /// outData - Encrypted or decrypted output + /// ivOut - Chaining value to use for IV in next round + pub fn EncryptDecrypt2_async( + &mut self, + keyHandle: &TPM_HANDLE, + inData: &Vec, + decrypt: u8, + mode: TPM_ALG_ID, + ivIn: &Vec, + ) -> Result<(), TpmError> { + let req = TPM2_EncryptDecrypt2_REQUEST::new( + keyHandle, + inData, + decrypt, + mode, + ivIn, + ); + + self.tpm.dispatch_command(TPM_CC::EncryptDecrypt2, &req)?; + Ok(()) + } + + /// This command performs a hash operation on a data buffer and returns the results. + /// data: Data to be hashed + /// hashAlg: Algorithm for the hash being computed shall not be TPM_ALG_NULL + /// hierarchy: Hierarchy to use for the ticket (TPM_RH_NULL allowed) + /// outHash - Results + /// validation - Ticket indicating that the sequence of octets used to compute outDigest + /// did not start with TPM_GENERATED_VALUE + /// will be a NULL ticket if the digest may not be signed with a restricted key + pub fn Hash_async( + &mut self, + data: &Vec, + hashAlg: TPM_ALG_ID, + hierarchy: &TPM_HANDLE, + ) -> Result<(), TpmError> { + let req = TPM2_Hash_REQUEST::new( + data, + hashAlg, + hierarchy, + ); + + self.tpm.dispatch_command(TPM_CC::Hash, &req)?; + Ok(()) + } + + /// This command performs an HMAC on the supplied data using the indicated hash algorithm. + /// handle: Handle for the symmetric signing key providing the HMAC key + /// Auth Index: 1 + /// Auth Role: USER + /// buffer: HMAC data + /// hashAlg: Algorithm to use for HMAC + /// outHMAC - The returned HMAC in a sized buffer + pub fn HMAC_async( + &mut self, + handle: &TPM_HANDLE, + buffer: &Vec, + hashAlg: TPM_ALG_ID, + ) -> Result<(), TpmError> { + let req = TPM2_HMAC_REQUEST::new( + handle, + buffer, + hashAlg, + ); + + self.tpm.dispatch_command(TPM_CC::HMAC, &req)?; + Ok(()) + } + + /// This command performs an HMAC or a block cipher MAC on the supplied data using the + /// indicated algorithm. + /// handle: Handle for the symmetric signing key providing the MAC key + /// Auth Index: 1 + /// Auth Role: USER + /// buffer: MAC data + /// inScheme: Algorithm to use for MAC + /// outMAC - The returned MAC in a sized buffer + pub fn MAC_async( + &mut self, + handle: &TPM_HANDLE, + buffer: &Vec, + inScheme: TPM_ALG_ID, + ) -> Result<(), TpmError> { + let req = TPM2_MAC_REQUEST::new( + handle, + buffer, + inScheme, + ); + + self.tpm.dispatch_command(TPM_CC::MAC, &req)?; + Ok(()) + } + + /// This command returns the next bytesRequested octets from the random number generator (RNG). + /// bytesRequested: Number of octets to return + /// randomBytes - The random octets + pub fn GetRandom_async( + &mut self, + bytesRequested: u16, + ) -> Result<(), TpmError> { + let req = TPM2_GetRandom_REQUEST::new( + bytesRequested, + ); + + self.tpm.dispatch_command(TPM_CC::GetRandom, &req)?; + Ok(()) + } + + /// This command is used to add "additional information" to the RNG state. + /// inData: Additional information + pub fn StirRandom_async( + &mut self, + inData: &Vec, + ) -> Result<(), TpmError> { + let req = TPM2_StirRandom_REQUEST::new( + inData, + ); + + self.tpm.dispatch_command(TPM_CC::StirRandom, &req)?; + Ok(()) + } + + /// This command starts an HMAC sequence. The TPM will create and initialize an HMAC sequence + /// structure, assign a handle to the sequence, and set the authValue of the sequence object + /// to the value in auth. + /// handle: Handle of an HMAC key + /// Auth Index: 1 + /// Auth Role: USER + /// auth: Authorization value for subsequent use of the sequence + /// hashAlg: The hash algorithm to use for the HMAC + /// handle - A handle to reference the sequence + pub fn HMAC_Start_async( + &mut self, + handle: &TPM_HANDLE, + auth: &Vec, + hashAlg: TPM_ALG_ID, + ) -> Result<(), TpmError> { + let req = TPM2_HMAC_Start_REQUEST::new( + handle, + auth, + hashAlg, + ); + + self.tpm.dispatch_command(TPM_CC::HMAC_Start, &req)?; + Ok(()) + } + + /// This command starts a MAC sequence. The TPM will create and initialize a MAC sequence + /// structure, assign a handle to the sequence, and set the authValue of the sequence object + /// to the value in auth. + /// handle: Handle of a MAC key + /// Auth Index: 1 + /// Auth Role: USER + /// auth: Authorization value for subsequent use of the sequence + /// inScheme: The algorithm to use for the MAC + /// handle - A handle to reference the sequence + pub fn MAC_Start_async( + &mut self, + handle: &TPM_HANDLE, + auth: &Vec, + inScheme: TPM_ALG_ID, + ) -> Result<(), TpmError> { + let req = TPM2_MAC_Start_REQUEST::new( + handle, + auth, + inScheme, + ); + + self.tpm.dispatch_command(TPM_CC::MAC_Start, &req)?; + Ok(()) + } + + /// This command starts a hash or an Event Sequence. If hashAlg is an implemented hash, then a + /// hash sequence is started. If hashAlg is TPM_ALG_NULL, then an Event Sequence is started. + /// If hashAlg is neither an implemented algorithm nor TPM_ALG_NULL, then the TPM shall return + /// TPM_RC_HASH. + /// auth: Authorization value for subsequent use of the sequence + /// hashAlg: The hash algorithm to use for the hash sequence + /// An Event Sequence starts if this is TPM_ALG_NULL. + /// handle - A handle to reference the sequence + pub fn HashSequenceStart_async( + &mut self, + auth: &Vec, + hashAlg: TPM_ALG_ID, + ) -> Result<(), TpmError> { + let req = TPM2_HashSequenceStart_REQUEST::new( + auth, + hashAlg, + ); + + self.tpm.dispatch_command(TPM_CC::HashSequenceStart, &req)?; + Ok(()) + } + + /// This command is used to add data to a hash or HMAC sequence. The amount of data in buffer + /// may be any size up to the limits of the TPM. + /// sequenceHandle: Handle for the sequence object + /// Auth Index: 1 + /// Auth Role: USER + /// buffer: Data to be added to hash + pub fn SequenceUpdate_async( + &mut self, + sequenceHandle: &TPM_HANDLE, + buffer: &Vec, + ) -> Result<(), TpmError> { + let req = TPM2_SequenceUpdate_REQUEST::new( + sequenceHandle, + buffer, + ); + + self.tpm.dispatch_command(TPM_CC::SequenceUpdate, &req)?; + Ok(()) + } + + /// This command adds the last part of data, if any, to a hash/HMAC sequence and returns the result. + /// sequenceHandle: Authorization for the sequence + /// Auth Index: 1 + /// Auth Role: USER + /// buffer: Data to be added to the hash/HMAC + /// hierarchy: Hierarchy of the ticket for a hash + /// result - The returned HMAC or digest in a sized buffer + /// validation - Ticket indicating that the sequence of octets used to compute outDigest + /// did not start with TPM_GENERATED_VALUE + /// This is a NULL Ticket when the sequence is HMAC. + pub fn SequenceComplete_async( + &mut self, + sequenceHandle: &TPM_HANDLE, + buffer: &Vec, + hierarchy: &TPM_HANDLE, + ) -> Result<(), TpmError> { + let req = TPM2_SequenceComplete_REQUEST::new( + sequenceHandle, + buffer, + hierarchy, + ); + + self.tpm.dispatch_command(TPM_CC::SequenceComplete, &req)?; + Ok(()) + } + + /// This command adds the last part of data, if any, to an Event Sequence and returns the + /// result in a digest list. If pcrHandle references a PCR and not TPM_RH_NULL, then the + /// returned digest list is processed in the same manner as the digest list input parameter to + /// TPM2_PCR_Extend(). That is, if a bank contains a PCR associated with pcrHandle, it is + /// extended with the associated digest value from the list. + /// pcrHandle: PCR to be extended with the Event data + /// Auth Index: 1 + /// Auth Role: USER + /// sequenceHandle: Authorization for the sequence + /// Auth Index: 2 + /// Auth Role: USER + /// buffer: Data to be added to the Event + /// results - List of digests computed for the PCR + pub fn EventSequenceComplete_async( + &mut self, + pcrHandle: &TPM_HANDLE, + sequenceHandle: &TPM_HANDLE, + buffer: &Vec, + ) -> Result<(), TpmError> { + let req = TPM2_EventSequenceComplete_REQUEST::new( + pcrHandle, + sequenceHandle, + buffer, + ); + + self.tpm.dispatch_command(TPM_CC::EventSequenceComplete, &req)?; + Ok(()) + } + + /// The purpose of this command is to prove that an object with a specific Name is loaded in + /// the TPM. By certifying that the object is loaded, the TPM warrants that a public area with + /// a given Name is self-consistent and associated with a valid sensitive area. If a relying + /// party has a public area that has the same Name as a Name certified with this command, then + /// the values in that public area are correct. + /// objectHandle: Handle of the object to be certified + /// Auth Index: 1 + /// Auth Role: ADMIN + /// signHandle: Handle of the key used to sign the attestation structure + /// Auth Index: 2 + /// Auth Role: USER + /// qualifyingData: User provided qualifying data + /// inScheme: Signing scheme to use if the scheme for signHandle is TPM_ALG_NULL + /// One of: TPMS_SIG_SCHEME_RSASSA, TPMS_SIG_SCHEME_RSAPSS, TPMS_SIG_SCHEME_ECDSA, + /// TPMS_SIG_SCHEME_ECDAA, TPMS_SIG_SCHEME_SM2, TPMS_SIG_SCHEME_ECSCHNORR, + /// TPMS_SCHEME_HMAC, TPMS_SCHEME_HASH, TPMS_NULL_SIG_SCHEME. + /// certifyInfo - The structure that was signed + /// signature - The asymmetric signature over certifyInfo using the key referenced by signHandle + pub fn Certify_async( + &mut self, + objectHandle: &TPM_HANDLE, + signHandle: &TPM_HANDLE, + qualifyingData: &Vec, + inScheme: &Option, + ) -> Result<(), TpmError> { + let req = TPM2_Certify_REQUEST::new( + objectHandle, + signHandle, + qualifyingData, + inScheme, + ); + + self.tpm.dispatch_command(TPM_CC::Certify, &req)?; + Ok(()) + } + + /// This command is used to prove the association between an object and its creation data. The + /// TPM will validate that the ticket was produced by the TPM and that the ticket validates + /// the association between a loaded public area and the provided hash of the creation data + /// (creationHash). + /// signHandle: Handle of the key that will sign the attestation block + /// Auth Index: 1 + /// Auth Role: USER + /// objectHandle: The object associated with the creation data + /// Auth Index: None + /// qualifyingData: User-provided qualifying data + /// creationHash: Hash of the creation data produced by TPM2_Create() or TPM2_CreatePrimary() + /// inScheme: Signing scheme to use if the scheme for signHandle is TPM_ALG_NULL + /// One of: TPMS_SIG_SCHEME_RSASSA, TPMS_SIG_SCHEME_RSAPSS, TPMS_SIG_SCHEME_ECDSA, + /// TPMS_SIG_SCHEME_ECDAA, TPMS_SIG_SCHEME_SM2, TPMS_SIG_SCHEME_ECSCHNORR, + /// TPMS_SCHEME_HMAC, TPMS_SCHEME_HASH, TPMS_NULL_SIG_SCHEME. + /// creationTicket: Ticket produced by TPM2_Create() or TPM2_CreatePrimary() + /// certifyInfo - The structure that was signed + /// signature - The signature over certifyInfo + pub fn CertifyCreation_async( + &mut self, + signHandle: &TPM_HANDLE, + objectHandle: &TPM_HANDLE, + qualifyingData: &Vec, + creationHash: &Vec, + inScheme: &Option, + creationTicket: &TPMT_TK_CREATION, + ) -> Result<(), TpmError> { + let req = TPM2_CertifyCreation_REQUEST::new( + signHandle, + objectHandle, + qualifyingData, + creationHash, + inScheme, + creationTicket, + ); + + self.tpm.dispatch_command(TPM_CC::CertifyCreation, &req)?; + Ok(()) + } + + /// This command is used to quote PCR values. + /// signHandle: Handle of key that will perform signature + /// Auth Index: 1 + /// Auth Role: USER + /// qualifyingData: Data supplied by the caller + /// inScheme: Signing scheme to use if the scheme for signHandle is TPM_ALG_NULL + /// One of: TPMS_SIG_SCHEME_RSASSA, TPMS_SIG_SCHEME_RSAPSS, TPMS_SIG_SCHEME_ECDSA, + /// TPMS_SIG_SCHEME_ECDAA, TPMS_SIG_SCHEME_SM2, TPMS_SIG_SCHEME_ECSCHNORR, + /// TPMS_SCHEME_HMAC, TPMS_SCHEME_HASH, TPMS_NULL_SIG_SCHEME. + /// PCRselect: PCR set to quote + /// quoted - The quoted information + /// signature - The signature over quoted + pub fn Quote_async( + &mut self, + signHandle: &TPM_HANDLE, + qualifyingData: &Vec, + inScheme: &Option, + PCRselect: &Vec, + ) -> Result<(), TpmError> { + let req = TPM2_Quote_REQUEST::new( + signHandle, + qualifyingData, + inScheme, + PCRselect, + ); + + self.tpm.dispatch_command(TPM_CC::Quote, &req)?; + Ok(()) + } + + /// This command returns a digital signature of the audit session digest. + /// privacyAdminHandle: Handle of the privacy administrator (TPM_RH_ENDORSEMENT) + /// Auth Index: 1 + /// Auth Role: USER + /// signHandle: Handle of the signing key + /// Auth Index: 2 + /// Auth Role: USER + /// sessionHandle: Handle of the audit session + /// Auth Index: None + /// qualifyingData: User-provided qualifying data may be zero-length + /// inScheme: Signing scheme to use if the scheme for signHandle is TPM_ALG_NULL + /// One of: TPMS_SIG_SCHEME_RSASSA, TPMS_SIG_SCHEME_RSAPSS, TPMS_SIG_SCHEME_ECDSA, + /// TPMS_SIG_SCHEME_ECDAA, TPMS_SIG_SCHEME_SM2, TPMS_SIG_SCHEME_ECSCHNORR, + /// TPMS_SCHEME_HMAC, TPMS_SCHEME_HASH, TPMS_NULL_SIG_SCHEME. + /// auditInfo - The audit information that was signed + /// signature - The signature over auditInfo + pub fn GetSessionAuditDigest_async( + &mut self, + privacyAdminHandle: &TPM_HANDLE, + signHandle: &TPM_HANDLE, + sessionHandle: &TPM_HANDLE, + qualifyingData: &Vec, + inScheme: &Option, + ) -> Result<(), TpmError> { + let req = TPM2_GetSessionAuditDigest_REQUEST::new( + privacyAdminHandle, + signHandle, + sessionHandle, + qualifyingData, + inScheme, + ); + + self.tpm.dispatch_command(TPM_CC::GetSessionAuditDigest, &req)?; + Ok(()) + } + + /// This command returns the current value of the command audit digest, a digest of the + /// commands being audited, and the audit hash algorithm. These values are placed in an + /// attestation structure and signed with the key referenced by signHandle. + /// privacyHandle: Handle of the privacy administrator (TPM_RH_ENDORSEMENT) + /// Auth Index: 1 + /// Auth Role: USER + /// signHandle: The handle of the signing key + /// Auth Index: 2 + /// Auth Role: USER + /// qualifyingData: Other data to associate with this audit digest + /// inScheme: Signing scheme to use if the scheme for signHandle is TPM_ALG_NULL + /// One of: TPMS_SIG_SCHEME_RSASSA, TPMS_SIG_SCHEME_RSAPSS, TPMS_SIG_SCHEME_ECDSA, + /// TPMS_SIG_SCHEME_ECDAA, TPMS_SIG_SCHEME_SM2, TPMS_SIG_SCHEME_ECSCHNORR, + /// TPMS_SCHEME_HMAC, TPMS_SCHEME_HASH, TPMS_NULL_SIG_SCHEME. + /// auditInfo - The auditInfo that was signed + /// signature - The signature over auditInfo + pub fn GetCommandAuditDigest_async( + &mut self, + privacyHandle: &TPM_HANDLE, + signHandle: &TPM_HANDLE, + qualifyingData: &Vec, + inScheme: &Option, + ) -> Result<(), TpmError> { + let req = TPM2_GetCommandAuditDigest_REQUEST::new( + privacyHandle, + signHandle, + qualifyingData, + inScheme, + ); + + self.tpm.dispatch_command(TPM_CC::GetCommandAuditDigest, &req)?; + Ok(()) + } + + /// This command returns the current values of Time and Clock. + /// privacyAdminHandle: Handle of the privacy administrator (TPM_RH_ENDORSEMENT) + /// Auth Index: 1 + /// Auth Role: USER + /// signHandle: The keyHandle identifier of a loaded key that can perform digital signatures + /// Auth Index: 2 + /// Auth Role: USER + /// qualifyingData: Data to tick stamp + /// inScheme: Signing scheme to use if the scheme for signHandle is TPM_ALG_NULL + /// One of: TPMS_SIG_SCHEME_RSASSA, TPMS_SIG_SCHEME_RSAPSS, TPMS_SIG_SCHEME_ECDSA, + /// TPMS_SIG_SCHEME_ECDAA, TPMS_SIG_SCHEME_SM2, TPMS_SIG_SCHEME_ECSCHNORR, + /// TPMS_SCHEME_HMAC, TPMS_SCHEME_HASH, TPMS_NULL_SIG_SCHEME. + /// timeInfo - Standard TPM-generated attestation block + /// signature - The signature over timeInfo + pub fn GetTime_async( + &mut self, + privacyAdminHandle: &TPM_HANDLE, + signHandle: &TPM_HANDLE, + qualifyingData: &Vec, + inScheme: &Option, + ) -> Result<(), TpmError> { + let req = TPM2_GetTime_REQUEST::new( + privacyAdminHandle, + signHandle, + qualifyingData, + inScheme, + ); + + self.tpm.dispatch_command(TPM_CC::GetTime, &req)?; + Ok(()) + } + + /// The purpose of this command is to generate an X.509 certificate that proves an object with + /// a specific public key and attributes is loaded in the TPM. In contrast to TPM2_Certify, + /// which uses a TCG-defined data structure to convey attestation information, + /// TPM2_CertifyX509 encodes the attestation information in a DER-encoded X.509 certificate + /// that is compliant with RFC5280 Internet X.509 Public Key Infrastructure Certificate and + /// Certificate Revocation List (CRL) Profile. + /// objectHandle: Handle of the object to be certified + /// Auth Index: 1 + /// Auth Role: ADMIN + /// signHandle: Handle of the key used to sign the attestation structure + /// Auth Index: 2 + /// Auth Role: USER + /// reserved: Shall be an Empty Buffer + /// inScheme: Signing scheme to use if the scheme for signHandle is TPM_ALG_NULL + /// One of: TPMS_SIG_SCHEME_RSASSA, TPMS_SIG_SCHEME_RSAPSS, TPMS_SIG_SCHEME_ECDSA, + /// TPMS_SIG_SCHEME_ECDAA, TPMS_SIG_SCHEME_SM2, TPMS_SIG_SCHEME_ECSCHNORR, + /// TPMS_SCHEME_HMAC, TPMS_SCHEME_HASH, TPMS_NULL_SIG_SCHEME. + /// partialCertificate: A DER encoded partial certificate + /// addedToCertificate - A DER encoded SEQUENCE containing the DER encoded fields added to + /// partialCertificate to make it a complete RFC5280 TBSCertificate. + /// tbsDigest - The digest that was signed + /// signature - The signature over tbsDigest + pub fn CertifyX509_async( + &mut self, + objectHandle: &TPM_HANDLE, + signHandle: &TPM_HANDLE, + reserved: &Vec, + inScheme: &Option, + partialCertificate: &Vec, + ) -> Result<(), TpmError> { + let req = TPM2_CertifyX509_REQUEST::new( + objectHandle, + signHandle, + reserved, + inScheme, + partialCertificate, + ); + + self.tpm.dispatch_command(TPM_CC::CertifyX509, &req)?; + Ok(()) + } + + /// TPM2_Commit() performs the first part of an ECC anonymous signing operation. The TPM will + /// perform the point multiplications on the provided points and return intermediate signing + /// values. The signHandle parameter shall refer to an ECC key and the signing scheme must be + /// anonymous (TPM_RC_SCHEME). + /// signHandle: Handle of the key that will be used in the signing operation + /// Auth Index: 1 + /// Auth Role: USER + /// P1: A point (M) on the curve used by signHandle + /// s2: Octet array used to derive x-coordinate of a base point + /// y2: Y coordinate of the point associated with s2 + /// K - ECC point K [ds](x2, y2) + /// L - ECC point L [r](x2, y2) + /// E - ECC point E [r]P1 + /// counter - Least-significant 16 bits of commitCount + pub fn Commit_async( + &mut self, + signHandle: &TPM_HANDLE, + P1: &TPMS_ECC_POINT, + s2: &Vec, + y2: &Vec, + ) -> Result<(), TpmError> { + let req = TPM2_Commit_REQUEST::new( + signHandle, + P1, + s2, + y2, + ); + + self.tpm.dispatch_command(TPM_CC::Commit, &req)?; + Ok(()) + } + + /// TPM2_EC_Ephemeral() creates an ephemeral key for use in a two-phase key exchange protocol. + /// curveID: The curve for the computed ephemeral point + /// Q - Ephemeral public key Q [r]G + /// counter - Least-significant 16 bits of commitCount + pub fn EC_Ephemeral_async( + &mut self, + curveID: TPM_ECC_CURVE, + ) -> Result<(), TpmError> { + let req = TPM2_EC_Ephemeral_REQUEST::new( + curveID, + ); + + self.tpm.dispatch_command(TPM_CC::EC_Ephemeral, &req)?; + Ok(()) + } + + /// This command uses loaded keys to validate a signature on a message with the message digest + /// passed to the TPM. + /// keyHandle: Handle of public key that will be used in the validation + /// Auth Index: None + /// digest: Digest of the signed message + /// signature: Signature to be tested + /// One of: TPMS_SIGNATURE_RSASSA, TPMS_SIGNATURE_RSAPSS, TPMS_SIGNATURE_ECDSA, + /// TPMS_SIGNATURE_ECDAA, TPMS_SIGNATURE_SM2, TPMS_SIGNATURE_ECSCHNORR, TPMT_HA, + /// TPMS_SCHEME_HASH, TPMS_NULL_SIGNATURE. + /// validation - This ticket is produced by TPM2_VerifySignature(). This formulation is + /// used for multiple ticket uses. The ticket provides evidence that the TPM + /// has validated that a digest was signed by a key with the Name of keyName. + /// The ticket is computed by + pub fn VerifySignature_async( + &mut self, + keyHandle: &TPM_HANDLE, + digest: &Vec, + signature: &Option, + ) -> Result<(), TpmError> { + let req = TPM2_VerifySignature_REQUEST::new( + keyHandle, + digest, + signature, + ); + + self.tpm.dispatch_command(TPM_CC::VerifySignature, &req)?; + Ok(()) + } + + /// This command causes the TPM to sign an externally provided hash with the specified + /// symmetric or asymmetric signing key. + /// keyHandle: Handle of key that will perform signing + /// Auth Index: 1 + /// Auth Role: USER + /// digest: Digest to be signed + /// inScheme: Signing scheme to use if the scheme for keyHandle is TPM_ALG_NULL + /// One of: TPMS_SIG_SCHEME_RSASSA, TPMS_SIG_SCHEME_RSAPSS, TPMS_SIG_SCHEME_ECDSA, + /// TPMS_SIG_SCHEME_ECDAA, TPMS_SIG_SCHEME_SM2, TPMS_SIG_SCHEME_ECSCHNORR, + /// TPMS_SCHEME_HMAC, TPMS_SCHEME_HASH, TPMS_NULL_SIG_SCHEME. + /// validation: Proof that digest was created by the TPM + /// If keyHandle is not a restricted signing key, then this may be a NULL Ticket with + /// tag = TPM_ST_CHECKHASH. + /// signature - The signature + pub fn Sign_async( + &mut self, + keyHandle: &TPM_HANDLE, + digest: &Vec, + inScheme: &Option, + validation: &TPMT_TK_HASHCHECK, + ) -> Result<(), TpmError> { + let req = TPM2_Sign_REQUEST::new( + keyHandle, + digest, + inScheme, + validation, + ); + + self.tpm.dispatch_command(TPM_CC::Sign, &req)?; + Ok(()) + } + + /// This command may be used by the Privacy Administrator or platform to change the audit + /// status of a command or to set the hash algorithm used for the audit digest, but not both + /// at the same time. + /// auth: TPM_RH_OWNER or TPM_RH_PLATFORM+{PP} + /// Auth Index: 1 + /// Auth Role: USER + /// auditAlg: Hash algorithm for the audit digest; if TPM_ALG_NULL, then the hash is not changed + /// setList: List of commands that will be added to those that will be audited + /// clearList: List of commands that will no longer be audited + pub fn SetCommandCodeAuditStatus_async( + &mut self, + auth: &TPM_HANDLE, + auditAlg: TPM_ALG_ID, + setList: &Vec, + clearList: &Vec, + ) -> Result<(), TpmError> { + let req = TPM2_SetCommandCodeAuditStatus_REQUEST::new( + auth, + auditAlg, + setList, + clearList, + ); + + self.tpm.dispatch_command(TPM_CC::SetCommandCodeAuditStatus, &req)?; + Ok(()) + } + + /// This command is used to cause an update to the indicated PCR. The digests parameter + /// contains one or more tagged digest values identified by an algorithm ID. For each digest, + /// the PCR associated with pcrHandle is Extended into the bank identified by the tag (hashAlg). + /// pcrHandle: Handle of the PCR + /// Auth Handle: 1 + /// Auth Role: USER + /// digests: List of tagged digest values to be extended + pub fn PCR_Extend_async( + &mut self, + pcrHandle: &TPM_HANDLE, + digests: &Vec, + ) -> Result<(), TpmError> { + let req = TPM2_PCR_Extend_REQUEST::new( + pcrHandle, + digests, + ); + + self.tpm.dispatch_command(TPM_CC::PCR_Extend, &req)?; + Ok(()) + } + + /// This command is used to cause an update to the indicated PCR. + /// pcrHandle: Handle of the PCR + /// Auth Handle: 1 + /// Auth Role: USER + /// eventData: Event data in sized buffer + /// digests - Table 80 shows the basic hash-agile structure used in this specification. To + /// handle hash agility, this structure uses the hashAlg parameter to indicate + /// the algorithm used to compute the digest and, by implication, the size of + /// the digest. + pub fn PCR_Event_async( + &mut self, + pcrHandle: &TPM_HANDLE, + eventData: &Vec, + ) -> Result<(), TpmError> { + let req = TPM2_PCR_Event_REQUEST::new( + pcrHandle, + eventData, + ); + + self.tpm.dispatch_command(TPM_CC::PCR_Event, &req)?; + Ok(()) + } + + /// This command returns the values of all PCR specified in pcrSelectionIn. + /// pcrSelectionIn: The selection of PCR to read + /// pcrUpdateCounter - The current value of the PCR update counter + /// pcrSelectionOut - The PCR in the returned list + /// pcrValues - The contents of the PCR indicated in pcrSelectOut-˃ pcrSelection[] as + /// tagged digests + pub fn PCR_Read_async( + &mut self, + pcrSelectionIn: &Vec, + ) -> Result<(), TpmError> { + let req = TPM2_PCR_Read_REQUEST::new( + pcrSelectionIn, + ); + + self.tpm.dispatch_command(TPM_CC::PCR_Read, &req)?; + Ok(()) + } + + /// This command is used to set the desired PCR allocation of PCR and algorithms. This command + /// requires Platform Authorization. + /// authHandle: TPM_RH_PLATFORM+{PP} + /// Auth Index: 1 + /// Auth Role: USER + /// pcrAllocation: The requested allocation + /// allocationSuccess - YES if the allocation succeeded + /// maxPCR - Maximum number of PCR that may be in a bank + /// sizeNeeded - Number of octets required to satisfy the request + /// sizeAvailable - Number of octets available. Computed before the allocation. + pub fn PCR_Allocate_async( + &mut self, + authHandle: &TPM_HANDLE, + pcrAllocation: &Vec, + ) -> Result<(), TpmError> { + let req = TPM2_PCR_Allocate_REQUEST::new( + authHandle, + pcrAllocation, + ); + + self.tpm.dispatch_command(TPM_CC::PCR_Allocate, &req)?; + Ok(()) + } + + /// This command is used to associate a policy with a PCR or group of PCR. The policy + /// determines the conditions under which a PCR may be extended or reset. + /// authHandle: TPM_RH_PLATFORM+{PP} + /// Auth Index: 1 + /// Auth Role: USER + /// authPolicy: The desired authPolicy + /// hashAlg: The hash algorithm of the policy + /// pcrNum: The PCR for which the policy is to be set + pub fn PCR_SetAuthPolicy_async( + &mut self, + authHandle: &TPM_HANDLE, + authPolicy: &Vec, + hashAlg: TPM_ALG_ID, + pcrNum: &TPM_HANDLE, + ) -> Result<(), TpmError> { + let req = TPM2_PCR_SetAuthPolicy_REQUEST::new( + authHandle, + authPolicy, + hashAlg, + pcrNum, + ); + + self.tpm.dispatch_command(TPM_CC::PCR_SetAuthPolicy, &req)?; + Ok(()) + } + + /// This command changes the authValue of a PCR or group of PCR. + /// pcrHandle: Handle for a PCR that may have an authorization value set + /// Auth Index: 1 + /// Auth Role: USER + /// auth: The desired authorization value + pub fn PCR_SetAuthValue_async( + &mut self, + pcrHandle: &TPM_HANDLE, + auth: &Vec, + ) -> Result<(), TpmError> { + let req = TPM2_PCR_SetAuthValue_REQUEST::new( + pcrHandle, + auth, + ); + + self.tpm.dispatch_command(TPM_CC::PCR_SetAuthValue, &req)?; + Ok(()) + } + + /// If the attribute of a PCR allows the PCR to be reset and proper authorization is provided, + /// then this command may be used to set the PCR in all banks to zero. The attributes of the + /// PCR may restrict the locality that can perform the reset operation. + /// pcrHandle: The PCR to reset + /// Auth Index: 1 + /// Auth Role: USER + pub fn PCR_Reset_async( + &mut self, + pcrHandle: &TPM_HANDLE, + ) -> Result<(), TpmError> { + let req = TPM2_PCR_Reset_REQUEST::new( + pcrHandle, + ); + + self.tpm.dispatch_command(TPM_CC::PCR_Reset, &req)?; + Ok(()) + } + + /// This command includes a signed authorization in a policy. The command ties the policy to a + /// signing key by including the Name of the signing key in the policyDigest + /// authObject: Handle for a key that will validate the signature + /// Auth Index: None + /// policySession: Handle for the policy session being extended + /// Auth Index: None + /// nonceTPM: The policy nonce for the session + /// This can be the Empty Buffer. + /// cpHashA: Digest of the command parameters to which this authorization is limited + /// This is not the cpHash for this command but the cpHash for the command to which + /// this policy session will be applied. If it is not limited, the parameter will be + /// the Empty Buffer. + /// policyRef: A reference to a policy relating to the authorization may be the Empty Buffer + /// Size is limited to be no larger than the nonce size supported on the TPM. + /// expiration: Time when authorization will expire, measured in seconds from the time that + /// nonceTPM was generated + /// If expiration is non-negative, a NULL Ticket is returned. See 23.2.5. + /// auth: Signed authorization (not optional) + /// One of: TPMS_SIGNATURE_RSASSA, TPMS_SIGNATURE_RSAPSS, TPMS_SIGNATURE_ECDSA, + /// TPMS_SIGNATURE_ECDAA, TPMS_SIGNATURE_SM2, TPMS_SIGNATURE_ECSCHNORR, TPMT_HA, + /// TPMS_SCHEME_HASH, TPMS_NULL_SIGNATURE. + /// timeout - Implementation-specific time value, used to indicate to the TPM when the + /// ticket expires + /// NOTE If policyTicket is a NULL Ticket, then this shall be the Empty Buffer. + /// policyTicket - Produced if the command succeeds and expiration in the command was + /// non-zero; this ticket will use the TPMT_ST_AUTH_SIGNED structure tag. + /// See 23.2.5 + pub fn PolicySigned_async( + &mut self, + authObject: &TPM_HANDLE, + policySession: &TPM_HANDLE, + nonceTPM: &Vec, + cpHashA: &Vec, + policyRef: &Vec, + expiration: i32, + auth: &Option, + ) -> Result<(), TpmError> { + let req = TPM2_PolicySigned_REQUEST::new( + authObject, + policySession, + nonceTPM, + cpHashA, + policyRef, + expiration, + auth, + ); + + self.tpm.dispatch_command(TPM_CC::PolicySigned, &req)?; + Ok(()) + } + + /// This command includes a secret-based authorization to a policy. The caller proves + /// knowledge of the secret value using an authorization session using the authValue + /// associated with authHandle. A password session, an HMAC session, or a policy session + /// containing TPM2_PolicyAuthValue() or TPM2_PolicyPassword() will satisfy this requirement. + /// authHandle: Handle for an entity providing the authorization + /// Auth Index: 1 + /// Auth Role: USER + /// policySession: Handle for the policy session being extended + /// Auth Index: None + /// nonceTPM: The policy nonce for the session + /// This can be the Empty Buffer. + /// cpHashA: Digest of the command parameters to which this authorization is limited + /// This not the cpHash for this command but the cpHash for the command to which this + /// policy session will be applied. If it is not limited, the parameter will be the + /// Empty Buffer. + /// policyRef: A reference to a policy relating to the authorization may be the Empty Buffer + /// Size is limited to be no larger than the nonce size supported on the TPM. + /// expiration: Time when authorization will expire, measured in seconds from the time that + /// nonceTPM was generated + /// If expiration is non-negative, a NULL Ticket is returned. See 23.2.5. + /// timeout - Implementation-specific time value used to indicate to the TPM when the + /// ticket expires + /// policyTicket - Produced if the command succeeds and expiration in the command was + /// non-zero ( See 23.2.5). This ticket will use the TPMT_ST_AUTH_SECRET + /// structure tag + pub fn PolicySecret_async( + &mut self, + authHandle: &TPM_HANDLE, + policySession: &TPM_HANDLE, + nonceTPM: &Vec, + cpHashA: &Vec, + policyRef: &Vec, + expiration: i32, + ) -> Result<(), TpmError> { + let req = TPM2_PolicySecret_REQUEST::new( + authHandle, + policySession, + nonceTPM, + cpHashA, + policyRef, + expiration, + ); + + self.tpm.dispatch_command(TPM_CC::PolicySecret, &req)?; + Ok(()) + } + + /// This command is similar to TPM2_PolicySigned() except that it takes a ticket instead of a + /// signed authorization. The ticket represents a validated authorization that had an + /// expiration time associated with it. + /// policySession: Handle for the policy session being extended + /// Auth Index: None + /// timeout: Time when authorization will expire + /// The contents are TPM specific. This shall be the value returned when ticket was produced. + /// cpHashA: Digest of the command parameters to which this authorization is limited + /// If it is not limited, the parameter will be the Empty Buffer. + /// policyRef: Reference to a qualifier for the policy may be the Empty Buffer + /// authName: Name of the object that provided the authorization + /// ticket: An authorization ticket returned by the TPM in response to a TPM2_PolicySigned() + /// or TPM2_PolicySecret() + pub fn PolicyTicket_async( + &mut self, + policySession: &TPM_HANDLE, + timeout: &Vec, + cpHashA: &Vec, + policyRef: &Vec, + authName: &Vec, + ticket: &TPMT_TK_AUTH, + ) -> Result<(), TpmError> { + let req = TPM2_PolicyTicket_REQUEST::new( + policySession, + timeout, + cpHashA, + policyRef, + authName, + ticket, + ); + + self.tpm.dispatch_command(TPM_CC::PolicyTicket, &req)?; + Ok(()) + } + + /// This command allows options in authorizations without requiring that the TPM evaluate all + /// of the options. If a policy may be satisfied by different sets of conditions, the TPM need + /// only evaluate one set that satisfies the policy. This command will indicate that one of + /// the required sets of conditions has been satisfied. + /// policySession: Handle for the policy session being extended + /// Auth Index: None + /// pHashList: The list of hashes to check for a match + pub fn PolicyOR_async( + &mut self, + policySession: &TPM_HANDLE, + pHashList: &Vec, + ) -> Result<(), TpmError> { + let req = TPM2_PolicyOR_REQUEST::new( + policySession, + pHashList, + ); + + self.tpm.dispatch_command(TPM_CC::PolicyOR, &req)?; + Ok(()) + } + + /// This command is used to cause conditional gating of a policy based on PCR. This command + /// together with TPM2_PolicyOR() allows one group of authorizations to occur when PCR are in + /// one state and a different set of authorizations when the PCR are in a different state. + /// policySession: Handle for the policy session being extended + /// Auth Index: None + /// pcrDigest: Expected digest value of the selected PCR using the hash algorithm of the + /// session; may be zero length + /// pcrs: The PCR to include in the check digest + pub fn PolicyPCR_async( + &mut self, + policySession: &TPM_HANDLE, + pcrDigest: &Vec, + pcrs: &Vec, + ) -> Result<(), TpmError> { + let req = TPM2_PolicyPCR_REQUEST::new( + policySession, + pcrDigest, + pcrs, + ); + + self.tpm.dispatch_command(TPM_CC::PolicyPCR, &req)?; + Ok(()) + } + + /// This command indicates that the authorization will be limited to a specific locality. + /// policySession: Handle for the policy session being extended + /// Auth Index: None + /// locality: The allowed localities for the policy + pub fn PolicyLocality_async( + &mut self, + policySession: &TPM_HANDLE, + locality: TPMA_LOCALITY, + ) -> Result<(), TpmError> { + let req = TPM2_PolicyLocality_REQUEST::new( + policySession, + locality, + ); + + self.tpm.dispatch_command(TPM_CC::PolicyLocality, &req)?; + Ok(()) + } + + /// This command is used to cause conditional gating of a policy based on the contents of an + /// NV Index. It is an immediate assertion. The NV index is validated during the + /// TPM2_PolicyNV() command, not when the session is used for authorization. + /// authHandle: Handle indicating the source of the authorization value + /// Auth Index: 1 + /// Auth Role: USER + /// nvIndex: The NV Index of the area to read + /// Auth Index: None + /// policySession: Handle for the policy session being extended + /// Auth Index: None + /// operandB: The second operand + /// offset: The octet offset in the NV Index for the start of operand A + /// operation: The comparison to make + pub fn PolicyNV_async( + &mut self, + authHandle: &TPM_HANDLE, + nvIndex: &TPM_HANDLE, + policySession: &TPM_HANDLE, + operandB: &Vec, + offset: u16, + operation: TPM_EO, + ) -> Result<(), TpmError> { + let req = TPM2_PolicyNV_REQUEST::new( + authHandle, + nvIndex, + policySession, + operandB, + offset, + operation, + ); + + self.tpm.dispatch_command(TPM_CC::PolicyNV, &req)?; + Ok(()) + } + + /// This command is used to cause conditional gating of a policy based on the contents of the + /// TPMS_TIME_INFO structure. + /// policySession: Handle for the policy session being extended + /// Auth Index: None + /// operandB: The second operand + /// offset: The octet offset in the TPMS_TIME_INFO structure for the start of operand A + /// operation: The comparison to make + pub fn PolicyCounterTimer_async( + &mut self, + policySession: &TPM_HANDLE, + operandB: &Vec, + offset: u16, + operation: TPM_EO, + ) -> Result<(), TpmError> { + let req = TPM2_PolicyCounterTimer_REQUEST::new( + policySession, + operandB, + offset, + operation, + ); + + self.tpm.dispatch_command(TPM_CC::PolicyCounterTimer, &req)?; + Ok(()) + } + + /// This command indicates that the authorization will be limited to a specific command code. + /// policySession: Handle for the policy session being extended + /// Auth Index: None + /// code: The allowed commandCode + pub fn PolicyCommandCode_async( + &mut self, + policySession: &TPM_HANDLE, + code: TPM_CC, + ) -> Result<(), TpmError> { + let req = TPM2_PolicyCommandCode_REQUEST::new( + policySession, + code, + ); + + self.tpm.dispatch_command(TPM_CC::PolicyCommandCode, &req)?; + Ok(()) + } + + /// This command indicates that physical presence will need to be asserted at the time the + /// authorization is performed. + /// policySession: Handle for the policy session being extended + /// Auth Index: None + pub fn PolicyPhysicalPresence_async( + &mut self, + policySession: &TPM_HANDLE, + ) -> Result<(), TpmError> { + let req = TPM2_PolicyPhysicalPresence_REQUEST::new( + policySession, + ); + + self.tpm.dispatch_command(TPM_CC::PolicyPhysicalPresence, &req)?; + Ok(()) + } + + /// This command is used to allow a policy to be bound to a specific command and command parameters. + /// policySession: Handle for the policy session being extended + /// Auth Index: None + /// cpHashA: The cpHash added to the policy + pub fn PolicyCpHash_async( + &mut self, + policySession: &TPM_HANDLE, + cpHashA: &Vec, + ) -> Result<(), TpmError> { + let req = TPM2_PolicyCpHash_REQUEST::new( + policySession, + cpHashA, + ); + + self.tpm.dispatch_command(TPM_CC::PolicyCpHash, &req)?; + Ok(()) + } + + /// This command allows a policy to be bound to a specific set of TPM entities without being + /// bound to the parameters of the command. This is most useful for commands such as + /// TPM2_Duplicate() and for TPM2_PCR_Event() when the referenced PCR requires a policy. + /// policySession: Handle for the policy session being extended + /// Auth Index: None + /// nameHash: The digest to be added to the policy + pub fn PolicyNameHash_async( + &mut self, + policySession: &TPM_HANDLE, + nameHash: &Vec, + ) -> Result<(), TpmError> { + let req = TPM2_PolicyNameHash_REQUEST::new( + policySession, + nameHash, + ); + + self.tpm.dispatch_command(TPM_CC::PolicyNameHash, &req)?; + Ok(()) + } + + /// This command allows qualification of duplication to allow duplication to a selected new parent. + /// policySession: Handle for the policy session being extended + /// Auth Index: None + /// objectName: The Name of the object to be duplicated + /// newParentName: The Name of the new parent + /// includeObject: If YES, the objectName will be included in the value in policySessionpolicyDigest + pub fn PolicyDuplicationSelect_async( + &mut self, + policySession: &TPM_HANDLE, + objectName: &Vec, + newParentName: &Vec, + includeObject: u8, + ) -> Result<(), TpmError> { + let req = TPM2_PolicyDuplicationSelect_REQUEST::new( + policySession, + objectName, + newParentName, + includeObject, + ); + + self.tpm.dispatch_command(TPM_CC::PolicyDuplicationSelect, &req)?; + Ok(()) + } + + /// This command allows policies to change. If a policy were static, then it would be + /// difficult to add users to a policy. This command lets a policy authority sign a new policy + /// so that it may be used in an existing policy. + /// policySession: Handle for the policy session being extended + /// Auth Index: None + /// approvedPolicy: Digest of the policy being approved + /// policyRef: A policy qualifier + /// keySign: Name of a key that can sign a policy addition + /// checkTicket: Ticket validating that approvedPolicy and policyRef were signed by keySign + pub fn PolicyAuthorize_async( + &mut self, + policySession: &TPM_HANDLE, + approvedPolicy: &Vec, + policyRef: &Vec, + keySign: &Vec, + checkTicket: &TPMT_TK_VERIFIED, + ) -> Result<(), TpmError> { + let req = TPM2_PolicyAuthorize_REQUEST::new( + policySession, + approvedPolicy, + policyRef, + keySign, + checkTicket, + ); + + self.tpm.dispatch_command(TPM_CC::PolicyAuthorize, &req)?; + Ok(()) + } + + /// This command allows a policy to be bound to the authorization value of the authorized entity. + /// policySession: Handle for the policy session being extended + /// Auth Index: None + pub fn PolicyAuthValue_async( + &mut self, + policySession: &TPM_HANDLE, + ) -> Result<(), TpmError> { + let req = TPM2_PolicyAuthValue_REQUEST::new( + policySession, + ); + + self.tpm.dispatch_command(TPM_CC::PolicyAuthValue, &req)?; + Ok(()) + } + + /// This command allows a policy to be bound to the authorization value of the authorized object. + /// policySession: Handle for the policy session being extended + /// Auth Index: None + pub fn PolicyPassword_async( + &mut self, + policySession: &TPM_HANDLE, + ) -> Result<(), TpmError> { + let req = TPM2_PolicyPassword_REQUEST::new( + policySession, + ); + + self.tpm.dispatch_command(TPM_CC::PolicyPassword, &req)?; + Ok(()) + } + + /// This command returns the current policyDigest of the session. This command allows the TPM + /// to be used to perform the actions required to pre-compute the authPolicy for an object. + /// policySession: Handle for the policy session + /// Auth Index: None + /// policyDigest - The current value of the policySessionpolicyDigest + pub fn PolicyGetDigest_async( + &mut self, + policySession: &TPM_HANDLE, + ) -> Result<(), TpmError> { + let req = TPM2_PolicyGetDigest_REQUEST::new( + policySession, + ); + + self.tpm.dispatch_command(TPM_CC::PolicyGetDigest, &req)?; + Ok(()) + } + + /// This command allows a policy to be bound to the TPMA_NV_WRITTEN attributes. This is a + /// deferred assertion. Values are stored in the policy session context and checked when the + /// policy is used for authorization. + /// policySession: Handle for the policy session being extended + /// Auth Index: None + /// writtenSet: YES if NV Index is required to have been written + /// NO if NV Index is required not to have been written + pub fn PolicyNvWritten_async( + &mut self, + policySession: &TPM_HANDLE, + writtenSet: u8, + ) -> Result<(), TpmError> { + let req = TPM2_PolicyNvWritten_REQUEST::new( + policySession, + writtenSet, + ); + + self.tpm.dispatch_command(TPM_CC::PolicyNvWritten, &req)?; + Ok(()) + } + + /// This command allows a policy to be bound to a specific creation template. This is most + /// useful for an object creation command such as TPM2_Create(), TPM2_CreatePrimary(), or + /// TPM2_CreateLoaded(). + /// policySession: Handle for the policy session being extended + /// Auth Index: None + /// templateHash: The digest to be added to the policy + pub fn PolicyTemplate_async( + &mut self, + policySession: &TPM_HANDLE, + templateHash: &Vec, + ) -> Result<(), TpmError> { + let req = TPM2_PolicyTemplate_REQUEST::new( + policySession, + templateHash, + ); + + self.tpm.dispatch_command(TPM_CC::PolicyTemplate, &req)?; + Ok(()) + } + + /// This command provides a capability that is the equivalent of a revocable policy. With + /// TPM2_PolicyAuthorize(), the authorization ticket never expires, so the authorization may + /// not be withdrawn. With this command, the approved policy is kept in an NV Index location + /// so that the policy may be changed as needed to render the old policy unusable. + /// authHandle: Handle indicating the source of the authorization value + /// Auth Index: 1 + /// Auth Role: USER + /// nvIndex: The NV Index of the area to read + /// Auth Index: None + /// policySession: Handle for the policy session being extended + /// Auth Index: None + pub fn PolicyAuthorizeNV_async( + &mut self, + authHandle: &TPM_HANDLE, + nvIndex: &TPM_HANDLE, + policySession: &TPM_HANDLE, + ) -> Result<(), TpmError> { + let req = TPM2_PolicyAuthorizeNV_REQUEST::new( + authHandle, + nvIndex, + policySession, + ); + + self.tpm.dispatch_command(TPM_CC::PolicyAuthorizeNV, &req)?; + Ok(()) + } + + /// This command is used to create a Primary Object under one of the Primary Seeds or a + /// Temporary Object under TPM_RH_NULL. The command uses a TPM2B_PUBLIC as a template for the + /// object to be created. The size of the unique field shall not be checked for consistency + /// with the other object parameters. The command will create and load a Primary Object. The + /// sensitive area is not returned. + /// primaryHandle: TPM_RH_ENDORSEMENT, TPM_RH_OWNER, TPM_RH_PLATFORM+{PP}, or TPM_RH_NULL + /// Auth Index: 1 + /// Auth Role: USER + /// inSensitive: The sensitive data, see TPM 2.0 Part 1 Sensitive Values + /// inPublic: The public template + /// outsideInfo: Data that will be included in the creation data for this object to provide + /// permanent, verifiable linkage between this object and some object owner data + /// creationPCR: PCR that will be used in creation data + /// handle - Handle of type TPM_HT_TRANSIENT for created Primary Object + /// outPublic - The public portion of the created object + /// creationData - Contains a TPMT_CREATION_DATA + /// creationHash - Digest of creationData using nameAlg of outPublic + /// creationTicket - Ticket used by TPM2_CertifyCreation() to validate that the creation + /// data was produced by the TPM + /// name - The name of the created object + pub fn CreatePrimary_async( + &mut self, + primaryHandle: &TPM_HANDLE, + inSensitive: &TPMS_SENSITIVE_CREATE, + inPublic: &TPMT_PUBLIC, + outsideInfo: &Vec, + creationPCR: &Vec, + ) -> Result<(), TpmError> { + let req = TPM2_CreatePrimary_REQUEST::new( + primaryHandle, + inSensitive, + inPublic, + outsideInfo, + creationPCR, + ); + + self.tpm.dispatch_command(TPM_CC::CreatePrimary, &req)?; + Ok(()) + } + + /// This command enables and disables use of a hierarchy and its associated NV storage. The + /// command allows phEnable, phEnableNV, shEnable, and ehEnable to be changed when the proper + /// authorization is provided. + /// authHandle: TPM_RH_ENDORSEMENT, TPM_RH_OWNER or TPM_RH_PLATFORM+{PP} + /// Auth Index: 1 + /// Auth Role: USER + /// enable: The enable being modified + /// TPM_RH_ENDORSEMENT, TPM_RH_OWNER, TPM_RH_PLATFORM, or TPM_RH_PLATFORM_NV + /// state: YES if the enable should be SET, NO if the enable should be CLEAR + pub fn HierarchyControl_async( + &mut self, + authHandle: &TPM_HANDLE, + enable: &TPM_HANDLE, + state: u8, + ) -> Result<(), TpmError> { + let req = TPM2_HierarchyControl_REQUEST::new( + authHandle, + enable, + state, + ); + + self.tpm.dispatch_command(TPM_CC::HierarchyControl, &req)?; + Ok(()) + } + + /// This command allows setting of the authorization policy for the lockout (lockoutPolicy), + /// the platform hierarchy (platformPolicy), the storage hierarchy (ownerPolicy), and the + /// endorsement hierarchy (endorsementPolicy). On TPMs implementing Authenticated Countdown + /// Timers (ACT), this command may also be used to set the authorization policy for an ACT. + /// authHandle: TPM_RH_LOCKOUT, TPM_RH_ENDORSEMENT, TPM_RH_OWNER, TPMI_RH_ACT or TPM_RH_PLATFORM+{PP} + /// Auth Index: 1 + /// Auth Role: USER + /// authPolicy: An authorization policy digest; may be the Empty Buffer + /// If hashAlg is TPM_ALG_NULL, then this shall be an Empty Buffer. + /// hashAlg: The hash algorithm to use for the policy + /// If the authPolicy is an Empty Buffer, then this field shall be TPM_ALG_NULL. + pub fn SetPrimaryPolicy_async( + &mut self, + authHandle: &TPM_HANDLE, + authPolicy: &Vec, + hashAlg: TPM_ALG_ID, + ) -> Result<(), TpmError> { + let req = TPM2_SetPrimaryPolicy_REQUEST::new( + authHandle, + authPolicy, + hashAlg, + ); + + self.tpm.dispatch_command(TPM_CC::SetPrimaryPolicy, &req)?; + Ok(()) + } + + /// This replaces the current platform primary seed (PPS) with a value from the RNG and sets + /// platformPolicy to the default initialization value (the Empty Buffer). + /// authHandle: TPM_RH_PLATFORM+{PP} + /// Auth Index: 1 + /// Auth Role: USER + pub fn ChangePPS_async( + &mut self, + authHandle: &TPM_HANDLE, + ) -> Result<(), TpmError> { + let req = TPM2_ChangePPS_REQUEST::new( + authHandle, + ); + + self.tpm.dispatch_command(TPM_CC::ChangePPS, &req)?; + Ok(()) + } + + /// This replaces the current endorsement primary seed (EPS) with a value from the RNG and + /// sets the Endorsement hierarchy controls to their default initialization values: ehEnable + /// is SET, endorsementAuth and endorsementPolicy are both set to the Empty Buffer. It will + /// flush any resident objects (transient or persistent) in the Endorsement hierarchy and not + /// allow objects in the hierarchy associated with the previous EPS to be loaded. + /// authHandle: TPM_RH_PLATFORM+{PP} + /// Auth Handle: 1 + /// Auth Role: USER + pub fn ChangeEPS_async( + &mut self, + authHandle: &TPM_HANDLE, + ) -> Result<(), TpmError> { + let req = TPM2_ChangeEPS_REQUEST::new( + authHandle, + ); + + self.tpm.dispatch_command(TPM_CC::ChangeEPS, &req)?; + Ok(()) + } + + /// This command removes all TPM context associated with a specific Owner. + /// authHandle: TPM_RH_LOCKOUT or TPM_RH_PLATFORM+{PP} + /// Auth Handle: 1 + /// Auth Role: USER + pub fn Clear_async( + &mut self, + authHandle: &TPM_HANDLE, + ) -> Result<(), TpmError> { + let req = TPM2_Clear_REQUEST::new( + authHandle, + ); + + self.tpm.dispatch_command(TPM_CC::Clear, &req)?; + Ok(()) + } + + /// TPM2_ClearControl() disables and enables the execution of TPM2_Clear(). + /// auth: TPM_RH_LOCKOUT or TPM_RH_PLATFORM+{PP} + /// Auth Handle: 1 + /// Auth Role: USER + /// disable: YES if the disableOwnerClear flag is to be SET, NO if the flag is to be CLEAR. + pub fn ClearControl_async( + &mut self, + auth: &TPM_HANDLE, + disable: u8, + ) -> Result<(), TpmError> { + let req = TPM2_ClearControl_REQUEST::new( + auth, + disable, + ); + + self.tpm.dispatch_command(TPM_CC::ClearControl, &req)?; + Ok(()) + } + + /// This command allows the authorization secret for a hierarchy or lockout to be changed + /// using the current authorization value as the command authorization. + /// authHandle: TPM_RH_LOCKOUT, TPM_RH_ENDORSEMENT, TPM_RH_OWNER or TPM_RH_PLATFORM+{PP} + /// Auth Index: 1 + /// Auth Role: USER + /// newAuth: New authorization value + pub fn HierarchyChangeAuth_async( + &mut self, + authHandle: &TPM_HANDLE, + newAuth: &Vec, + ) -> Result<(), TpmError> { + let req = TPM2_HierarchyChangeAuth_REQUEST::new( + authHandle, + newAuth, + ); + + self.tpm.dispatch_command(TPM_CC::HierarchyChangeAuth, &req)?; + Ok(()) + } + + /// This command cancels the effect of a TPM lockout due to a number of successive + /// authorization failures. If this command is properly authorized, the lockout counter is set + /// to zero. + /// lockHandle: TPM_RH_LOCKOUT + /// Auth Index: 1 + /// Auth Role: USER + pub fn DictionaryAttackLockReset_async( + &mut self, + lockHandle: &TPM_HANDLE, + ) -> Result<(), TpmError> { + let req = TPM2_DictionaryAttackLockReset_REQUEST::new( + lockHandle, + ); + + self.tpm.dispatch_command(TPM_CC::DictionaryAttackLockReset, &req)?; + Ok(()) + } + + /// This command changes the lockout parameters. + /// lockHandle: TPM_RH_LOCKOUT + /// Auth Index: 1 + /// Auth Role: USER + /// newMaxTries: Count of authorization failures before the lockout is imposed + /// newRecoveryTime: Time in seconds before the authorization failure count is automatically decremented + /// A value of zero indicates that DA protection is disabled. + /// lockoutRecovery: Time in seconds after a lockoutAuth failure before use of lockoutAuth is allowed + /// A value of zero indicates that a reboot is required. + pub fn DictionaryAttackParameters_async( + &mut self, + lockHandle: &TPM_HANDLE, + newMaxTries: u32, + newRecoveryTime: u32, + lockoutRecovery: u32, + ) -> Result<(), TpmError> { + let req = TPM2_DictionaryAttackParameters_REQUEST::new( + lockHandle, + newMaxTries, + newRecoveryTime, + lockoutRecovery, + ); + + self.tpm.dispatch_command(TPM_CC::DictionaryAttackParameters, &req)?; + Ok(()) + } + + /// This command is used to determine which commands require assertion of Physical Presence + /// (PP) in addition to platformAuth/platformPolicy. + /// auth: TPM_RH_PLATFORM+PP + /// Auth Index: 1 + /// Auth Role: USER + Physical Presence + /// setList: List of commands to be added to those that will require that Physical Presence be + /// asserted + /// clearList: List of commands that will no longer require that Physical Presence be asserted + pub fn PP_Commands_async( + &mut self, + auth: &TPM_HANDLE, + setList: &Vec, + clearList: &Vec, + ) -> Result<(), TpmError> { + let req = TPM2_PP_Commands_REQUEST::new( + auth, + setList, + clearList, + ); + + self.tpm.dispatch_command(TPM_CC::PP_Commands, &req)?; + Ok(()) + } + + /// This command allows the platform to change the set of algorithms that are used by the TPM. + /// The algorithmSet setting is a vendor-dependent value. + /// authHandle: TPM_RH_PLATFORM + /// Auth Index: 1 + /// Auth Role: USER + /// algorithmSet: A TPM vendor-dependent value indicating the algorithm set selection + pub fn SetAlgorithmSet_async( + &mut self, + authHandle: &TPM_HANDLE, + algorithmSet: u32, + ) -> Result<(), TpmError> { + let req = TPM2_SetAlgorithmSet_REQUEST::new( + authHandle, + algorithmSet, + ); + + self.tpm.dispatch_command(TPM_CC::SetAlgorithmSet, &req)?; + Ok(()) + } + + /// This command uses platformPolicy and a TPM Vendor Authorization Key to authorize a Field + /// Upgrade Manifest. + /// authorization: TPM_RH_PLATFORM+{PP} + /// Auth Index:1 + /// Auth Role: ADMIN + /// keyHandle: Handle of a public area that contains the TPM Vendor Authorization Key that + /// will be used to validate manifestSignature + /// Auth Index: None + /// fuDigest: Digest of the first block in the field upgrade sequence + /// manifestSignature: Signature over fuDigest using the key associated with keyHandle (not optional) + /// One of: TPMS_SIGNATURE_RSASSA, TPMS_SIGNATURE_RSAPSS, TPMS_SIGNATURE_ECDSA, + /// TPMS_SIGNATURE_ECDAA, TPMS_SIGNATURE_SM2, TPMS_SIGNATURE_ECSCHNORR, TPMT_HA, + /// TPMS_SCHEME_HASH, TPMS_NULL_SIGNATURE. + pub fn FieldUpgradeStart_async( + &mut self, + authorization: &TPM_HANDLE, + keyHandle: &TPM_HANDLE, + fuDigest: &Vec, + manifestSignature: &Option, + ) -> Result<(), TpmError> { + let req = TPM2_FieldUpgradeStart_REQUEST::new( + authorization, + keyHandle, + fuDigest, + manifestSignature, + ); + + self.tpm.dispatch_command(TPM_CC::FieldUpgradeStart, &req)?; + Ok(()) + } + + /// This command will take the actual field upgrade image to be installed on the TPM. The + /// exact format of fuData is vendor-specific. This command is only possible following a + /// successful TPM2_FieldUpgradeStart(). If the TPM has not received a properly authorized + /// TPM2_FieldUpgradeStart(), then the TPM shall return TPM_RC_FIELDUPGRADE. + /// fuData: Field upgrade image data + /// nextDigest - Tagged digest of the next block + /// TPM_ALG_NULL if field update is complete + /// firstDigest - Tagged digest of the first block of the sequence + pub fn FieldUpgradeData_async( + &mut self, + fuData: &Vec, + ) -> Result<(), TpmError> { + let req = TPM2_FieldUpgradeData_REQUEST::new( + fuData, + ); + + self.tpm.dispatch_command(TPM_CC::FieldUpgradeData, &req)?; + Ok(()) + } + + /// This command is used to read a copy of the current firmware installed in the TPM. + /// sequenceNumber: The number of previous calls to this command in this sequence + /// set to 0 on the first call + /// fuData - Field upgrade image data + pub fn FirmwareRead_async( + &mut self, + sequenceNumber: u32, + ) -> Result<(), TpmError> { + let req = TPM2_FirmwareRead_REQUEST::new( + sequenceNumber, + ); + + self.tpm.dispatch_command(TPM_CC::FirmwareRead, &req)?; + Ok(()) + } + + /// This command saves a session context, object context, or sequence object context outside + /// the TPM. + /// saveHandle: Handle of the resource to save + /// Auth Index: None + /// context - This structure is used in TPM2_ContextLoad() and TPM2_ContextSave(). If the + /// values of the TPMS_CONTEXT structure in TPM2_ContextLoad() are not the same + /// as the values when the context was saved (TPM2_ContextSave()), then the TPM + /// shall not load the context. + pub fn ContextSave_async( + &mut self, + saveHandle: &TPM_HANDLE, + ) -> Result<(), TpmError> { + let req = TPM2_ContextSave_REQUEST::new( + saveHandle, + ); + + self.tpm.dispatch_command(TPM_CC::ContextSave, &req)?; + Ok(()) + } + + /// This command is used to reload a context that has been saved by TPM2_ContextSave(). + /// context: The context blob + /// handle - The handle assigned to the resource after it has been successfully loaded + pub fn ContextLoad_async( + &mut self, + context: &TPMS_CONTEXT, + ) -> Result<(), TpmError> { + let req = TPM2_ContextLoad_REQUEST::new( + context, + ); + + self.tpm.dispatch_command(TPM_CC::ContextLoad, &req)?; + Ok(()) + } + + /// This command causes all context associated with a loaded object, sequence object, or + /// session to be removed from TPM memory. + /// flushHandle: The handle of the item to flush + /// NOTE This is a use of a handle as a parameter. + pub fn FlushContext_async( + &mut self, + flushHandle: &TPM_HANDLE, + ) -> Result<(), TpmError> { + let req = TPM2_FlushContext_REQUEST::new( + flushHandle, + ); + + self.tpm.dispatch_command(TPM_CC::FlushContext, &req)?; + Ok(()) + } + + /// This command allows certain Transient Objects to be made persistent or a persistent object + /// to be evicted. + /// auth: TPM_RH_OWNER or TPM_RH_PLATFORM+{PP} + /// Auth Handle: 1 + /// Auth Role: USER + /// objectHandle: The handle of a loaded object + /// Auth Index: None + /// persistentHandle: If objectHandle is a transient object handle, then this is the + /// persistent handle for the object + /// if objectHandle is a persistent object handle, then it shall be the same value as + /// persistentHandle + pub fn EvictControl_async( + &mut self, + auth: &TPM_HANDLE, + objectHandle: &TPM_HANDLE, + persistentHandle: &TPM_HANDLE, + ) -> Result<(), TpmError> { + let req = TPM2_EvictControl_REQUEST::new( + auth, + objectHandle, + persistentHandle, + ); + + self.tpm.dispatch_command(TPM_CC::EvictControl, &req)?; + Ok(()) + } + + /// This command reads the current TPMS_TIME_INFO structure that contains the current setting + /// of Time, Clock, resetCount, and restartCount. + /// currentTime - This structure is used in, e.g., the TPM2_GetTime() attestation and + /// TPM2_ReadClock(). + pub fn ReadClock_async( + &mut self, + ) -> Result<(), TpmError> { + let req = TPM2_ReadClock_REQUEST::default(); + + self.tpm.dispatch_command(TPM_CC::ReadClock, &req)?; + Ok(()) + } + + /// This command is used to advance the value of the TPMs Clock. The command will fail if + /// newTime is less than the current value of Clock or if the new time is greater than + /// FFFF00000000000016. If both of these checks succeed, Clock is set to newTime. If either of + /// these checks fails, the TPM shall return TPM_RC_VALUE and make no change to Clock. + /// auth: TPM_RH_OWNER or TPM_RH_PLATFORM+{PP} + /// Auth Handle: 1 + /// Auth Role: USER + /// newTime: New Clock setting in milliseconds + pub fn ClockSet_async( + &mut self, + auth: &TPM_HANDLE, + newTime: u64, + ) -> Result<(), TpmError> { + let req = TPM2_ClockSet_REQUEST::new( + auth, + newTime, + ); + + self.tpm.dispatch_command(TPM_CC::ClockSet, &req)?; + Ok(()) + } + + /// This command adjusts the rate of advance of Clock and Time to provide a better + /// approximation to real time. + /// auth: TPM_RH_OWNER or TPM_RH_PLATFORM+{PP} + /// Auth Handle: 1 + /// Auth Role: USER + /// rateAdjust: Adjustment to current Clock update rate + pub fn ClockRateAdjust_async( + &mut self, + auth: &TPM_HANDLE, + rateAdjust: TPM_CLOCK_ADJUST, + ) -> Result<(), TpmError> { + let req = TPM2_ClockRateAdjust_REQUEST::new( + auth, + rateAdjust, + ); + + self.tpm.dispatch_command(TPM_CC::ClockRateAdjust, &req)?; + Ok(()) + } + + /// This command returns various information regarding the TPM and its current state. + /// capability: Group selection; determines the format of the response + /// property: Further definition of information + /// propertyCount: Number of properties of the indicated type to return + /// moreData - Flag to indicate if there are more values of this type + /// capabilityData - The capability data + pub fn GetCapability_async( + &mut self, + capability: TPM_CAP, + property: u32, + propertyCount: u32, + ) -> Result<(), TpmError> { + let req = TPM2_GetCapability_REQUEST::new( + capability, + property, + propertyCount, + ); + + self.tpm.dispatch_command(TPM_CC::GetCapability, &req)?; + Ok(()) + } + + /// This command is used to check to see if specific combinations of algorithm parameters are supported. + /// parameters: Algorithm parameters to be validated + /// One of: TPMS_KEYEDHASH_PARMS, TPMS_SYMCIPHER_PARMS, TPMS_RSA_PARMS, TPMS_ECC_PARMS, + /// TPMS_ASYM_PARMS. + pub fn TestParms_async( + &mut self, + parameters: &Option, + ) -> Result<(), TpmError> { + let req = TPM2_TestParms_REQUEST::new( + parameters, + ); + + self.tpm.dispatch_command(TPM_CC::TestParms, &req)?; + Ok(()) + } + + /// This command defines the attributes of an NV Index and causes the TPM to reserve space to + /// hold the data associated with the NV Index. If a definition already exists at the NV + /// Index, the TPM will return TPM_RC_NV_DEFINED. + /// authHandle: TPM_RH_OWNER or TPM_RH_PLATFORM+{PP} + /// Auth Index: 1 + /// Auth Role: USER + /// auth: The authorization value + /// publicInfo: The public parameters of the NV area + pub fn NV_DefineSpace_async( + &mut self, + authHandle: &TPM_HANDLE, + auth: &Vec, + publicInfo: &TPMS_NV_PUBLIC, + ) -> Result<(), TpmError> { + let req = TPM2_NV_DefineSpace_REQUEST::new( + authHandle, + auth, + publicInfo, + ); + + self.tpm.dispatch_command(TPM_CC::NV_DefineSpace, &req)?; + Ok(()) + } + + /// This command removes an Index from the TPM. + /// authHandle: TPM_RH_OWNER or TPM_RH_PLATFORM+{PP} + /// Auth Index: 1 + /// Auth Role: USER + /// nvIndex: The NV Index to remove from NV space + /// Auth Index: None + pub fn NV_UndefineSpace_async( + &mut self, + authHandle: &TPM_HANDLE, + nvIndex: &TPM_HANDLE, + ) -> Result<(), TpmError> { + let req = TPM2_NV_UndefineSpace_REQUEST::new( + authHandle, + nvIndex, + ); + + self.tpm.dispatch_command(TPM_CC::NV_UndefineSpace, &req)?; + Ok(()) + } + + /// This command allows removal of a platform-created NV Index that has TPMA_NV_POLICY_DELETE SET. + /// nvIndex: Index to be deleted + /// Auth Index: 1 + /// Auth Role: ADMIN + /// platform: TPM_RH_PLATFORM + {PP} + /// Auth Index: 2 + /// Auth Role: USER + pub fn NV_UndefineSpaceSpecial_async( + &mut self, + nvIndex: &TPM_HANDLE, + platform: &TPM_HANDLE, + ) -> Result<(), TpmError> { + let req = TPM2_NV_UndefineSpaceSpecial_REQUEST::new( + nvIndex, + platform, + ); + + self.tpm.dispatch_command(TPM_CC::NV_UndefineSpaceSpecial, &req)?; + Ok(()) + } + + /// This command is used to read the public area and Name of an NV Index. The public area of + /// an Index is not privacy-sensitive and no authorization is required to read this data. + /// nvIndex: The NV Index + /// Auth Index: None + /// nvPublic - The public area of the NV Index + /// nvName - The Name of the nvIndex + pub fn NV_ReadPublic_async( + &mut self, + nvIndex: &TPM_HANDLE, + ) -> Result<(), TpmError> { + let req = TPM2_NV_ReadPublic_REQUEST::new( + nvIndex, + ); + + self.tpm.dispatch_command(TPM_CC::NV_ReadPublic, &req)?; + Ok(()) + } + + /// This command writes a value to an area in NV memory that was previously defined by + /// TPM2_NV_DefineSpace(). + /// authHandle: Handle indicating the source of the authorization value + /// Auth Index: 1 + /// Auth Role: USER + /// nvIndex: The NV Index of the area to write + /// Auth Index: None + /// data: The data to write + /// offset: The octet offset into the NV Area + pub fn NV_Write_async( + &mut self, + authHandle: &TPM_HANDLE, + nvIndex: &TPM_HANDLE, + data: &Vec, + offset: u16, + ) -> Result<(), TpmError> { + let req = TPM2_NV_Write_REQUEST::new( + authHandle, + nvIndex, + data, + offset, + ); + + self.tpm.dispatch_command(TPM_CC::NV_Write, &req)?; + Ok(()) + } + + /// This command is used to increment the value in an NV Index that has the TPM_NT_COUNTER + /// attribute. The data value of the NV Index is incremented by one. + /// authHandle: Handle indicating the source of the authorization value + /// Auth Index: 1 + /// Auth Role: USER + /// nvIndex: The NV Index to increment + /// Auth Index: None + pub fn NV_Increment_async( + &mut self, + authHandle: &TPM_HANDLE, + nvIndex: &TPM_HANDLE, + ) -> Result<(), TpmError> { + let req = TPM2_NV_Increment_REQUEST::new( + authHandle, + nvIndex, + ); + + self.tpm.dispatch_command(TPM_CC::NV_Increment, &req)?; + Ok(()) + } + + /// This command extends a value to an area in NV memory that was previously defined by + /// TPM2_NV_DefineSpace. + /// authHandle: Handle indicating the source of the authorization value + /// Auth Index: 1 + /// Auth Role: USER + /// nvIndex: The NV Index to extend + /// Auth Index: None + /// data: The data to extend + pub fn NV_Extend_async( + &mut self, + authHandle: &TPM_HANDLE, + nvIndex: &TPM_HANDLE, + data: &Vec, + ) -> Result<(), TpmError> { + let req = TPM2_NV_Extend_REQUEST::new( + authHandle, + nvIndex, + data, + ); + + self.tpm.dispatch_command(TPM_CC::NV_Extend, &req)?; + Ok(()) + } + + /// This command is used to SET bits in an NV Index that was created as a bit field. Any + /// number of bits from 0 to 64 may be SET. The contents of bits are ORed with the current + /// contents of the NV Index. + /// authHandle: Handle indicating the source of the authorization value + /// Auth Index: 1 + /// Auth Role: USER + /// nvIndex: NV Index of the area in which the bit is to be set + /// Auth Index: None + /// bits: The data to OR with the current contents + pub fn NV_SetBits_async( + &mut self, + authHandle: &TPM_HANDLE, + nvIndex: &TPM_HANDLE, + bits: u64, + ) -> Result<(), TpmError> { + let req = TPM2_NV_SetBits_REQUEST::new( + authHandle, + nvIndex, + bits, + ); + + self.tpm.dispatch_command(TPM_CC::NV_SetBits, &req)?; + Ok(()) + } + + /// If the TPMA_NV_WRITEDEFINE or TPMA_NV_WRITE_STCLEAR attributes of an NV location are SET, + /// then this command may be used to inhibit further writes of the NV Index. + /// authHandle: Handle indicating the source of the authorization value + /// Auth Index: 1 + /// Auth Role: USER + /// nvIndex: The NV Index of the area to lock + /// Auth Index: None + pub fn NV_WriteLock_async( + &mut self, + authHandle: &TPM_HANDLE, + nvIndex: &TPM_HANDLE, + ) -> Result<(), TpmError> { + let req = TPM2_NV_WriteLock_REQUEST::new( + authHandle, + nvIndex, + ); + + self.tpm.dispatch_command(TPM_CC::NV_WriteLock, &req)?; + Ok(()) + } + + /// The command will SET TPMA_NV_WRITELOCKED for all indexes that have their + /// TPMA_NV_GLOBALLOCK attribute SET. + /// authHandle: TPM_RH_OWNER or TPM_RH_PLATFORM+{PP} + /// Auth Index: 1 + /// Auth Role: USER + pub fn NV_GlobalWriteLock_async( + &mut self, + authHandle: &TPM_HANDLE, + ) -> Result<(), TpmError> { + let req = TPM2_NV_GlobalWriteLock_REQUEST::new( + authHandle, + ); + + self.tpm.dispatch_command(TPM_CC::NV_GlobalWriteLock, &req)?; + Ok(()) + } + + /// This command reads a value from an area in NV memory previously defined by TPM2_NV_DefineSpace(). + /// authHandle: The handle indicating the source of the authorization value + /// Auth Index: 1 + /// Auth Role: USER + /// nvIndex: The NV Index to be read + /// Auth Index: None + /// size: Number of octets to read + /// offset: Octet offset into the NV area + /// This value shall be less than or equal to the size of the nvIndex data. + /// data - The data read + pub fn NV_Read_async( + &mut self, + authHandle: &TPM_HANDLE, + nvIndex: &TPM_HANDLE, + size: u16, + offset: u16, + ) -> Result<(), TpmError> { + let req = TPM2_NV_Read_REQUEST::new( + authHandle, + nvIndex, + size, + offset, + ); + + self.tpm.dispatch_command(TPM_CC::NV_Read, &req)?; + Ok(()) + } + + /// If TPMA_NV_READ_STCLEAR is SET in an Index, then this command may be used to prevent + /// further reads of the NV Index until the next TPM2_Startup (TPM_SU_CLEAR). + /// authHandle: The handle indicating the source of the authorization value + /// Auth Index: 1 + /// Auth Role: USER + /// nvIndex: The NV Index to be locked + /// Auth Index: None + pub fn NV_ReadLock_async( + &mut self, + authHandle: &TPM_HANDLE, + nvIndex: &TPM_HANDLE, + ) -> Result<(), TpmError> { + let req = TPM2_NV_ReadLock_REQUEST::new( + authHandle, + nvIndex, + ); + + self.tpm.dispatch_command(TPM_CC::NV_ReadLock, &req)?; + Ok(()) + } + + /// This command allows the authorization secret for an NV Index to be changed. + /// nvIndex: Handle of the entity + /// Auth Index: 1 + /// Auth Role: ADMIN + /// newAuth: New authorization value + pub fn NV_ChangeAuth_async( + &mut self, + nvIndex: &TPM_HANDLE, + newAuth: &Vec, + ) -> Result<(), TpmError> { + let req = TPM2_NV_ChangeAuth_REQUEST::new( + nvIndex, + newAuth, + ); + + self.tpm.dispatch_command(TPM_CC::NV_ChangeAuth, &req)?; + Ok(()) + } + + /// The purpose of this command is to certify the contents of an NV Index or portion of an NV Index. + /// signHandle: Handle of the key used to sign the attestation structure + /// Auth Index: 1 + /// Auth Role: USER + /// authHandle: Handle indicating the source of the authorization value for the NV Index + /// Auth Index: 2 + /// Auth Role: USER + /// nvIndex: Index for the area to be certified + /// Auth Index: None + /// qualifyingData: User-provided qualifying data + /// inScheme: Signing scheme to use if the scheme for signHandle is TPM_ALG_NULL + /// One of: TPMS_SIG_SCHEME_RSASSA, TPMS_SIG_SCHEME_RSAPSS, TPMS_SIG_SCHEME_ECDSA, + /// TPMS_SIG_SCHEME_ECDAA, TPMS_SIG_SCHEME_SM2, TPMS_SIG_SCHEME_ECSCHNORR, + /// TPMS_SCHEME_HMAC, TPMS_SCHEME_HASH, TPMS_NULL_SIG_SCHEME. + /// size: Number of octets to certify + /// offset: Octet offset into the NV area + /// This value shall be less than or equal to the size of the nvIndex data. + /// certifyInfo - The structure that was signed + /// signature - The asymmetric signature over certifyInfo using the key referenced by signHandle + pub fn NV_Certify_async( + &mut self, + signHandle: &TPM_HANDLE, + authHandle: &TPM_HANDLE, + nvIndex: &TPM_HANDLE, + qualifyingData: &Vec, + inScheme: &Option, + size: u16, + offset: u16, + ) -> Result<(), TpmError> { + let req = TPM2_NV_Certify_REQUEST::new( + signHandle, + authHandle, + nvIndex, + qualifyingData, + inScheme, + size, + offset, + ); + + self.tpm.dispatch_command(TPM_CC::NV_Certify, &req)?; + Ok(()) + } + + /// The purpose of this command is to obtain information about an Attached Component + /// referenced by an AC handle. + /// ac: Handle indicating the Attached Component + /// Auth Index: None + /// capability: Starting info type + /// count: Maximum number of values to return + /// moreData - Flag to indicate whether there are more values + /// capabilitiesData - List of capabilities + pub fn AC_GetCapability_async( + &mut self, + ac: &TPM_HANDLE, + capability: TPM_AT, + count: u32, + ) -> Result<(), TpmError> { + let req = TPM2_AC_GetCapability_REQUEST::new( + ac, + capability, + count, + ); + + self.tpm.dispatch_command(TPM_CC::AC_GetCapability, &req)?; + Ok(()) + } + + /// The purpose of this command is to send (copy) a loaded object from the TPM to an Attached Component. + /// sendObject: Handle of the object being sent to ac + /// Auth Index: 1 + /// Auth Role: DUP + /// authHandle: The handle indicating the source of the authorization value + /// Auth Index: 2 + /// Auth Role: USER + /// ac: Handle indicating the Attached Component to which the object will be sent + /// Auth Index: None + /// acDataIn: Optional non sensitive information related to the object + /// acDataOut - May include AC specific data or information about an error. + pub fn AC_Send_async( + &mut self, + sendObject: &TPM_HANDLE, + authHandle: &TPM_HANDLE, + ac: &TPM_HANDLE, + acDataIn: &Vec, + ) -> Result<(), TpmError> { + let req = TPM2_AC_Send_REQUEST::new( + sendObject, + authHandle, + ac, + acDataIn, + ); + + self.tpm.dispatch_command(TPM_CC::AC_Send, &req)?; + Ok(()) + } + + /// This command allows qualification of the sending (copying) of an Object to an Attached + /// Component (AC). Qualification includes selection of the receiving AC and the method of + /// authentication for the AC, and, in certain circumstances, the Object to be sent may be specified. + /// policySession: Handle for the policy session being extended + /// Auth Index: None + /// objectName: The Name of the Object to be sent + /// authHandleName: The Name associated with authHandle used in the TPM2_AC_Send() command + /// acName: The Name of the Attached Component to which the Object will be sent + /// includeObject: If SET, objectName will be included in the value in policySessionpolicyDigest + pub fn Policy_AC_SendSelect_async( + &mut self, + policySession: &TPM_HANDLE, + objectName: &Vec, + authHandleName: &Vec, + acName: &Vec, + includeObject: u8, + ) -> Result<(), TpmError> { + let req = TPM2_Policy_AC_SendSelect_REQUEST::new( + policySession, + objectName, + authHandleName, + acName, + includeObject, + ); + + self.tpm.dispatch_command(TPM_CC::Policy_AC_SendSelect, &req)?; + Ok(()) + } + + /// This command is used to set the time remaining before an Authenticated Countdown Timer + /// (ACT) expires. + /// actHandle: Handle of the selected ACT + /// Auth Index: 1 + /// Auth Role: USER + /// startTimeout: The start timeout value for the ACT in seconds + pub fn ACT_SetTimeout_async( + &mut self, + actHandle: &TPM_HANDLE, + startTimeout: u32, + ) -> Result<(), TpmError> { + let req = TPM2_ACT_SetTimeout_REQUEST::new( + actHandle, + startTimeout, + ); + + self.tpm.dispatch_command(TPM_CC::ACT_SetTimeout, &req)?; + Ok(()) + } + + /// This is a placeholder to allow testing of the dispatch code. + /// inputData: Dummy data + /// outputData - Dummy data + pub fn Vendor_TCG_Test_async( + &mut self, + inputData: &Vec, + ) -> Result<(), TpmError> { + let req = TPM2_Vendor_TCG_Test_REQUEST::new( + inputData, + ); + + self.tpm.dispatch_command(TPM_CC::Vendor_TCG_Test, &req)?; + Ok(()) + } + + /// TPM2_Startup() is always preceded by _TPM_Init, which is the physical indication that TPM + /// initialization is necessary because of a system-wide reset. TPM2_Startup() is only valid + /// after _TPM_Init. Additional TPM2_Startup() commands are not allowed after it has completed + /// successfully. If a TPM requires TPM2_Startup() and another command is received, or if the + /// TPM receives TPM2_Startup() when it is not required, the TPM shall return TPM_RC_INITIALIZE. + pub fn Startup_complete( + &mut self, + ) -> Result<(), TpmError> { + let mut resp = EmptyTpmResponse::default(); + self.tpm.process_response(TPM_CC::Startup, &mut resp)?; + Ok(()) + } + + /// This command is used to prepare the TPM for a power cycle. The shutdownType parameter + /// indicates how the subsequent TPM2_Startup() will be processed. + pub fn Shutdown_complete( + &mut self, + ) -> Result<(), TpmError> { + let mut resp = EmptyTpmResponse::default(); + self.tpm.process_response(TPM_CC::Shutdown, &mut resp)?; + Ok(()) + } + + /// This command causes the TPM to perform a test of its capabilities. If the fullTest is YES, + /// the TPM will test all functions. If fullTest = NO, the TPM will only test those functions + /// that have not previously been tested. + pub fn SelfTest_complete( + &mut self, + ) -> Result<(), TpmError> { + let mut resp = EmptyTpmResponse::default(); + self.tpm.process_response(TPM_CC::SelfTest, &mut resp)?; + Ok(()) + } + + /// This command causes the TPM to perform a test of the selected algorithms. + /// toDoList - List of algorithms that need testing + pub fn IncrementalSelfTest_complete( + &mut self, + ) -> Result, TpmError> { + let mut resp = IncrementalSelfTestResponse::default(); + self.tpm.process_response(TPM_CC::IncrementalSelfTest, &mut resp)?; + Ok(resp.toDoList) + } + + /// This command returns manufacturer-specific information regarding the results of a + /// self-test and an indication of the test status. + /// outData - Test result data + /// contains manufacturer-specific information + /// testResult - TBD + pub fn GetTestResult_complete( + &mut self, + ) -> Result { + let mut resp = GetTestResultResponse::default(); + self.tpm.process_response(TPM_CC::GetTestResult, &mut resp)?; + Ok(resp) + } + + /// This command is used to start an authorization session using alternative methods of + /// establishing the session key (sessionKey). The session key is then used to derive values + /// used for authorization and for encrypting parameters. + /// handle - Handle for the newly created session + /// nonceTPM - The initial nonce from the TPM, used in the computation of the sessionKey + pub fn StartAuthSession_complete( + &mut self, + ) -> Result { + let mut resp = StartAuthSessionResponse::default(); + self.tpm.process_response(TPM_CC::StartAuthSession, &mut resp)?; + Ok(resp) + } + + /// This command allows a policy authorization session to be returned to its initial state. + /// This command is used after the TPM returns TPM_RC_PCR_CHANGED. That response code + /// indicates that a policy will fail because the PCR have changed after TPM2_PolicyPCR() was + /// executed. Restarting the session allows the authorizations to be replayed because the + /// session restarts with the same nonceTPM. If the PCR are valid for the policy, the policy + /// may then succeed. + pub fn PolicyRestart_complete( + &mut self, + ) -> Result<(), TpmError> { + let mut resp = EmptyTpmResponse::default(); + self.tpm.process_response(TPM_CC::PolicyRestart, &mut resp)?; + Ok(()) + } + + /// This command is used to create an object that can be loaded into a TPM using TPM2_Load(). + /// If the command completes successfully, the TPM will create the new object and return the + /// objects creation data (creationData), its public area (outPublic), and its encrypted + /// sensitive area (outPrivate). Preservation of the returned data is the responsibility of + /// the caller. The object will need to be loaded (TPM2_Load()) before it may be used. The + /// only difference between the inPublic TPMT_PUBLIC template and the outPublic TPMT_PUBLIC + /// object is in the unique field. + /// outPrivate - The private portion of the object + /// outPublic - The public portion of the created object + /// creationData - Contains a TPMS_CREATION_DATA + /// creationHash - Digest of creationData using nameAlg of outPublic + /// creationTicket - Ticket used by TPM2_CertifyCreation() to validate that the creation + /// data was produced by the TPM + pub fn Create_complete( + &mut self, + ) -> Result { + let mut resp = CreateResponse::default(); + self.tpm.process_response(TPM_CC::Create, &mut resp)?; + Ok(resp) + } + + /// This command is used to load objects into the TPM. This command is used when both a + /// TPM2B_PUBLIC and TPM2B_PRIVATE are to be loaded. If only a TPM2B_PUBLIC is to be loaded, + /// the TPM2_LoadExternal command is used. + /// handle - Handle of type TPM_HT_TRANSIENT for the loaded object + /// name - Name of the loaded object + pub fn Load_complete( + &mut self, + ) -> Result { + let mut resp = LoadResponse::default(); + self.tpm.process_response(TPM_CC::Load, &mut resp)?; + Ok(resp) + } + + /// This command is used to load an object that is not a Protected Object into the TPM. The + /// command allows loading of a public area or both a public and sensitive area. + /// handle - Handle of type TPM_HT_TRANSIENT for the loaded object + /// name - Name of the loaded object + pub fn LoadExternal_complete( + &mut self, + ) -> Result { + let mut resp = LoadExternalResponse::default(); + self.tpm.process_response(TPM_CC::LoadExternal, &mut resp)?; + Ok(resp) + } + + /// This command allows access to the public area of a loaded object. + /// outPublic - Structure containing the public area of an object + /// name - Name of the object + /// qualifiedName - The Qualified Name of the object + pub fn ReadPublic_complete( + &mut self, + ) -> Result { + let mut resp = ReadPublicResponse::default(); + self.tpm.process_response(TPM_CC::ReadPublic, &mut resp)?; + Ok(resp) + } + + /// This command enables the association of a credential with an object in a way that ensures + /// that the TPM has validated the parameters of the credentialed object. + /// certInfo - The decrypted certificate information + /// the data should be no larger than the size of the digest of the nameAlg + /// associated with keyHandle + pub fn ActivateCredential_complete( + &mut self, + ) -> Result, TpmError> { + let mut resp = ActivateCredentialResponse::default(); + self.tpm.process_response(TPM_CC::ActivateCredential, &mut resp)?; + Ok(resp.certInfo) + } + + /// This command allows the TPM to perform the actions required of a Certificate Authority + /// (CA) in creating a TPM2B_ID_OBJECT containing an activation credential. + /// credentialBlob - The credential + /// secret - Handle algorithm-dependent data that wraps the key that encrypts credentialBlob + pub fn MakeCredential_complete( + &mut self, + ) -> Result { + let mut resp = MakeCredentialResponse::default(); + self.tpm.process_response(TPM_CC::MakeCredential, &mut resp)?; + Ok(resp) + } + + /// This command returns the data in a loaded Sealed Data Object. + /// outData - Unsealed data + /// Size of outData is limited to be no more than 128 octets. + pub fn Unseal_complete( + &mut self, + ) -> Result, TpmError> { + let mut resp = UnsealResponse::default(); + self.tpm.process_response(TPM_CC::Unseal, &mut resp)?; + Ok(resp.outData) + } + + /// This command is used to change the authorization secret for a TPM-resident object. + /// outPrivate - Private area containing the new authorization value + pub fn ObjectChangeAuth_complete( + &mut self, + ) -> Result { + let mut resp = ObjectChangeAuthResponse::default(); + self.tpm.process_response(TPM_CC::ObjectChangeAuth, &mut resp)?; + Ok(resp.outPrivate) + } + + /// This command creates an object and loads it in the TPM. This command allows creation of + /// any type of object (Primary, Ordinary, or Derived) depending on the type of parentHandle. + /// If parentHandle references a Primary Seed, then a Primary Object is created; if + /// parentHandle references a Storage Parent, then an Ordinary Object is created; and if + /// parentHandle references a Derivation Parent, then a Derived Object is generated. + /// handle - Handle of type TPM_HT_TRANSIENT for created object + /// outPrivate - The sensitive area of the object (optional) + /// outPublic - The public portion of the created object + /// name - The name of the created object + pub fn CreateLoaded_complete( + &mut self, + ) -> Result { + let mut resp = CreateLoadedResponse::default(); + self.tpm.process_response(TPM_CC::CreateLoaded, &mut resp)?; + Ok(resp) + } + + /// This command duplicates a loaded object so that it may be used in a different hierarchy. + /// The new parent key for the duplicate may be on the same or different TPM or TPM_RH_NULL. + /// Only the public area of newParentHandle is required to be loaded. + /// encryptionKeyOut - If the caller provided an encryption key or if symmetricAlg was + /// TPM_ALG_NULL, then this will be the Empty Buffer; otherwise, it + /// shall contain the TPM-generated, symmetric encryption key for the + /// inner wrapper. + /// duplicate - Private area that may be encrypted by encryptionKeyIn; and may be doubly encrypted + /// outSymSeed - Seed protected by the asymmetric algorithms of new parent (NP) + pub fn Duplicate_complete( + &mut self, + ) -> Result { + let mut resp = DuplicateResponse::default(); + self.tpm.process_response(TPM_CC::Duplicate, &mut resp)?; + Ok(resp) + } + + /// This command allows the TPM to serve in the role as a Duplication Authority. If proper + /// authorization for use of the oldParent is provided, then an HMAC key and a symmetric key + /// are recovered from inSymSeed and used to integrity check and decrypt inDuplicate. A new + /// protection seed value is generated according to the methods appropriate for newParent and + /// the blob is re-encrypted and a new integrity value is computed. The re-encrypted blob is + /// returned in outDuplicate and the symmetric key returned in outSymKey. + /// outDuplicate - An object encrypted using symmetric key derived from outSymSeed + /// outSymSeed - Seed for a symmetric key protected by newParent asymmetric key + pub fn Rewrap_complete( + &mut self, + ) -> Result { + let mut resp = RewrapResponse::default(); + self.tpm.process_response(TPM_CC::Rewrap, &mut resp)?; + Ok(resp) + } + + /// This command allows an object to be encrypted using the symmetric encryption values of a + /// Storage Key. After encryption, the object may be loaded and used in the new hierarchy. The + /// imported object (duplicate) may be singly encrypted, multiply encrypted, or unencrypted. + /// outPrivate - The sensitive area encrypted with the symmetric key of parentHandle + pub fn Import_complete( + &mut self, + ) -> Result { + let mut resp = ImportResponse::default(); + self.tpm.process_response(TPM_CC::Import, &mut resp)?; + Ok(resp.outPrivate) + } + + /// This command performs RSA encryption using the indicated padding scheme according to IETF + /// RFC 8017. If the scheme of keyHandle is TPM_ALG_NULL, then the caller may use inScheme to + /// specify the padding scheme. If scheme of keyHandle is not TPM_ALG_NULL, then inScheme + /// shall either be TPM_ALG_NULL or be the same as scheme (TPM_RC_SCHEME). + /// outData - Encrypted output + pub fn RSA_Encrypt_complete( + &mut self, + ) -> Result, TpmError> { + let mut resp = RSA_EncryptResponse::default(); + self.tpm.process_response(TPM_CC::RSA_Encrypt, &mut resp)?; + Ok(resp.outData) + } + + /// This command performs RSA decryption using the indicated padding scheme according to IETF + /// RFC 8017 ((PKCS#1). + /// message - Decrypted output + pub fn RSA_Decrypt_complete( + &mut self, + ) -> Result, TpmError> { + let mut resp = RSA_DecryptResponse::default(); + self.tpm.process_response(TPM_CC::RSA_Decrypt, &mut resp)?; + Ok(resp.message) + } + + /// This command uses the TPM to generate an ephemeral key pair (de, Qe where Qe [de]G). It + /// uses the private ephemeral key and a loaded public key (QS) to compute the shared secret + /// value (P [hde]QS). + /// zPoint - Results of P h[de]Qs + /// pubPoint - Generated ephemeral public point (Qe) + pub fn ECDH_KeyGen_complete( + &mut self, + ) -> Result { + let mut resp = ECDH_KeyGenResponse::default(); + self.tpm.process_response(TPM_CC::ECDH_KeyGen, &mut resp)?; + Ok(resp) + } + + /// This command uses the TPM to recover the Z value from a public point (QB) and a private + /// key (ds). It will perform the multiplication of the provided inPoint (QB) with the private + /// key (ds) and return the coordinates of the resultant point (Z = (xZ , yZ) [hds]QB; where h + /// is the cofactor of the curve). + /// outPoint - X and Y coordinates of the product of the multiplication Z = (xZ , yZ) [hdS]QB + pub fn ECDH_ZGen_complete( + &mut self, + ) -> Result { + let mut resp = ECDH_ZGenResponse::default(); + self.tpm.process_response(TPM_CC::ECDH_ZGen, &mut resp)?; + Ok(resp.outPoint) + } + + /// This command returns the parameters of an ECC curve identified by its TCG-assigned curveID. + /// parameters - ECC parameters for the selected curve + pub fn ECC_Parameters_complete( + &mut self, + ) -> Result { + let mut resp = ECC_ParametersResponse::default(); + self.tpm.process_response(TPM_CC::ECC_Parameters, &mut resp)?; + Ok(resp.parameters) + } + + /// This command supports two-phase key exchange protocols. The command is used in combination + /// with TPM2_EC_Ephemeral(). TPM2_EC_Ephemeral() generates an ephemeral key and returns the + /// public point of that ephemeral key along with a numeric value that allows the TPM to + /// regenerate the associated private key. + /// outZ1 - X and Y coordinates of the computed value (scheme dependent) + /// outZ2 - X and Y coordinates of the second computed value (scheme dependent) + pub fn ZGen_2Phase_complete( + &mut self, + ) -> Result { + let mut resp = ZGen_2PhaseResponse::default(); + self.tpm.process_response(TPM_CC::ZGen_2Phase, &mut resp)?; + Ok(resp) + } + + /// This command performs ECC encryption as described in Part 1, Annex D. + /// C1 - The public ephemeral key used for ECDH + /// C2 - The data block produced by the XOR process + /// C3 - The integrity value + pub fn ECC_Encrypt_complete( + &mut self, + ) -> Result { + let mut resp = ECC_EncryptResponse::default(); + self.tpm.process_response(TPM_CC::ECC_Encrypt, &mut resp)?; + Ok(resp) + } + + /// This command performs ECC decryption. + /// plainText - Decrypted output + pub fn ECC_Decrypt_complete( + &mut self, + ) -> Result, TpmError> { + let mut resp = ECC_DecryptResponse::default(); + self.tpm.process_response(TPM_CC::ECC_Decrypt, &mut resp)?; + Ok(resp.plainText) + } + + /// NOTE 1 This command is deprecated, and TPM2_EncryptDecrypt2() is preferred. This should be + /// reflected in platform-specific specifications. + /// outData - Encrypted or decrypted output + /// ivOut - Chaining value to use for IV in next round + pub fn EncryptDecrypt_complete( + &mut self, + ) -> Result { + let mut resp = EncryptDecryptResponse::default(); + self.tpm.process_response(TPM_CC::EncryptDecrypt, &mut resp)?; + Ok(resp) + } + + /// This command is identical to TPM2_EncryptDecrypt(), except that the inData parameter is + /// the first parameter. This permits inData to be parameter encrypted. + /// outData - Encrypted or decrypted output + /// ivOut - Chaining value to use for IV in next round + pub fn EncryptDecrypt2_complete( + &mut self, + ) -> Result { + let mut resp = EncryptDecrypt2Response::default(); + self.tpm.process_response(TPM_CC::EncryptDecrypt2, &mut resp)?; + Ok(resp) + } + + /// This command performs a hash operation on a data buffer and returns the results. + /// outHash - Results + /// validation - Ticket indicating that the sequence of octets used to compute outDigest + /// did not start with TPM_GENERATED_VALUE + /// will be a NULL ticket if the digest may not be signed with a restricted key + pub fn Hash_complete( + &mut self, + ) -> Result { + let mut resp = HashResponse::default(); + self.tpm.process_response(TPM_CC::Hash, &mut resp)?; + Ok(resp) + } + + /// This command performs an HMAC on the supplied data using the indicated hash algorithm. + /// outHMAC - The returned HMAC in a sized buffer + pub fn HMAC_complete( + &mut self, + ) -> Result, TpmError> { + let mut resp = HMACResponse::default(); + self.tpm.process_response(TPM_CC::HMAC, &mut resp)?; + Ok(resp.outHMAC) + } + + /// This command performs an HMAC or a block cipher MAC on the supplied data using the + /// indicated algorithm. + /// outMAC - The returned MAC in a sized buffer + pub fn MAC_complete( + &mut self, + ) -> Result, TpmError> { + let mut resp = MACResponse::default(); + self.tpm.process_response(TPM_CC::MAC, &mut resp)?; + Ok(resp.outMAC) + } + + /// This command returns the next bytesRequested octets from the random number generator (RNG). + /// randomBytes - The random octets + pub fn GetRandom_complete( + &mut self, + ) -> Result, TpmError> { + let mut resp = GetRandomResponse::default(); + self.tpm.process_response(TPM_CC::GetRandom, &mut resp)?; + Ok(resp.randomBytes) + } + + /// This command is used to add "additional information" to the RNG state. + pub fn StirRandom_complete( + &mut self, + ) -> Result<(), TpmError> { + let mut resp = EmptyTpmResponse::default(); + self.tpm.process_response(TPM_CC::StirRandom, &mut resp)?; + Ok(()) + } + + /// This command starts an HMAC sequence. The TPM will create and initialize an HMAC sequence + /// structure, assign a handle to the sequence, and set the authValue of the sequence object + /// to the value in auth. + /// handle - A handle to reference the sequence + pub fn HMAC_Start_complete( + &mut self, + ) -> Result { + let mut resp = HMAC_StartResponse::default(); + self.tpm.process_response(TPM_CC::HMAC_Start, &mut resp)?; + Ok(resp.handle) + } + + /// This command starts a MAC sequence. The TPM will create and initialize a MAC sequence + /// structure, assign a handle to the sequence, and set the authValue of the sequence object + /// to the value in auth. + /// handle - A handle to reference the sequence + pub fn MAC_Start_complete( + &mut self, + ) -> Result { + let mut resp = MAC_StartResponse::default(); + self.tpm.process_response(TPM_CC::MAC_Start, &mut resp)?; + Ok(resp.handle) + } + + /// This command starts a hash or an Event Sequence. If hashAlg is an implemented hash, then a + /// hash sequence is started. If hashAlg is TPM_ALG_NULL, then an Event Sequence is started. + /// If hashAlg is neither an implemented algorithm nor TPM_ALG_NULL, then the TPM shall return + /// TPM_RC_HASH. + /// handle - A handle to reference the sequence + pub fn HashSequenceStart_complete( + &mut self, + ) -> Result { + let mut resp = HashSequenceStartResponse::default(); + self.tpm.process_response(TPM_CC::HashSequenceStart, &mut resp)?; + Ok(resp.handle) + } + + /// This command is used to add data to a hash or HMAC sequence. The amount of data in buffer + /// may be any size up to the limits of the TPM. + pub fn SequenceUpdate_complete( + &mut self, + ) -> Result<(), TpmError> { + let mut resp = EmptyTpmResponse::default(); + self.tpm.process_response(TPM_CC::SequenceUpdate, &mut resp)?; + Ok(()) + } + + /// This command adds the last part of data, if any, to a hash/HMAC sequence and returns the result. + /// result - The returned HMAC or digest in a sized buffer + /// validation - Ticket indicating that the sequence of octets used to compute outDigest + /// did not start with TPM_GENERATED_VALUE + /// This is a NULL Ticket when the sequence is HMAC. + pub fn SequenceComplete_complete( + &mut self, + ) -> Result { + let mut resp = SequenceCompleteResponse::default(); + self.tpm.process_response(TPM_CC::SequenceComplete, &mut resp)?; + Ok(resp) + } + + /// This command adds the last part of data, if any, to an Event Sequence and returns the + /// result in a digest list. If pcrHandle references a PCR and not TPM_RH_NULL, then the + /// returned digest list is processed in the same manner as the digest list input parameter to + /// TPM2_PCR_Extend(). That is, if a bank contains a PCR associated with pcrHandle, it is + /// extended with the associated digest value from the list. + /// results - List of digests computed for the PCR + pub fn EventSequenceComplete_complete( + &mut self, + ) -> Result, TpmError> { + let mut resp = EventSequenceCompleteResponse::default(); + self.tpm.process_response(TPM_CC::EventSequenceComplete, &mut resp)?; + Ok(resp.results) + } + + /// The purpose of this command is to prove that an object with a specific Name is loaded in + /// the TPM. By certifying that the object is loaded, the TPM warrants that a public area with + /// a given Name is self-consistent and associated with a valid sensitive area. If a relying + /// party has a public area that has the same Name as a Name certified with this command, then + /// the values in that public area are correct. + /// certifyInfo - The structure that was signed + /// signature - The asymmetric signature over certifyInfo using the key referenced by signHandle + pub fn Certify_complete( + &mut self, + ) -> Result { + let mut resp = CertifyResponse::default(); + self.tpm.process_response(TPM_CC::Certify, &mut resp)?; + Ok(resp) + } + + /// This command is used to prove the association between an object and its creation data. The + /// TPM will validate that the ticket was produced by the TPM and that the ticket validates + /// the association between a loaded public area and the provided hash of the creation data + /// (creationHash). + /// certifyInfo - The structure that was signed + /// signature - The signature over certifyInfo + pub fn CertifyCreation_complete( + &mut self, + ) -> Result { + let mut resp = CertifyCreationResponse::default(); + self.tpm.process_response(TPM_CC::CertifyCreation, &mut resp)?; + Ok(resp) + } + + /// This command is used to quote PCR values. + /// quoted - The quoted information + /// signature - The signature over quoted + pub fn Quote_complete( + &mut self, + ) -> Result { + let mut resp = QuoteResponse::default(); + self.tpm.process_response(TPM_CC::Quote, &mut resp)?; + Ok(resp) + } + + /// This command returns a digital signature of the audit session digest. + /// auditInfo - The audit information that was signed + /// signature - The signature over auditInfo + pub fn GetSessionAuditDigest_complete( + &mut self, + ) -> Result { + let mut resp = GetSessionAuditDigestResponse::default(); + self.tpm.process_response(TPM_CC::GetSessionAuditDigest, &mut resp)?; + Ok(resp) + } + + /// This command returns the current value of the command audit digest, a digest of the + /// commands being audited, and the audit hash algorithm. These values are placed in an + /// attestation structure and signed with the key referenced by signHandle. + /// auditInfo - The auditInfo that was signed + /// signature - The signature over auditInfo + pub fn GetCommandAuditDigest_complete( + &mut self, + ) -> Result { + let mut resp = GetCommandAuditDigestResponse::default(); + self.tpm.process_response(TPM_CC::GetCommandAuditDigest, &mut resp)?; + Ok(resp) + } + + /// This command returns the current values of Time and Clock. + /// timeInfo - Standard TPM-generated attestation block + /// signature - The signature over timeInfo + pub fn GetTime_complete( + &mut self, + ) -> Result { + let mut resp = GetTimeResponse::default(); + self.tpm.process_response(TPM_CC::GetTime, &mut resp)?; + Ok(resp) + } + + /// The purpose of this command is to generate an X.509 certificate that proves an object with + /// a specific public key and attributes is loaded in the TPM. In contrast to TPM2_Certify, + /// which uses a TCG-defined data structure to convey attestation information, + /// TPM2_CertifyX509 encodes the attestation information in a DER-encoded X.509 certificate + /// that is compliant with RFC5280 Internet X.509 Public Key Infrastructure Certificate and + /// Certificate Revocation List (CRL) Profile. + /// addedToCertificate - A DER encoded SEQUENCE containing the DER encoded fields added to + /// partialCertificate to make it a complete RFC5280 TBSCertificate. + /// tbsDigest - The digest that was signed + /// signature - The signature over tbsDigest + pub fn CertifyX509_complete( + &mut self, + ) -> Result { + let mut resp = CertifyX509Response::default(); + self.tpm.process_response(TPM_CC::CertifyX509, &mut resp)?; + Ok(resp) + } + + /// TPM2_Commit() performs the first part of an ECC anonymous signing operation. The TPM will + /// perform the point multiplications on the provided points and return intermediate signing + /// values. The signHandle parameter shall refer to an ECC key and the signing scheme must be + /// anonymous (TPM_RC_SCHEME). + /// K - ECC point K [ds](x2, y2) + /// L - ECC point L [r](x2, y2) + /// E - ECC point E [r]P1 + /// counter - Least-significant 16 bits of commitCount + pub fn Commit_complete( + &mut self, + ) -> Result { + let mut resp = CommitResponse::default(); + self.tpm.process_response(TPM_CC::Commit, &mut resp)?; + Ok(resp) + } + + /// TPM2_EC_Ephemeral() creates an ephemeral key for use in a two-phase key exchange protocol. + /// Q - Ephemeral public key Q [r]G + /// counter - Least-significant 16 bits of commitCount + pub fn EC_Ephemeral_complete( + &mut self, + ) -> Result { + let mut resp = EC_EphemeralResponse::default(); + self.tpm.process_response(TPM_CC::EC_Ephemeral, &mut resp)?; + Ok(resp) + } + + /// This command uses loaded keys to validate a signature on a message with the message digest + /// passed to the TPM. + /// validation - This ticket is produced by TPM2_VerifySignature(). This formulation is + /// used for multiple ticket uses. The ticket provides evidence that the TPM + /// has validated that a digest was signed by a key with the Name of keyName. + /// The ticket is computed by + pub fn VerifySignature_complete( + &mut self, + ) -> Result { + let mut resp = VerifySignatureResponse::default(); + self.tpm.process_response(TPM_CC::VerifySignature, &mut resp)?; + Ok(resp.validation) + } + + /// This command causes the TPM to sign an externally provided hash with the specified + /// symmetric or asymmetric signing key. + /// signature - The signature + pub fn Sign_complete( + &mut self, + ) -> Result, TpmError> { + let mut resp = SignResponse::default(); + self.tpm.process_response(TPM_CC::Sign, &mut resp)?; + Ok(resp.signature) + } + + /// This command may be used by the Privacy Administrator or platform to change the audit + /// status of a command or to set the hash algorithm used for the audit digest, but not both + /// at the same time. + pub fn SetCommandCodeAuditStatus_complete( + &mut self, + ) -> Result<(), TpmError> { + let mut resp = EmptyTpmResponse::default(); + self.tpm.process_response(TPM_CC::SetCommandCodeAuditStatus, &mut resp)?; + Ok(()) + } + + /// This command is used to cause an update to the indicated PCR. The digests parameter + /// contains one or more tagged digest values identified by an algorithm ID. For each digest, + /// the PCR associated with pcrHandle is Extended into the bank identified by the tag (hashAlg). + pub fn PCR_Extend_complete( + &mut self, + ) -> Result<(), TpmError> { + let mut resp = EmptyTpmResponse::default(); + self.tpm.process_response(TPM_CC::PCR_Extend, &mut resp)?; + Ok(()) + } + + /// This command is used to cause an update to the indicated PCR. + /// digests - Table 80 shows the basic hash-agile structure used in this specification. To + /// handle hash agility, this structure uses the hashAlg parameter to indicate + /// the algorithm used to compute the digest and, by implication, the size of + /// the digest. + pub fn PCR_Event_complete( + &mut self, + ) -> Result, TpmError> { + let mut resp = PCR_EventResponse::default(); + self.tpm.process_response(TPM_CC::PCR_Event, &mut resp)?; + Ok(resp.digests) + } + + /// This command returns the values of all PCR specified in pcrSelectionIn. + /// pcrUpdateCounter - The current value of the PCR update counter + /// pcrSelectionOut - The PCR in the returned list + /// pcrValues - The contents of the PCR indicated in pcrSelectOut-˃ pcrSelection[] as + /// tagged digests + pub fn PCR_Read_complete( + &mut self, + ) -> Result { + let mut resp = PCR_ReadResponse::default(); + self.tpm.process_response(TPM_CC::PCR_Read, &mut resp)?; + Ok(resp) + } + + /// This command is used to set the desired PCR allocation of PCR and algorithms. This command + /// requires Platform Authorization. + /// allocationSuccess - YES if the allocation succeeded + /// maxPCR - Maximum number of PCR that may be in a bank + /// sizeNeeded - Number of octets required to satisfy the request + /// sizeAvailable - Number of octets available. Computed before the allocation. + pub fn PCR_Allocate_complete( + &mut self, + ) -> Result { + let mut resp = PCR_AllocateResponse::default(); + self.tpm.process_response(TPM_CC::PCR_Allocate, &mut resp)?; + Ok(resp) + } + + /// This command is used to associate a policy with a PCR or group of PCR. The policy + /// determines the conditions under which a PCR may be extended or reset. + pub fn PCR_SetAuthPolicy_complete( + &mut self, + ) -> Result<(), TpmError> { + let mut resp = EmptyTpmResponse::default(); + self.tpm.process_response(TPM_CC::PCR_SetAuthPolicy, &mut resp)?; + Ok(()) + } + + /// This command changes the authValue of a PCR or group of PCR. + pub fn PCR_SetAuthValue_complete( + &mut self, + ) -> Result<(), TpmError> { + let mut resp = EmptyTpmResponse::default(); + self.tpm.process_response(TPM_CC::PCR_SetAuthValue, &mut resp)?; + Ok(()) + } + + /// If the attribute of a PCR allows the PCR to be reset and proper authorization is provided, + /// then this command may be used to set the PCR in all banks to zero. The attributes of the + /// PCR may restrict the locality that can perform the reset operation. + pub fn PCR_Reset_complete( + &mut self, + ) -> Result<(), TpmError> { + let mut resp = EmptyTpmResponse::default(); + self.tpm.process_response(TPM_CC::PCR_Reset, &mut resp)?; + Ok(()) + } + + /// This command includes a signed authorization in a policy. The command ties the policy to a + /// signing key by including the Name of the signing key in the policyDigest + /// timeout - Implementation-specific time value, used to indicate to the TPM when the + /// ticket expires + /// NOTE If policyTicket is a NULL Ticket, then this shall be the Empty Buffer. + /// policyTicket - Produced if the command succeeds and expiration in the command was + /// non-zero; this ticket will use the TPMT_ST_AUTH_SIGNED structure tag. + /// See 23.2.5 + pub fn PolicySigned_complete( + &mut self, + ) -> Result { + let mut resp = PolicySignedResponse::default(); + self.tpm.process_response(TPM_CC::PolicySigned, &mut resp)?; + Ok(resp) + } + + /// This command includes a secret-based authorization to a policy. The caller proves + /// knowledge of the secret value using an authorization session using the authValue + /// associated with authHandle. A password session, an HMAC session, or a policy session + /// containing TPM2_PolicyAuthValue() or TPM2_PolicyPassword() will satisfy this requirement. + /// timeout - Implementation-specific time value used to indicate to the TPM when the + /// ticket expires + /// policyTicket - Produced if the command succeeds and expiration in the command was + /// non-zero ( See 23.2.5). This ticket will use the TPMT_ST_AUTH_SECRET + /// structure tag + pub fn PolicySecret_complete( + &mut self, + ) -> Result { + let mut resp = PolicySecretResponse::default(); + self.tpm.process_response(TPM_CC::PolicySecret, &mut resp)?; + Ok(resp) + } + + /// This command is similar to TPM2_PolicySigned() except that it takes a ticket instead of a + /// signed authorization. The ticket represents a validated authorization that had an + /// expiration time associated with it. + pub fn PolicyTicket_complete( + &mut self, + ) -> Result<(), TpmError> { + let mut resp = EmptyTpmResponse::default(); + self.tpm.process_response(TPM_CC::PolicyTicket, &mut resp)?; + Ok(()) + } + + /// This command allows options in authorizations without requiring that the TPM evaluate all + /// of the options. If a policy may be satisfied by different sets of conditions, the TPM need + /// only evaluate one set that satisfies the policy. This command will indicate that one of + /// the required sets of conditions has been satisfied. + pub fn PolicyOR_complete( + &mut self, + ) -> Result<(), TpmError> { + let mut resp = EmptyTpmResponse::default(); + self.tpm.process_response(TPM_CC::PolicyOR, &mut resp)?; + Ok(()) + } + + /// This command is used to cause conditional gating of a policy based on PCR. This command + /// together with TPM2_PolicyOR() allows one group of authorizations to occur when PCR are in + /// one state and a different set of authorizations when the PCR are in a different state. + pub fn PolicyPCR_complete( + &mut self, + ) -> Result<(), TpmError> { + let mut resp = EmptyTpmResponse::default(); + self.tpm.process_response(TPM_CC::PolicyPCR, &mut resp)?; + Ok(()) + } + + /// This command indicates that the authorization will be limited to a specific locality. + pub fn PolicyLocality_complete( + &mut self, + ) -> Result<(), TpmError> { + let mut resp = EmptyTpmResponse::default(); + self.tpm.process_response(TPM_CC::PolicyLocality, &mut resp)?; + Ok(()) + } + + /// This command is used to cause conditional gating of a policy based on the contents of an + /// NV Index. It is an immediate assertion. The NV index is validated during the + /// TPM2_PolicyNV() command, not when the session is used for authorization. + pub fn PolicyNV_complete( + &mut self, + ) -> Result<(), TpmError> { + let mut resp = EmptyTpmResponse::default(); + self.tpm.process_response(TPM_CC::PolicyNV, &mut resp)?; + Ok(()) + } + + /// This command is used to cause conditional gating of a policy based on the contents of the + /// TPMS_TIME_INFO structure. + pub fn PolicyCounterTimer_complete( + &mut self, + ) -> Result<(), TpmError> { + let mut resp = EmptyTpmResponse::default(); + self.tpm.process_response(TPM_CC::PolicyCounterTimer, &mut resp)?; + Ok(()) + } + + /// This command indicates that the authorization will be limited to a specific command code. + pub fn PolicyCommandCode_complete( + &mut self, + ) -> Result<(), TpmError> { + let mut resp = EmptyTpmResponse::default(); + self.tpm.process_response(TPM_CC::PolicyCommandCode, &mut resp)?; + Ok(()) + } + + /// This command indicates that physical presence will need to be asserted at the time the + /// authorization is performed. + pub fn PolicyPhysicalPresence_complete( + &mut self, + ) -> Result<(), TpmError> { + let mut resp = EmptyTpmResponse::default(); + self.tpm.process_response(TPM_CC::PolicyPhysicalPresence, &mut resp)?; + Ok(()) + } + + /// This command is used to allow a policy to be bound to a specific command and command parameters. + pub fn PolicyCpHash_complete( + &mut self, + ) -> Result<(), TpmError> { + let mut resp = EmptyTpmResponse::default(); + self.tpm.process_response(TPM_CC::PolicyCpHash, &mut resp)?; + Ok(()) + } + + /// This command allows a policy to be bound to a specific set of TPM entities without being + /// bound to the parameters of the command. This is most useful for commands such as + /// TPM2_Duplicate() and for TPM2_PCR_Event() when the referenced PCR requires a policy. + pub fn PolicyNameHash_complete( + &mut self, + ) -> Result<(), TpmError> { + let mut resp = EmptyTpmResponse::default(); + self.tpm.process_response(TPM_CC::PolicyNameHash, &mut resp)?; + Ok(()) + } + + /// This command allows qualification of duplication to allow duplication to a selected new parent. + pub fn PolicyDuplicationSelect_complete( + &mut self, + ) -> Result<(), TpmError> { + let mut resp = EmptyTpmResponse::default(); + self.tpm.process_response(TPM_CC::PolicyDuplicationSelect, &mut resp)?; + Ok(()) + } + + /// This command allows policies to change. If a policy were static, then it would be + /// difficult to add users to a policy. This command lets a policy authority sign a new policy + /// so that it may be used in an existing policy. + pub fn PolicyAuthorize_complete( + &mut self, + ) -> Result<(), TpmError> { + let mut resp = EmptyTpmResponse::default(); + self.tpm.process_response(TPM_CC::PolicyAuthorize, &mut resp)?; + Ok(()) + } + + /// This command allows a policy to be bound to the authorization value of the authorized entity. + pub fn PolicyAuthValue_complete( + &mut self, + ) -> Result<(), TpmError> { + let mut resp = EmptyTpmResponse::default(); + self.tpm.process_response(TPM_CC::PolicyAuthValue, &mut resp)?; + Ok(()) + } + + /// This command allows a policy to be bound to the authorization value of the authorized object. + pub fn PolicyPassword_complete( + &mut self, + ) -> Result<(), TpmError> { + let mut resp = EmptyTpmResponse::default(); + self.tpm.process_response(TPM_CC::PolicyPassword, &mut resp)?; + Ok(()) + } + + /// This command returns the current policyDigest of the session. This command allows the TPM + /// to be used to perform the actions required to pre-compute the authPolicy for an object. + /// policyDigest - The current value of the policySessionpolicyDigest + pub fn PolicyGetDigest_complete( + &mut self, + ) -> Result, TpmError> { + let mut resp = PolicyGetDigestResponse::default(); + self.tpm.process_response(TPM_CC::PolicyGetDigest, &mut resp)?; + Ok(resp.policyDigest) + } + + /// This command allows a policy to be bound to the TPMA_NV_WRITTEN attributes. This is a + /// deferred assertion. Values are stored in the policy session context and checked when the + /// policy is used for authorization. + pub fn PolicyNvWritten_complete( + &mut self, + ) -> Result<(), TpmError> { + let mut resp = EmptyTpmResponse::default(); + self.tpm.process_response(TPM_CC::PolicyNvWritten, &mut resp)?; + Ok(()) + } + + /// This command allows a policy to be bound to a specific creation template. This is most + /// useful for an object creation command such as TPM2_Create(), TPM2_CreatePrimary(), or + /// TPM2_CreateLoaded(). + pub fn PolicyTemplate_complete( + &mut self, + ) -> Result<(), TpmError> { + let mut resp = EmptyTpmResponse::default(); + self.tpm.process_response(TPM_CC::PolicyTemplate, &mut resp)?; + Ok(()) + } + + /// This command provides a capability that is the equivalent of a revocable policy. With + /// TPM2_PolicyAuthorize(), the authorization ticket never expires, so the authorization may + /// not be withdrawn. With this command, the approved policy is kept in an NV Index location + /// so that the policy may be changed as needed to render the old policy unusable. + pub fn PolicyAuthorizeNV_complete( + &mut self, + ) -> Result<(), TpmError> { + let mut resp = EmptyTpmResponse::default(); + self.tpm.process_response(TPM_CC::PolicyAuthorizeNV, &mut resp)?; + Ok(()) + } + + /// This command is used to create a Primary Object under one of the Primary Seeds or a + /// Temporary Object under TPM_RH_NULL. The command uses a TPM2B_PUBLIC as a template for the + /// object to be created. The size of the unique field shall not be checked for consistency + /// with the other object parameters. The command will create and load a Primary Object. The + /// sensitive area is not returned. + /// handle - Handle of type TPM_HT_TRANSIENT for created Primary Object + /// outPublic - The public portion of the created object + /// creationData - Contains a TPMT_CREATION_DATA + /// creationHash - Digest of creationData using nameAlg of outPublic + /// creationTicket - Ticket used by TPM2_CertifyCreation() to validate that the creation + /// data was produced by the TPM + /// name - The name of the created object + pub fn CreatePrimary_complete( + &mut self, + ) -> Result { + let mut resp = CreatePrimaryResponse::default(); + self.tpm.process_response(TPM_CC::CreatePrimary, &mut resp)?; + Ok(resp) + } + + /// This command enables and disables use of a hierarchy and its associated NV storage. The + /// command allows phEnable, phEnableNV, shEnable, and ehEnable to be changed when the proper + /// authorization is provided. + pub fn HierarchyControl_complete( + &mut self, + ) -> Result<(), TpmError> { + let mut resp = EmptyTpmResponse::default(); + self.tpm.process_response(TPM_CC::HierarchyControl, &mut resp)?; + Ok(()) + } + + /// This command allows setting of the authorization policy for the lockout (lockoutPolicy), + /// the platform hierarchy (platformPolicy), the storage hierarchy (ownerPolicy), and the + /// endorsement hierarchy (endorsementPolicy). On TPMs implementing Authenticated Countdown + /// Timers (ACT), this command may also be used to set the authorization policy for an ACT. + pub fn SetPrimaryPolicy_complete( + &mut self, + ) -> Result<(), TpmError> { + let mut resp = EmptyTpmResponse::default(); + self.tpm.process_response(TPM_CC::SetPrimaryPolicy, &mut resp)?; + Ok(()) + } + + /// This replaces the current platform primary seed (PPS) with a value from the RNG and sets + /// platformPolicy to the default initialization value (the Empty Buffer). + pub fn ChangePPS_complete( + &mut self, + ) -> Result<(), TpmError> { + let mut resp = EmptyTpmResponse::default(); + self.tpm.process_response(TPM_CC::ChangePPS, &mut resp)?; + Ok(()) + } + + /// This replaces the current endorsement primary seed (EPS) with a value from the RNG and + /// sets the Endorsement hierarchy controls to their default initialization values: ehEnable + /// is SET, endorsementAuth and endorsementPolicy are both set to the Empty Buffer. It will + /// flush any resident objects (transient or persistent) in the Endorsement hierarchy and not + /// allow objects in the hierarchy associated with the previous EPS to be loaded. + pub fn ChangeEPS_complete( + &mut self, + ) -> Result<(), TpmError> { + let mut resp = EmptyTpmResponse::default(); + self.tpm.process_response(TPM_CC::ChangeEPS, &mut resp)?; + Ok(()) + } + + /// This command removes all TPM context associated with a specific Owner. + pub fn Clear_complete( + &mut self, + ) -> Result<(), TpmError> { + let mut resp = EmptyTpmResponse::default(); + self.tpm.process_response(TPM_CC::Clear, &mut resp)?; + Ok(()) + } + + /// TPM2_ClearControl() disables and enables the execution of TPM2_Clear(). + pub fn ClearControl_complete( + &mut self, + ) -> Result<(), TpmError> { + let mut resp = EmptyTpmResponse::default(); + self.tpm.process_response(TPM_CC::ClearControl, &mut resp)?; + Ok(()) + } + + /// This command allows the authorization secret for a hierarchy or lockout to be changed + /// using the current authorization value as the command authorization. + pub fn HierarchyChangeAuth_complete( + &mut self, + ) -> Result<(), TpmError> { + let mut resp = EmptyTpmResponse::default(); + self.tpm.process_response(TPM_CC::HierarchyChangeAuth, &mut resp)?; + Ok(()) + } + + /// This command cancels the effect of a TPM lockout due to a number of successive + /// authorization failures. If this command is properly authorized, the lockout counter is set + /// to zero. + pub fn DictionaryAttackLockReset_complete( + &mut self, + ) -> Result<(), TpmError> { + let mut resp = EmptyTpmResponse::default(); + self.tpm.process_response(TPM_CC::DictionaryAttackLockReset, &mut resp)?; + Ok(()) + } + + /// This command changes the lockout parameters. + pub fn DictionaryAttackParameters_complete( + &mut self, + ) -> Result<(), TpmError> { + let mut resp = EmptyTpmResponse::default(); + self.tpm.process_response(TPM_CC::DictionaryAttackParameters, &mut resp)?; + Ok(()) + } + + /// This command is used to determine which commands require assertion of Physical Presence + /// (PP) in addition to platformAuth/platformPolicy. + pub fn PP_Commands_complete( + &mut self, + ) -> Result<(), TpmError> { + let mut resp = EmptyTpmResponse::default(); + self.tpm.process_response(TPM_CC::PP_Commands, &mut resp)?; + Ok(()) + } + + /// This command allows the platform to change the set of algorithms that are used by the TPM. + /// The algorithmSet setting is a vendor-dependent value. + pub fn SetAlgorithmSet_complete( + &mut self, + ) -> Result<(), TpmError> { + let mut resp = EmptyTpmResponse::default(); + self.tpm.process_response(TPM_CC::SetAlgorithmSet, &mut resp)?; + Ok(()) + } + + /// This command uses platformPolicy and a TPM Vendor Authorization Key to authorize a Field + /// Upgrade Manifest. + pub fn FieldUpgradeStart_complete( + &mut self, + ) -> Result<(), TpmError> { + let mut resp = EmptyTpmResponse::default(); + self.tpm.process_response(TPM_CC::FieldUpgradeStart, &mut resp)?; + Ok(()) + } + + /// This command will take the actual field upgrade image to be installed on the TPM. The + /// exact format of fuData is vendor-specific. This command is only possible following a + /// successful TPM2_FieldUpgradeStart(). If the TPM has not received a properly authorized + /// TPM2_FieldUpgradeStart(), then the TPM shall return TPM_RC_FIELDUPGRADE. + /// nextDigest - Tagged digest of the next block + /// TPM_ALG_NULL if field update is complete + /// firstDigest - Tagged digest of the first block of the sequence + pub fn FieldUpgradeData_complete( + &mut self, + ) -> Result { + let mut resp = FieldUpgradeDataResponse::default(); + self.tpm.process_response(TPM_CC::FieldUpgradeData, &mut resp)?; + Ok(resp) + } + + /// This command is used to read a copy of the current firmware installed in the TPM. + /// fuData - Field upgrade image data + pub fn FirmwareRead_complete( + &mut self, + ) -> Result, TpmError> { + let mut resp = FirmwareReadResponse::default(); + self.tpm.process_response(TPM_CC::FirmwareRead, &mut resp)?; + Ok(resp.fuData) + } + + /// This command saves a session context, object context, or sequence object context outside + /// the TPM. + /// context - This structure is used in TPM2_ContextLoad() and TPM2_ContextSave(). If the + /// values of the TPMS_CONTEXT structure in TPM2_ContextLoad() are not the same + /// as the values when the context was saved (TPM2_ContextSave()), then the TPM + /// shall not load the context. + pub fn ContextSave_complete( + &mut self, + ) -> Result { + let mut resp = ContextSaveResponse::default(); + self.tpm.process_response(TPM_CC::ContextSave, &mut resp)?; + Ok(resp.context) + } + + /// This command is used to reload a context that has been saved by TPM2_ContextSave(). + /// handle - The handle assigned to the resource after it has been successfully loaded + pub fn ContextLoad_complete( + &mut self, + ) -> Result { + let mut resp = ContextLoadResponse::default(); + self.tpm.process_response(TPM_CC::ContextLoad, &mut resp)?; + Ok(resp.handle) + } + + /// This command causes all context associated with a loaded object, sequence object, or + /// session to be removed from TPM memory. + pub fn FlushContext_complete( + &mut self, + ) -> Result<(), TpmError> { + let mut resp = EmptyTpmResponse::default(); + self.tpm.process_response(TPM_CC::FlushContext, &mut resp)?; + Ok(()) + } + + /// This command allows certain Transient Objects to be made persistent or a persistent object + /// to be evicted. + pub fn EvictControl_complete( + &mut self, + ) -> Result<(), TpmError> { + let mut resp = EmptyTpmResponse::default(); + self.tpm.process_response(TPM_CC::EvictControl, &mut resp)?; + Ok(()) + } + + /// This command reads the current TPMS_TIME_INFO structure that contains the current setting + /// of Time, Clock, resetCount, and restartCount. + /// currentTime - This structure is used in, e.g., the TPM2_GetTime() attestation and + /// TPM2_ReadClock(). + pub fn ReadClock_complete( + &mut self, + ) -> Result { + let mut resp = ReadClockResponse::default(); + self.tpm.process_response(TPM_CC::ReadClock, &mut resp)?; + Ok(resp.currentTime) + } + + /// This command is used to advance the value of the TPMs Clock. The command will fail if + /// newTime is less than the current value of Clock or if the new time is greater than + /// FFFF00000000000016. If both of these checks succeed, Clock is set to newTime. If either of + /// these checks fails, the TPM shall return TPM_RC_VALUE and make no change to Clock. + pub fn ClockSet_complete( + &mut self, + ) -> Result<(), TpmError> { + let mut resp = EmptyTpmResponse::default(); + self.tpm.process_response(TPM_CC::ClockSet, &mut resp)?; + Ok(()) + } + + /// This command adjusts the rate of advance of Clock and Time to provide a better + /// approximation to real time. + pub fn ClockRateAdjust_complete( + &mut self, + ) -> Result<(), TpmError> { + let mut resp = EmptyTpmResponse::default(); + self.tpm.process_response(TPM_CC::ClockRateAdjust, &mut resp)?; + Ok(()) + } + + /// This command returns various information regarding the TPM and its current state. + /// moreData - Flag to indicate if there are more values of this type + /// capabilityData - The capability data + pub fn GetCapability_complete( + &mut self, + ) -> Result { + let mut resp = GetCapabilityResponse::default(); + self.tpm.process_response(TPM_CC::GetCapability, &mut resp)?; + Ok(resp) + } + + /// This command is used to check to see if specific combinations of algorithm parameters are supported. + pub fn TestParms_complete( + &mut self, + ) -> Result<(), TpmError> { + let mut resp = EmptyTpmResponse::default(); + self.tpm.process_response(TPM_CC::TestParms, &mut resp)?; + Ok(()) + } + + /// This command defines the attributes of an NV Index and causes the TPM to reserve space to + /// hold the data associated with the NV Index. If a definition already exists at the NV + /// Index, the TPM will return TPM_RC_NV_DEFINED. + pub fn NV_DefineSpace_complete( + &mut self, + ) -> Result<(), TpmError> { + let mut resp = EmptyTpmResponse::default(); + self.tpm.process_response(TPM_CC::NV_DefineSpace, &mut resp)?; + Ok(()) + } + + /// This command removes an Index from the TPM. + pub fn NV_UndefineSpace_complete( + &mut self, + ) -> Result<(), TpmError> { + let mut resp = EmptyTpmResponse::default(); + self.tpm.process_response(TPM_CC::NV_UndefineSpace, &mut resp)?; + Ok(()) + } + + /// This command allows removal of a platform-created NV Index that has TPMA_NV_POLICY_DELETE SET. + pub fn NV_UndefineSpaceSpecial_complete( + &mut self, + ) -> Result<(), TpmError> { + let mut resp = EmptyTpmResponse::default(); + self.tpm.process_response(TPM_CC::NV_UndefineSpaceSpecial, &mut resp)?; + Ok(()) + } + + /// This command is used to read the public area and Name of an NV Index. The public area of + /// an Index is not privacy-sensitive and no authorization is required to read this data. + /// nvPublic - The public area of the NV Index + /// nvName - The Name of the nvIndex + pub fn NV_ReadPublic_complete( + &mut self, + ) -> Result { + let mut resp = NV_ReadPublicResponse::default(); + self.tpm.process_response(TPM_CC::NV_ReadPublic, &mut resp)?; + Ok(resp) + } + + /// This command writes a value to an area in NV memory that was previously defined by + /// TPM2_NV_DefineSpace(). + pub fn NV_Write_complete( + &mut self, + ) -> Result<(), TpmError> { + let mut resp = EmptyTpmResponse::default(); + self.tpm.process_response(TPM_CC::NV_Write, &mut resp)?; + Ok(()) + } + + /// This command is used to increment the value in an NV Index that has the TPM_NT_COUNTER + /// attribute. The data value of the NV Index is incremented by one. + pub fn NV_Increment_complete( + &mut self, + ) -> Result<(), TpmError> { + let mut resp = EmptyTpmResponse::default(); + self.tpm.process_response(TPM_CC::NV_Increment, &mut resp)?; + Ok(()) + } + + /// This command extends a value to an area in NV memory that was previously defined by + /// TPM2_NV_DefineSpace. + pub fn NV_Extend_complete( + &mut self, + ) -> Result<(), TpmError> { + let mut resp = EmptyTpmResponse::default(); + self.tpm.process_response(TPM_CC::NV_Extend, &mut resp)?; + Ok(()) + } + + /// This command is used to SET bits in an NV Index that was created as a bit field. Any + /// number of bits from 0 to 64 may be SET. The contents of bits are ORed with the current + /// contents of the NV Index. + pub fn NV_SetBits_complete( + &mut self, + ) -> Result<(), TpmError> { + let mut resp = EmptyTpmResponse::default(); + self.tpm.process_response(TPM_CC::NV_SetBits, &mut resp)?; + Ok(()) + } + + /// If the TPMA_NV_WRITEDEFINE or TPMA_NV_WRITE_STCLEAR attributes of an NV location are SET, + /// then this command may be used to inhibit further writes of the NV Index. + pub fn NV_WriteLock_complete( + &mut self, + ) -> Result<(), TpmError> { + let mut resp = EmptyTpmResponse::default(); + self.tpm.process_response(TPM_CC::NV_WriteLock, &mut resp)?; + Ok(()) + } + + /// The command will SET TPMA_NV_WRITELOCKED for all indexes that have their + /// TPMA_NV_GLOBALLOCK attribute SET. + pub fn NV_GlobalWriteLock_complete( + &mut self, + ) -> Result<(), TpmError> { + let mut resp = EmptyTpmResponse::default(); + self.tpm.process_response(TPM_CC::NV_GlobalWriteLock, &mut resp)?; + Ok(()) + } + + /// This command reads a value from an area in NV memory previously defined by TPM2_NV_DefineSpace(). + /// data - The data read + pub fn NV_Read_complete( + &mut self, + ) -> Result, TpmError> { + let mut resp = NV_ReadResponse::default(); + self.tpm.process_response(TPM_CC::NV_Read, &mut resp)?; + Ok(resp.data) + } + + /// If TPMA_NV_READ_STCLEAR is SET in an Index, then this command may be used to prevent + /// further reads of the NV Index until the next TPM2_Startup (TPM_SU_CLEAR). + pub fn NV_ReadLock_complete( + &mut self, + ) -> Result<(), TpmError> { + let mut resp = EmptyTpmResponse::default(); + self.tpm.process_response(TPM_CC::NV_ReadLock, &mut resp)?; + Ok(()) + } + + /// This command allows the authorization secret for an NV Index to be changed. + pub fn NV_ChangeAuth_complete( + &mut self, + ) -> Result<(), TpmError> { + let mut resp = EmptyTpmResponse::default(); + self.tpm.process_response(TPM_CC::NV_ChangeAuth, &mut resp)?; + Ok(()) + } + + /// The purpose of this command is to certify the contents of an NV Index or portion of an NV Index. + /// certifyInfo - The structure that was signed + /// signature - The asymmetric signature over certifyInfo using the key referenced by signHandle + pub fn NV_Certify_complete( + &mut self, + ) -> Result { + let mut resp = NV_CertifyResponse::default(); + self.tpm.process_response(TPM_CC::NV_Certify, &mut resp)?; + Ok(resp) + } + + /// The purpose of this command is to obtain information about an Attached Component + /// referenced by an AC handle. + /// moreData - Flag to indicate whether there are more values + /// capabilitiesData - List of capabilities + pub fn AC_GetCapability_complete( + &mut self, + ) -> Result { + let mut resp = AC_GetCapabilityResponse::default(); + self.tpm.process_response(TPM_CC::AC_GetCapability, &mut resp)?; + Ok(resp) + } + + /// The purpose of this command is to send (copy) a loaded object from the TPM to an Attached Component. + /// acDataOut - May include AC specific data or information about an error. + pub fn AC_Send_complete( + &mut self, + ) -> Result { + let mut resp = AC_SendResponse::default(); + self.tpm.process_response(TPM_CC::AC_Send, &mut resp)?; + Ok(resp.acDataOut) + } + + /// This command allows qualification of the sending (copying) of an Object to an Attached + /// Component (AC). Qualification includes selection of the receiving AC and the method of + /// authentication for the AC, and, in certain circumstances, the Object to be sent may be specified. + pub fn Policy_AC_SendSelect_complete( + &mut self, + ) -> Result<(), TpmError> { + let mut resp = EmptyTpmResponse::default(); + self.tpm.process_response(TPM_CC::Policy_AC_SendSelect, &mut resp)?; + Ok(()) + } + + /// This command is used to set the time remaining before an Authenticated Countdown Timer + /// (ACT) expires. + pub fn ACT_SetTimeout_complete( + &mut self, + ) -> Result<(), TpmError> { + let mut resp = EmptyTpmResponse::default(); + self.tpm.process_response(TPM_CC::ACT_SetTimeout, &mut resp)?; + Ok(()) + } + + /// This is a placeholder to allow testing of the dispatch code. + /// outputData - Dummy data + pub fn Vendor_TCG_Test_complete( + &mut self, + ) -> Result, TpmError> { + let mut resp = Vendor_TCG_TestResponse::default(); + self.tpm.process_response(TPM_CC::Vendor_TCG_Test, &mut resp)?; + Ok(resp.outputData) + } + +} + diff --git a/TSS.Rust/src/tpm2_helpers.rs b/TSS.Rust/src/tpm2_helpers.rs new file mode 100644 index 00000000..34904e5d --- /dev/null +++ b/TSS.Rust/src/tpm2_helpers.rs @@ -0,0 +1,55 @@ +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See the LICENSE file in the project root for full license information. + */ + +use crate::{tpm_buffer::TpmBuffer, tpm_types::ENUM_TO_STR_MAP}; + +/// Convert a numeric enum value to its string representation +/// +/// # Arguments +/// +/// * `enum_val` - The numeric value of the enum +/// * `enum_id` - The identifier of the enum type +/// +/// # Returns +/// +/// The string representation of the enum value, or a formatted string of OR'd values +pub fn enum_to_str(enum_val: u64, enum_id: std::any::TypeId) -> String { + let mut res = String::new(); + + // Try to find the exact enum value in the map + if let Some(enum_map) = ENUM_TO_STR_MAP.get(&enum_id) { + if let Some(name) = enum_map.get(&enum_val) { + return name.to_string(); + } + + // If not found as an exact match, try to decompose as bit flags + let mut cur_bit: u64 = 1; + let mut found_bits: u64 = 0; + + while (found_bits != enum_val) { + if (cur_bit & enum_val) != 0 { + found_bits |= cur_bit; + + if !res.is_empty() { + res.push_str(" | "); + } + + if let Some(bit_name) = enum_map.get(&cur_bit) { + res.push_str(bit_name); + } + } + + cur_bit <<= 1; + } + } + + res // Return empty string if enum ID is not found +} + +pub fn int_to_tpm>(val: T) -> Vec { + let mut buffer = TpmBuffer::new(None); + buffer.write_num(val.into(), std::mem::size_of::().into()); + buffer.trim().to_vec() +} \ No newline at end of file diff --git a/TSS.Rust/src/tpm2_impl.rs b/TSS.Rust/src/tpm2_impl.rs new file mode 100644 index 00000000..74936a83 --- /dev/null +++ b/TSS.Rust/src/tpm2_impl.rs @@ -0,0 +1,1309 @@ +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See the LICENSE file in the project root for full license information. + */ + +use crate::auth_session::Session; +use crate::crypto::Crypto; +use crate::device::TpmDevice; +use crate::error::TpmError; +use crate::tpm_buffer::{TpmBuffer, TpmMarshaller}; +use crate::tpm_structure::{CmdStructure, ReqStructure, RespStructure, TpmEnum}; +use crate::tpm_types::{ + TPMA_SESSION, TPMS_AUTH_COMMAND, TPMS_AUTH_RESPONSE, TPMT_HA, TPMT_SYM_DEF, TPM_ALG_ID, + TPM_CC, TPM_HANDLE, TPM_HT, TPM_RC, TPM_RH, TPM_SE, TPM_ST, +}; + +/// A TPM error with associated command and context information +#[derive(Debug, Clone)] +pub struct TpmCommandError { + /// Response code returned by the TPM + pub response_code: TPM_RC, + /// Command code that triggered the error + pub command_code: TPM_CC, + /// Description of the error + pub message: String, +} + +impl std::fmt::Display for TpmCommandError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!( + f, + "TPM command {:?} failed with response code {:?}: {}", + self.command_code, self.response_code, self.message + ) + } +} + +impl std::error::Error for TpmCommandError {} + +impl From for TpmError { + fn from(err: TpmCommandError) -> Self { + TpmError::GenericError(err.to_string()) + } +} + +/// Base implementation for TPM operations +pub struct Tpm2 { + /// The TPM device used for communication + device: Box, + + /// Response code returned by the last executed command + last_response_code: TPM_RC, + + /// Error object (may be None) generated during the last TPM command execution + last_error: Option, + + /// TPM sessions associated with the next command + sessions: Option>, + + /// Controls whether exceptions are enabled + exceptions_enabled: bool, + + /// Suppresses exceptions in response to the next command failure, when exceptions are enabled + errors_allowed: bool, + + /// Command code for the current operation (for error reporting) + current_cmd_code: Option, + + /// Session tag for the current operation + current_session_tag: Option, + + /// Handle for pending TPM commands + pending_command: Option, + + /// Input handles for current command + in_handles: Vec, + + /// Auth value for objects + object_in_auth: Vec, + + /// Name for objects + object_in_name: Vec, + + /// Admin authorization handles with auth values + admin_platform: TPM_HANDLE, + admin_owner: TPM_HANDLE, + admin_endorsement: TPM_HANDLE, + admin_lockout: TPM_HANDLE, + + /// CpHash for parameter encryption + cp_hash: Option, + + /// Command audit hash + command_audit_hash: TPMT_HA, + + /// Audit command flag + audit_command: bool, + + /// Audit CpHash + audit_cp_hash: TPMT_HA, + + /// Encryption session + enc_session: Option, + + /// Decryption session + dec_session: Option, + + /// Nonces for TPM parameter encryption/decryption + nonce_tpm_dec: Vec, + nonce_tpm_enc: Vec, + + /// Command buffer for last command + last_command_buf: Vec, + + /// Last command's serialized parameters (before handles) + last_cmd_params: Vec, + + /// Sessions updated after the last command (preserved for continueSession) + completed_sessions: Option>, +} + +impl Tpm2 { + /// Creates a new Tpm2 with the specified device + pub fn new(device: Box) -> Self { + Tpm2 { + device, + last_response_code: TPM_RC::SUCCESS, + last_error: None, + sessions: None, + exceptions_enabled: false, + errors_allowed: true, + current_cmd_code: None, + current_session_tag: None, + pending_command: None, + in_handles: Vec::new(), + object_in_auth: Vec::new(), + object_in_name: Vec::new(), + admin_platform: TPM_HANDLE::new(0), + admin_owner: TPM_HANDLE::new(0), + admin_endorsement: TPM_HANDLE::new(0), + admin_lockout: TPM_HANDLE::new(0), + cp_hash: None, + command_audit_hash: TPMT_HA::default(), + audit_command: false, + audit_cp_hash: TPMT_HA::default(), + enc_session: None, + dec_session: None, + nonce_tpm_dec: Vec::new(), + nonce_tpm_enc: Vec::new(), + last_command_buf: Vec::new(), + last_cmd_params: Vec::new(), + completed_sessions: None, + } + } + + /// Checks whether the response code is generated by the TSS.Rust implementation + fn is_comm_medium_error(code: TPM_RC) -> bool { + // Check if error is in the TSS communication layer rather than TPM itself + (code.get_value()) & 0xFFFF0000 == 0x80280000 + } + + /// Cleans the raw response code from the TPM + fn response_code_from_tpm_error(raw_response: TPM_RC) -> TPM_RC { + if Self::is_comm_medium_error(raw_response) { + return raw_response; + } + + let raw_response_u32 = raw_response.get_value(); + let is_fmt = (raw_response_u32 & TPM_RC::RC_FMT1.get_value()) != 0; + + + let mask: u32 = if is_fmt { 0xBF } else { 0x97F }; + + TPM_RC { 0: (raw_response_u32 & mask) } + } + + /// Send a TPM command to the underlying TPM device. + pub fn dispatch( + &mut self, + cmd_code: TPM_CC, + req: R, + resp: &mut S, + ) -> Result<(), TpmError> { + loop { + let process_phase_two = match self.dispatch_command(cmd_code, &req) { + Ok(v) => v, + Err(e) => { + self.current_cmd_code = None; + return Err(e); + } + }; + match self.process_response(cmd_code, resp) { + Ok(done) => { + if !process_phase_two || done { + break; + } + } + Err(e) => { + self.current_cmd_code = None; + return Err(e); + } + } + std::thread::sleep(std::time::Duration::from_millis(1000)); + } + + Ok(()) + } + + /// Internal method to dispatch a command to the TPM + pub fn dispatch_command( + &mut self, + cmd_code: TPM_CC, + req: &R, + ) -> Result<(bool), TpmError> { + if self.current_cmd_code.is_some() { + return Err(TpmError::GenericError( + "Pending async command must be completed before issuing the next command." + .to_string(), + )); + } + + if self.audit_command && self.command_audit_hash.hashAlg == TPM_ALG_ID::NULL { + return Err(TpmError::GenericError( + "Command audit is not enabled".to_string(), + )); + } + + self.current_cmd_code = Some(cmd_code); + + // Determine session tag based on whether we need authorization + let num_auth_handles = req.num_auth_handles(); + let has_sessions = num_auth_handles > 0 || self.sessions.is_some(); + self.current_session_tag = if has_sessions { + Some(TPM_ST::SESSIONS) + } else { + Some(TPM_ST::NO_SESSIONS) + }; + + let mut cmd_buf = TpmBuffer::new(None); + + // Create command buffer header + cmd_buf.writeShort(self.current_session_tag.unwrap().get_value() as u16); + cmd_buf.writeInt(0); // to be filled in later + cmd_buf.writeInt(cmd_code.get_value()); + + // Marshal handles + self.in_handles = req.get_handles(); + // Set auth values for well-known admin handles (OWNER, LOCKOUT, ENDORSEMENT, PLATFORM) + for h in self.in_handles.iter_mut() { + Self::set_rh_auth_value_static(h, &self.admin_owner, &self.admin_endorsement, &self.admin_platform, &self.admin_lockout); + } + for handle in self.in_handles.iter() { + handle.toTpm(&mut cmd_buf)?; + } + + // Marshal command parameters to a separate buffer + let mut param_buf = TpmBuffer::new(None); + req.toTpm(&mut param_buf)?; + param_buf.trim(); + self.last_cmd_params = param_buf.buffer().clone(); + + // Process authorization sessions if present + let mut cp_hash_data = Vec::new(); + + if has_sessions { + // We do not know the size of the authorization area yet. + // Remember the place to marshal it, ... + let auth_size_pos = cmd_buf.current_pos(); + // ... and marshal a placeholder 0 value for now. + cmd_buf.writeInt(0); + + // If not all required sessions were provided explicitly, create the necessary + // number of password sessions with auth values from the corresponding TPM_HANDLE objects. + if let Some(ref mut sessions) = self.sessions { + // Ensure we have enough sessions + if sessions.len() < num_auth_handles as usize { + for _ in sessions.len()..(num_auth_handles as usize) { + sessions.push(Session::pw(None)); + } + } + + // Roll nonces + self.roll_nonces(); + + // Prepare parameter encryption sessions + self.prepare_param_encryption_sessions(); + + // Do parameter encryption if needed + self.do_param_encryption(req, &mut param_buf, 0, true)?; + + // Process authorization sessions and get cpHash data + cp_hash_data = self.process_auth_sessions( + &mut cmd_buf, + cmd_code, + num_auth_handles, + ¶m_buf.buffer(), + )?; + } else { + // Create all password sessions with auth from the corresponding handles + let mut new_sessions = Vec::with_capacity(num_auth_handles as usize); + for i in 0..num_auth_handles as usize { + let auth = if i < self.in_handles.len() { + Some(self.in_handles[i].auth_value.clone()) + } else { + None + }; + new_sessions.push(Session::pw(auth)); + } + + // Marshal sessions to command buffer + for sess in new_sessions.iter() { + sess.sess_in.toTpm(&mut cmd_buf)?; + } + + self.sessions = Some(new_sessions); + } + + // Update the auth area size + cmd_buf.write_num_at_pos( + (cmd_buf.current_pos() - auth_size_pos - 4) as u64, + auth_size_pos, + 4, + ); + } + + // Write marshaled command params to the command buffer + cmd_buf.writeByteBuf(¶m_buf.buffer()); + + // Fill in command buffer size in the command header + cmd_buf.write_num_at_pos(cmd_buf.current_pos() as u64, 2, 4); + cmd_buf.trim(); + + // Handle CpHash and Audit processing + if self.cp_hash.is_some() || self.audit_command { + if cp_hash_data.is_empty() { + cp_hash_data = self.get_cp_hash_data(cmd_code, ¶m_buf.buffer())?; + } + + if let Some(ref mut cp_hash) = self.cp_hash { + cp_hash.digest = Crypto::hash(cp_hash.hashAlg, &cp_hash_data)?; + self.clear_invocation_state(); + self.sessions = None; + self.cp_hash = None; + return Ok(false); + } + + if self.audit_command { + self.audit_cp_hash.digest = + Crypto::hash(self.command_audit_hash.hashAlg, &cp_hash_data)?; + } + } + + // Dispatch command to the device + self.last_command_buf = cmd_buf.trim().to_vec(); + self.device.dispatch_command(&self.last_command_buf)?; + + // Update request handles based on command + self.update_request_handles(cmd_code)?; + + // Set pending command + self.pending_command = Some(cmd_code); + + Ok(true) + } + + /// Process the TPM response and update the response structure + pub fn process_response( + &mut self, + cmd_code: TPM_CC, + resp_struct: &mut T, + ) -> Result<(bool), TpmError> { + if self.pending_command.is_none() { + return Err(TpmError::GenericError( + "Async command completion with no outstanding command".to_string(), + )); + } + + if self.pending_command.unwrap() != cmd_code { + return Err(TpmError::GenericError( + "Async command completion does not match command being processed".to_string(), + )); + } + + if self.audit_command && self.command_audit_hash.hashAlg == TPM_ALG_ID::NULL { + return Err(TpmError::GenericError( + "Command audit is not enabled".to_string(), + )); + } + + self.pending_command = None; + + // Get response from the TPM device + let raw_resp_buf = self.device.get_response()?; + + if raw_resp_buf.len() < 10 { + return Err(TpmError::GenericError(format!( + "Too short TPM response of {} B received", + raw_resp_buf.len() + ))); + } + + let mut resp_buf = TpmBuffer::from(&raw_resp_buf); + + // Read the response header + let resp_tag = TPM_ST::try_from(resp_buf.readShort())?; + let resp_size = resp_buf.readInt(); + let resp_code = TPM_RC::try_from(resp_buf.readInt())?; + + let act_resp_size = resp_buf.size(); + if resp_size as usize != act_resp_size { + return Err(TpmError::GenericError(format!( + "Inconsistent TPM response buffer: {} B reported, {} B received", + resp_size, act_resp_size + ))); + } + + if resp_code == TPM_RC::RETRY { + return Ok(false); + } + + // Clean and store the response code + self.last_response_code = Self::response_code_from_tpm_error(resp_code); + + // Figure out our reaction to the received response. This logic depends on: + // errors_allowed - no exception, regardless of success or failure + + // Store a copy of audit command flag before clearing invocation state + let audit_command = self.audit_command; + + // Handle errors and clean up invocation state + if resp_code != TPM_RC::SUCCESS { + self.clear_invocation_state(); + self.sessions = None; + + // Return error + return Err(TpmError::GenericError(format!( + "TPM Error - TPM_RC::{:?}", + self.last_response_code + ))); + } + + // A check for the session tag consistency across the command invocation + let sess_tag = self.current_session_tag.unwrap_or(TPM_ST::NULL); + if resp_tag != sess_tag { + self.clear_invocation_state(); + self.sessions = None; + return Err(TpmError::GenericError( + "Wrong response session tag".to_string(), + )); + } + + // + // The command succeeded, so we can process the response buffer + // + + // Get the handles if any + if resp_struct.num_handles() > 0 { + let handle_val = resp_buf.readInt(); + resp_struct.set_handle(&TPM_HANDLE::new(handle_val)); + } + + let resp_params_pos: usize; + let resp_params_size: usize; + let mut rp_ready = false; + + // If there are no sessions then response parameters take up the remaining part + // of the response buffer. Otherwise the response parameters area is preceded with + // its size, and followed by the session area. + if sess_tag == TPM_ST::SESSIONS { + resp_params_size = resp_buf.readInt() as usize; + resp_params_pos = resp_buf.current_pos(); + + // Process response sessions, including verification of response HMACs + rp_ready = match self.process_resp_sessions( + &mut resp_buf, + cmd_code, + resp_params_pos, + resp_params_size, + ) { + Ok(ready) => ready, + Err(e) => { + self.clear_invocation_state(); + self.sessions = None; + return Err(e); + } + }; + } else { + resp_params_pos = resp_buf.current_pos(); + resp_params_size = resp_buf.size() - resp_params_pos; + } + + // Update enc_session/dec_session nonces from the processed sessions + if let Some(ref sessions) = self.sessions { + if let Some(ref mut enc) = self.enc_session { + for s in sessions.iter() { + if s.sess_in.sessionHandle.handle == enc.sess_in.sessionHandle.handle { + enc.sess_out.nonce = s.sess_out.nonce.clone(); + enc.sess_in.nonce = s.sess_in.nonce.clone(); + break; + } + } + } + if let Some(ref mut dec) = self.dec_session { + for s in sessions.iter() { + if s.sess_in.sessionHandle.handle == dec.sess_in.sessionHandle.handle { + dec.sess_out.nonce = s.sess_out.nonce.clone(); + dec.sess_in.nonce = s.sess_in.nonce.clone(); + break; + } + } + } + } + + // Handle audit processing + if audit_command { + let rp_hash = self.get_rp_hash( + self.command_audit_hash.hashAlg, + &mut resp_buf, + cmd_code, + resp_params_pos, + resp_params_size, + rp_ready, + )?; + + // Extend audit digest: CommandAuditHash = H(CommandAuditHash || cpHash || rpHash) + let hash_alg = self.command_audit_hash.hashAlg; + let mut extend_data = Vec::new(); + extend_data.extend_from_slice(&self.command_audit_hash.digest); + extend_data.extend_from_slice(&self.audit_cp_hash.digest); + extend_data.extend_from_slice(&rp_hash); + if let Ok(new_digest) = Crypto::hash(hash_alg, &extend_data) { + self.command_audit_hash.digest = new_digest; + } + } + + // Parameter decryption (if necessary) + if let Err(e) = self.do_param_encryption(resp_struct, &mut resp_buf, resp_params_pos, false) + { + self.clear_invocation_state(); + self.sessions = None; + return Err(e); + } + // Clear encryption session state after use + self.enc_session = None; + self.dec_session = None; + + // Reset position to start of parameters area and unmarshall + resp_buf.set_current_pos(resp_params_pos); + resp_struct.initFromTpm(&mut resp_buf)?; + + // Validate that we read the exact number of bytes expected + if resp_buf.current_pos() != resp_params_pos + resp_params_size { + self.clear_invocation_state(); + self.sessions = None; + return Err(TpmError::GenericError( + "Bad response parameters area".to_string(), + )); + } + + // Update response handle with name and auth value + if let Err(e) = self.update_resp_handle(cmd_code, resp_struct) { + self.clear_invocation_state(); + self.sessions = None; + return Err(e); + } + + // Complete post-command handle updates (e.g., HierarchyChangeAuth auth tracking) + if let Err(e) = self.complete_update_request_handles(cmd_code) { + self.clear_invocation_state(); + self.sessions = None; + return Err(e); + } + + // Preserve sessions with continueSession for reuse, otherwise clear + self.completed_sessions = self.sessions.take(); + self.clear_invocation_state(); + + Ok(true) + } +} + +impl Tpm2 { + pub fn last_response_code(&self) -> TPM_RC { + self.last_response_code + } + + pub fn last_error(&self) -> Option { + self.last_error.clone() + } + + pub fn allow_errors(&mut self) -> &mut Self { + self.errors_allowed = true; + self + } + + pub fn enable_exceptions(&mut self, enable: bool) { + self.exceptions_enabled = enable; + self.errors_allowed = !enable; + } + + pub fn with_session(&mut self, session: Session) -> &mut Self { + self.sessions = Some(vec![session]); + self + } + + pub fn with_sessions(&mut self, sessions: Vec) -> &mut Self { + self.sessions = Some(sessions); + self + } + + /// Get the updated session after the last command completed. + /// This is needed when reusing HMAC/policy sessions across commands, + /// since the TPM updates nonces after each command. + pub fn last_sessions(&self) -> Option<&Vec> { + self.completed_sessions.as_ref() + } + + /// Get the first updated session from the last completed command. + /// Convenience method for the common single-session case. + pub fn last_session(&self) -> Option { + self.completed_sessions.as_ref() + .and_then(|s| s.first().cloned()) + } + + pub fn connect(&mut self) -> Result<(), TpmError> { + self.device.connect()?; + self.last_response_code = TPM_RC::SUCCESS; + Ok(()) + } + + pub fn close(&mut self) { + self.device.close(); + } +} + +/// High-level convenience methods for session management and common patterns. +impl Tpm2 { + /// Start a simple HMAC or policy auth session (no salt, no binding). + pub fn start_auth_session( + &mut self, + session_type: TPM_SE, + auth_hash: TPM_ALG_ID, + ) -> Result { + self.start_auth_session_full( + session_type, + auth_hash, + TPMA_SESSION::continueSession, + TPMT_SYM_DEF::default(), + ) + } + + /// Start an auth session with explicit attributes and symmetric definition. + pub fn start_auth_session_full( + &mut self, + session_type: TPM_SE, + auth_hash: TPM_ALG_ID, + attributes: TPMA_SESSION, + symmetric: TPMT_SYM_DEF, + ) -> Result { + let null_handle = TPM_HANDLE::new(TPM_RH::NULL.get_value()); + + self.start_auth_session_ex( + &null_handle, // tpmKey (no salt) + &null_handle, // bind (no binding) + session_type, + auth_hash, + attributes, + symmetric, + &[], // no salt + ) + } + + /// Start an auth session with full control (salt key, bind object, etc.). + pub fn start_auth_session_ex( + &mut self, + tpm_key: &TPM_HANDLE, + bind: &TPM_HANDLE, + session_type: TPM_SE, + auth_hash: TPM_ALG_ID, + attributes: TPMA_SESSION, + symmetric: TPMT_SYM_DEF, + salt: &[u8], + ) -> Result { + let nonce_size = Crypto::digestSize(auth_hash); + let nonce_caller = Crypto::get_random(nonce_size); + + // For salted sessions, encrypt the salt to the tpmKey's public area + let encrypted_salt = if !salt.is_empty() { + let pub_info = self.ReadPublic(tpm_key)?; + pub_info.outPublic.encrypt_session_salt(salt)? + } else { + Vec::new() + }; + + let resp = self.StartAuthSession( + tpm_key, + bind, + &nonce_caller, + &encrypted_salt, + session_type, + &symmetric, + auth_hash, + )?; + + Session::from_tpm_response( + resp.handle, + session_type, + auth_hash, + nonce_caller, + resp.nonceTPM, + attributes, + symmetric, + salt, + bind, + ) + } + + /// Set a session on this Tpm2 for the next command. + pub fn set_sessions(&mut self, sessions: Vec) { + self.sessions = Some(sessions); + } +} + +impl Tpm2 { + // Additional helper methods to support the dispatch_command and process_response implementations + + /// Roll nonces for all non-PWAP sessions + fn roll_nonces(&mut self) { + if let Some(ref mut sessions) = self.sessions { + for session in sessions.iter_mut() { + if !session.is_pwap() { + let nonce_size = session.sess_out.nonce.len(); + session.sess_in.nonce = Crypto::get_random(nonce_size.max(16)); + } + } + } + } + + /// Clear the current invocation state + fn clear_invocation_state(&mut self) { + self.current_cmd_code = None; + self.current_session_tag = None; + // Clear other command-specific state + } + + /// Set the auth value for an admin hierarchy handle. + /// Use this when the TPM's hierarchy auth was set externally (e.g., recovering from a + /// previous run that changed auth but failed to reset it). + pub fn set_admin_auth(&mut self, hierarchy: TPM_RH, auth: &[u8]) { + let val = hierarchy.get_value(); + if val == TPM_RH::OWNER.get_value() { + self.admin_owner.set_auth(auth); + } else if val == TPM_RH::ENDORSEMENT.get_value() { + self.admin_endorsement.set_auth(auth); + } else if val == TPM_RH::PLATFORM.get_value() { + self.admin_platform.set_auth(auth); + } else if val == TPM_RH::LOCKOUT.get_value() { + self.admin_lockout.set_auth(auth); + } + } + + /// Set auth values for well-known admin handles (avoids borrow issues) + fn set_rh_auth_value_static(h: &mut TPM_HANDLE, admin_owner: &TPM_HANDLE, admin_endorsement: &TPM_HANDLE, admin_platform: &TPM_HANDLE, admin_lockout: &TPM_HANDLE) { + match h.handle { + val if val == TPM_RH::OWNER.get_value() => h.set_auth(&admin_owner.auth_value), + val if val == TPM_RH::ENDORSEMENT.get_value() => { + h.set_auth(&admin_endorsement.auth_value) + } + val if val == TPM_RH::PLATFORM.get_value() => { + h.set_auth(&admin_platform.auth_value) + } + val if val == TPM_RH::LOCKOUT.get_value() => h.set_auth(&admin_lockout.auth_value), + _ => {} // No auth value change needed + } + } + + /// Get CpHash data for parameter encryption + fn get_cp_hash_data(&self, cmd_code: TPM_CC, cmd_params: &[u8]) -> Result, TpmError> { + let mut buf = TpmBuffer::new(None); + buf.writeInt(cmd_code.get_value()); + + for h in self.in_handles.iter() { + let name = h.get_name()?; + buf.writeByteBuf(&name); + } + + buf.writeByteBuf(&cmd_params.to_vec()); + Ok(buf.buffer().clone()) + } + + /// Process authorization sessions for a command + fn process_auth_sessions( + &mut self, + cmd_buf: &mut TpmBuffer, + cmd_code: TPM_CC, + num_auth_handles: u16, + cmd_params: &[u8], + ) -> Result, TpmError> { + let mut needs_hmac = false; + + if let Some(ref sessions) = self.sessions { + for session in sessions.iter() { + if !session.is_pwap() { + needs_hmac = true; + break; + } + } + } + + // Compute CpHash if needed for HMAC sessions + let cp_hash_data = if needs_hmac { + self.get_cp_hash_data(cmd_code, cmd_params)? + } else { + Vec::new() + }; + + if let Some(ref mut sessions) = self.sessions { + for (i, session) in sessions.iter().enumerate() { + let mut auth_cmd = TPMS_AUTH_COMMAND::default(); + + // If it's a PWAP session, handling is simple + if session.is_pwap() { + auth_cmd.sessionHandle = TPM_HANDLE::new(TPM_RH::PW.get_value()); + auth_cmd.nonce = Vec::new(); + + if i < self.in_handles.len() { + auth_cmd.hmac = self.in_handles[i].auth_value.clone(); + } + + auth_cmd.sessionAttributes = TPMA_SESSION::continueSession; + auth_cmd.toTpm(cmd_buf)?; + continue; + } + + // For non-PWAP sessions, we need more complex processing + let mut h_copy = None; + + if i < num_auth_handles as usize { + if i < self.in_handles.len() { + // Set appropriate auth value on handle + h_copy = Some(self.in_handles[i].clone()); + } + } + + auth_cmd.nonce = session.sess_in.nonce.clone(); + auth_cmd.sessionHandle = session.sess_in.sessionHandle.clone(); + auth_cmd.sessionAttributes = session.sess_in.sessionAttributes; + + if session.session_type == TPM_SE::HMAC || session.needs_hmac { + // Calculate HMAC based on CpHash + let cp_hash = Crypto::hash(session.get_hash_alg(), &cp_hash_data)?; + auth_cmd.hmac = session.get_auth_hmac( + cp_hash, + true, + &self.nonce_tpm_dec, + &self.nonce_tpm_enc, + h_copy.as_ref(), + )?; + } else if session.needs_password { + auth_cmd.hmac = self.in_handles[i].auth_value.clone(); + } + + auth_cmd.toTpm(cmd_buf)?; + } + } + + Ok(cp_hash_data) + } + + /// Prepare parameter encryption sessions + fn prepare_param_encryption_sessions(&mut self) { + self.enc_session = None; + self.dec_session = None; + self.nonce_tpm_dec.clear(); + self.nonce_tpm_enc.clear(); + + if let Some(ref sessions) = self.sessions { + for session in sessions.iter() { + if session.is_pwap() { + continue; + } + + // Check for decrypt attribute + if (session.sess_in.sessionAttributes.get_value() + & TPMA_SESSION::decrypt.get_value()) + != 0 + { + self.dec_session = Some(session.clone()); + } + + // Check for encrypt attribute + if (session.sess_in.sessionAttributes.get_value() + & TPMA_SESSION::encrypt.get_value()) + != 0 + { + self.enc_session = Some(session.clone()); + } + } + + // Store nonces for the first session to prevent tampering + if let Some(ref sessions_vec) = self.sessions { + if !sessions_vec.is_empty() { + let first_session = &sessions_vec[0]; + + // If first session is followed by decrypt session + if let Some(ref dec) = self.dec_session { + if dec.sess_in.sessionHandle.handle + != first_session.sess_in.sessionHandle.handle + { + self.nonce_tpm_dec = dec.sess_out.nonce.clone(); + } + } + + // If first session is followed by encrypt session (and it's not the decrypt session) + if let Some(ref enc) = self.enc_session { + if enc.sess_in.sessionHandle.handle + != first_session.sess_in.sessionHandle.handle + && (self.dec_session.is_none() + || enc.sess_in.sessionHandle.handle + != self + .dec_session + .as_ref() + .unwrap() + .sess_in + .sessionHandle + .handle) + { + self.nonce_tpm_enc = enc.sess_out.nonce.clone(); + } + } + } + } + } + } + + /// Process parameter encryption/decryption + fn do_param_encryption( + &self, + cmd: &T, + param_buf: &mut TpmBuffer, + start_pos: usize, + is_request: bool, + ) -> Result<(), TpmError> { + let xcrypt_sess = if is_request { + if self.dec_session.is_none() { + return Ok(()); + } + self.dec_session.as_ref() + } else { + if self.enc_session.is_none() { + return Ok(()); + } + self.enc_session.as_ref() + }; + + let sess = xcrypt_sess.unwrap(); + let sei = cmd.sess_enc_info(); + if sei.size_len == 0 || sei.val_len == 0 { + return Ok(()); + } + + let orig_cur_pos = param_buf.current_pos(); + param_buf.set_current_pos(start_pos); + + // Read the size of the first parameter (TPM2B prefix) + let arr_size = param_buf.read_num(sei.size_len as usize) as usize; + let arr_pos = param_buf.current_pos(); + + if arr_size == 0 { + param_buf.set_current_pos(orig_cur_pos); + return Ok(()); + } + + // Read the data to encrypt/decrypt + let to_xcrypt = param_buf.readByteBuf(arr_size * sei.val_len as usize); + + // Perform encryption/decryption + let result = sess.param_xcrypt(&to_xcrypt, is_request)?; + + // Write the result back into the buffer + param_buf.set_current_pos(arr_pos); + param_buf.writeByteBuf(&result); + + param_buf.set_current_pos(orig_cur_pos); + + Ok(()) + } + + /// Get RP hash (response parameter hash) + fn get_rp_hash( + &self, + hash_alg: TPM_ALG_ID, + resp_buf: &mut TpmBuffer, + cmd_code: TPM_CC, + resp_params_pos: usize, + resp_params_size: usize, + rp_ready: bool, + ) -> Result, TpmError> { + let rp_header_size = 8; + let rp_hash_data_pos = resp_params_pos - rp_header_size; + + if !rp_ready { + // Create a continuous data area required by rpHash + let orig_cur_pos = resp_buf.current_pos(); + resp_buf.set_current_pos(rp_hash_data_pos); + resp_buf.writeInt(TPM_RC::SUCCESS.get_value()); + resp_buf.writeInt(cmd_code.get_value()); + resp_buf.set_current_pos(orig_cur_pos); + } + + let data_to_hash = &resp_buf.buffer() + [rp_hash_data_pos..(rp_hash_data_pos + rp_header_size + resp_params_size)]; + Crypto::hash(hash_alg, data_to_hash) + } + + /// Process response sessions + fn process_resp_sessions( + &mut self, + resp_buf: &mut TpmBuffer, + cmd_code: TPM_CC, + resp_params_pos: usize, + resp_params_size: usize, + ) -> Result { + let mut rp_ready = false; + resp_buf.set_current_pos(resp_params_pos + resp_params_size); + + // Pre-compute values needed for HMAC verification to avoid borrow conflicts + let nonce_tpm_dec = self.nonce_tpm_dec.clone(); + let nonce_tpm_enc = self.nonce_tpm_enc.clone(); + let in_handles = self.in_handles.clone(); + + if let Some(ref mut sessions) = self.sessions { + for (j, session) in sessions.iter_mut().enumerate() { + let mut auth_response = TPMS_AUTH_RESPONSE::default(); + auth_response.initFromTpm(resp_buf)?; + + if session.is_pwap() { + // PWAP sessions should have empty nonce and hmac + if !auth_response.nonce.is_empty() || !auth_response.hmac.is_empty() { + return Err(TpmError::GenericError( + "Bad value in PWAP session response".to_string(), + )); + } + continue; + } + + // Non-PWAP session handling + let associated_handle = if j < in_handles.len() { + Some(&in_handles[j]) + } else { + None + }; + + // Update session data based on what the TPM just told us + session.sess_out.nonce = auth_response.nonce; + session.sess_out.sessionAttributes = auth_response.sessionAttributes; + // Update command attributes for next use + session.sess_in.sessionAttributes = auth_response.sessionAttributes; + + if session.session_type == TPM_SE::HMAC + || (session.session_type == TPM_SE::POLICY && session.needs_hmac) + { + // Compute rpHash inline to avoid borrow conflict with self + let rp_hash = { + let rp_header_size = 8; + let rp_hash_data_pos = resp_params_pos - rp_header_size; + + if !rp_ready { + let orig_cur_pos = resp_buf.current_pos(); + resp_buf.set_current_pos(rp_hash_data_pos); + resp_buf.writeInt(TPM_RC::SUCCESS.get_value()); + resp_buf.writeInt(cmd_code.get_value()); + resp_buf.set_current_pos(orig_cur_pos); + } + + let data_to_hash = &resp_buf.buffer() + [rp_hash_data_pos..(rp_hash_data_pos + rp_header_size + resp_params_size)]; + Crypto::hash(session.get_hash_alg(), data_to_hash)? + }; + rp_ready = true; + + let expected_hmac = session.get_auth_hmac( + rp_hash, + false, + &nonce_tpm_dec, + &nonce_tpm_enc, + associated_handle, + )?; + + if expected_hmac != auth_response.hmac { + return Err(TpmError::GenericError( + format!("Invalid TPM response HMAC (session {})", j), + )); + } + } + } + } + + if resp_buf.size() - resp_buf.current_pos() != 0 { + return Err(TpmError::GenericError( + "Invalid response buffer: Data beyond the authorization area".to_string(), + )); + } + + Ok(rp_ready) + } + + /// Update request handles based on command + fn update_request_handles( + &mut self, + cmd_code: TPM_CC, + ) -> Result<(), TpmError> { + // Reset state + self.object_in_name.clear(); + + // This function handles updates to handles based on specific commands + match cmd_code { + TPM_CC::HierarchyChangeAuth => { + // Extract newAuth from the serialized parameters (TPM2B: 2-byte size + data) + if self.last_cmd_params.len() >= 2 { + let size = u16::from_be_bytes([self.last_cmd_params[0], self.last_cmd_params[1]]) as usize; + if self.last_cmd_params.len() >= 2 + size { + self.object_in_auth = self.last_cmd_params[2..2 + size].to_vec(); + } + } + Ok(()) + } + TPM_CC::LoadExternal => { + // Store the name for later use + // In a real implementation, calculate the name from the public area + self.object_in_name = vec![]; // Calculate from req + Ok(()) + } + TPM_CC::Load => { + // Store the name for later use + // In a real implementation, calculate the name from the public area + self.object_in_name = vec![]; // Calculate from req + Ok(()) + } + TPM_CC::NV_ChangeAuth => { + // Extract newAuth from the serialized parameters (TPM2B: 2-byte size + data) + if self.last_cmd_params.len() >= 2 { + let size = u16::from_be_bytes([self.last_cmd_params[0], self.last_cmd_params[1]]) as usize; + if self.last_cmd_params.len() >= 2 + size { + self.object_in_auth = self.last_cmd_params[2..2 + size].to_vec(); + } + } + Ok(()) + } + TPM_CC::ObjectChangeAuth => { + // Extract newAuth from the serialized parameters (TPM2B: 2-byte size + data) + if self.last_cmd_params.len() >= 2 { + let size = u16::from_be_bytes([self.last_cmd_params[0], self.last_cmd_params[1]]) as usize; + if self.last_cmd_params.len() >= 2 + size { + self.object_in_auth = self.last_cmd_params[2..2 + size].to_vec(); + } + } + Ok(()) + } + TPM_CC::PCR_SetAuthValue => { + // Store auth value for later use + // In a real implementation, extract the new auth value from the request + self.object_in_auth = vec![]; // Extract from req + Ok(()) + } + TPM_CC::EvictControl => { + // Store name and auth value for later use + if (!self.in_handles.is_empty() + && self.in_handles[1].get_type() != TPM_HT::PERSISTENT) + { + let handle = &self.in_handles[1]; + self.object_in_auth = handle.auth_value.clone(); + self.object_in_name = handle.get_name()?; + } + Ok(()) + } + TPM_CC::Clear => { + // Reset admin auth values + if !self.in_handles.is_empty() { + let mut handle = self.in_handles[0].clone(); + handle.set_auth(&[]); + } + Ok(()) + } + TPM_CC::HashSequenceStart => { + // Extract auth from the serialized parameters (TPM2B: 2-byte size + data) + if self.last_cmd_params.len() >= 2 { + let size = u16::from_be_bytes([self.last_cmd_params[0], self.last_cmd_params[1]]) as usize; + if self.last_cmd_params.len() >= 2 + size { + self.object_in_auth = self.last_cmd_params[2..2 + size].to_vec(); + } + } + Ok(()) + } + _ => Ok(()), + } + } + + /// Complete update of request handles after command success + fn complete_update_request_handles(&mut self, cmd_code: TPM_CC) -> Result<(), TpmError> { + match cmd_code { + TPM_CC::HierarchyChangeAuth => { + // Update the appropriate hierarchy auth value + if !self.in_handles.is_empty() { + match self.in_handles[0].handle { + val if val == TPM_RH::OWNER.get_value() => { + self.admin_owner.set_auth(&self.object_in_auth) + } + val if val == TPM_RH::ENDORSEMENT.get_value() => { + self.admin_endorsement.set_auth(&self.object_in_auth) + } + val if val == TPM_RH::PLATFORM.get_value() => { + self.admin_platform.set_auth(&self.object_in_auth) + } + val if val == TPM_RH::LOCKOUT.get_value() => { + self.admin_lockout.set_auth(&self.object_in_auth) + } + _ => {} + } + + // Update handle auth + self.in_handles[0].set_auth(&self.object_in_auth); + } + Ok(()) + } + TPM_CC::NV_ChangeAuth => { + if !self.in_handles.is_empty() { + self.in_handles[0].set_auth(&self.object_in_auth); + } + Ok(()) + } + TPM_CC::PCR_SetAuthValue => { + if !self.in_handles.is_empty() { + self.in_handles[0].set_auth(&self.object_in_auth); + } + Ok(()) + } + TPM_CC::EvictControl => { + // Update handle auth and name + if self.in_handles.len() >= 2 && self.in_handles[1].get_type() != TPM_HT::PERSISTENT + { + self.in_handles[1].set_auth(&self.object_in_auth); + let _ = self.in_handles[1].set_name(&self.object_in_name.clone()); + } + Ok(()) + } + TPM_CC::Clear => { + // Reset all hierarchy auth values + self.admin_lockout.set_auth(&[]); + self.admin_owner.set_auth(&[]); + self.admin_endorsement.set_auth(&[]); + Ok(()) + } + _ => Ok(()), + } + } + + /// Update response handle with name and auth value + fn update_resp_handle( + &mut self, + cmd_code: TPM_CC, + resp: &mut T, + ) -> Result<(), TpmError> { + match cmd_code { + TPM_CC::Load | TPM_CC::CreatePrimary | TPM_CC::LoadExternal | TPM_CC::CreateLoaded => { + let name = resp.get_resp_name(); + if !name.is_empty() { + let mut handle = resp.get_handle(); + handle.set_name(&name)?; + resp.set_handle(&handle); + } + Ok(()) + } + TPM_CC::HashSequenceStart | TPM_CC::HMAC_Start => { + Ok(()) + } + _ => Ok(()), + } + } +} + +/// Factory function to create a new TPM implementation based on the available platform +pub fn create_tpm() -> Tpm2 { + #[cfg(target_os = "windows")] + { + use crate::device::TpmTbsDevice; + Tpm2::new(Box::new(TpmTbsDevice::new())) + } + #[cfg(not(target_os = "windows"))] + { + use crate::device::{TpmTbsDevice, TpmTcpDevice}; + + // Try to create a TBS device first (for Linux/Unix), falling back to TCP simulator + let mut tbs_device = TpmTbsDevice::new(); + match tbs_device.connect() { + Ok(_) => Tpm2::new(tbs_device), + Err(_) => { + // Fall back to TCP simulator + let tcp_device = TpmTcpDevice::new("127.0.0.1".to_string(), 2321); + Tpm2::new(Box::new(tcp_device)) + } + } + } +} + +/// Factory function to create a TPM implementation with a custom device +pub fn create_tpm_with_device(device: Box) -> Tpm2 { + Tpm2::new(device) +} diff --git a/TSS.Rust/src/tpm_buffer.rs b/TSS.Rust/src/tpm_buffer.rs new file mode 100644 index 00000000..31b1b7eb --- /dev/null +++ b/TSS.Rust/src/tpm_buffer.rs @@ -0,0 +1,373 @@ +// Since all of the functions here are called from auto-generated code that expects a specific names, +// we have to use those names and not the Rust convention of snake_case +#![allow(non_snake_case)] + +use crate::error::TpmError; +use crate::tpm_structure::TpmEnum; + +pub struct SizedStructInfo { + pub start_pos: usize, + pub size: usize, +} + +pub trait TpmMarshaller { + /** Convert this object to its TPM representation and store it in the given marshaling buffer */ + fn toTpm(&self, buf: &mut TpmBuffer) -> Result<(), TpmError>; + + /** Populate this object from the TPM representation in the given marshaling buffer */ + fn initFromTpm(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError>; +} + +pub struct TpmBuffer { + buf: Vec, + pos: usize, + out_of_bounds: bool, + sized_struct_sizes: Vec, +} + +impl TpmBuffer { + /** Constructs output (default) or input marshaling buffer depending on the parameter. */ + pub fn new(capacity_or_src_buf: Option<&TpmBuffer>) -> Self { + match capacity_or_src_buf { + Some(src_buf) => TpmBuffer { + buf: src_buf.buf.clone(), + pos: src_buf.pos, + out_of_bounds: false, + sized_struct_sizes: Vec::new(), + }, + None => TpmBuffer { + buf: Vec::with_capacity(4096), + pos: 0, + out_of_bounds: false, + sized_struct_sizes: Vec::new(), + }, + } + } + + pub fn from(src_buf: &[u8]) -> Self { + TpmBuffer { + buf: src_buf.to_vec(), + pos: 0, + out_of_bounds: false, + sized_struct_sizes: Vec::new(), + } + } + + /** @return Reference to the backing byte buffer */ + pub fn buffer(&self) -> &Vec { + &self.buf + } + + /** @return Size of the backing byte buffer. */ + pub fn size(&self) -> usize { + self.buf.len() + } + + /** @return Current read/write position in the backing byte buffer. */ + pub fn current_pos(&self) -> usize { + self.pos + } + + /** Sets the current read/write position in the backing byte buffer. */ + pub fn set_current_pos(&mut self, new_pos: usize) { + self.pos = new_pos; + self.out_of_bounds = self.size() < new_pos; + } + + /** @return True unless a previous read/write operation caused under/overflow correspondingly. */ + pub fn isOk(&self) -> bool { + !self.out_of_bounds + } + + /** Shrinks the backing byte buffer so that it ends at the current position */ + pub fn trim(&mut self) -> &Vec { + self.buf.truncate(self.pos); + &self.buf + } + + pub fn getCurStuctRemainingSize(&self) -> usize { + if let Some(ssi) = self.sized_struct_sizes.last() { + return ssi.size - (self.pos - ssi.start_pos); + } + 0 + } + + fn check_len(&mut self, len: usize) -> bool { + if self.buf.len() < self.pos + len { + // Grow the buffer if needed on write operations + self.buf.resize(self.pos + len, 0); + } + true + } + + pub fn write_num(&mut self, val: u64, len: usize) { + if !self.check_len(len) { + return; + } + + if len == 8 { + self.buf[self.pos] = ((val >> 56) & 0xFF) as u8; + self.pos += 1; + self.buf[self.pos] = ((val >> 48) & 0xFF) as u8; + self.pos += 1; + self.buf[self.pos] = ((val >> 40) & 0xFF) as u8; + self.pos += 1; + self.buf[self.pos] = ((val >> 32) & 0xFF) as u8; + self.pos += 1; + } + if len >= 4 { + self.buf[self.pos] = ((val >> 24) & 0xFF) as u8; + self.pos += 1; + self.buf[self.pos] = ((val >> 16) & 0xFF) as u8; + self.pos += 1; + } + if len >= 2 { + self.buf[self.pos] = ((val >> 8) & 0xFF) as u8; + self.pos += 1; + } + self.buf[self.pos] = (val & 0xFF) as u8; + self.pos += 1; + } + + pub fn read_num(&mut self, len: usize) -> u64 { + if !self.check_len(len) { + return 0; + } + + let mut res: u64 = 0; + if len == 8 { + res += (self.buf[self.pos] as u64) << 56; + self.pos += 1; + res += (self.buf[self.pos] as u64) << 48; + self.pos += 1; + res += (self.buf[self.pos] as u64) << 40; + self.pos += 1; + res += (self.buf[self.pos] as u64) << 32; + self.pos += 1; + } + if len >= 4 { + res += (self.buf[self.pos] as u64) << 24; + self.pos += 1; + res += (self.buf[self.pos] as u64) << 16; + self.pos += 1; + } + if len >= 2 { + res += (self.buf[self.pos] as u64) << 8; + self.pos += 1; + } + res += (self.buf[self.pos] as u8) as u64; + self.pos += 1; + res + } + + pub fn write_num_at_pos(&mut self, val: u64, pos: usize, len: usize) { + let cur_pos = self.pos; + self.pos = pos; + self.write_num(val, len); + self.pos = cur_pos; + } + + /** Writes the given 8-bit integer to this buffer */ + pub fn writeByte(&mut self, val: u8) { + if self.check_len(1) { + self.buf[self.pos] = val; + self.pos += 1; + } + } + + /** Marshals the given 16-bit integer to this buffer. */ + pub fn writeShort(&mut self, val: u16) { + self.write_num(val as u64, 2); + } + + /** Marshals the given 32-bit integer to this buffer. */ + pub fn writeInt(&mut self, val: u32) { + self.write_num(val as u64, 4); + } + + /** Marshals the given 64-bit integer to this buffer. */ + pub fn writeInt64(&mut self, val: u64) { + self.write_num(val, 8); + } + + /** Reads a byte from this buffer. */ + pub fn readByte(&mut self) -> u8 { + if self.check_len(1) { + let val = self.buf[self.pos]; + self.pos += 1; + return val; + } + 0 + } + + /** Unmarshals a 16-bit integer from this buffer. */ + pub fn readShort(&mut self) -> u16 { + self.read_num(2) as u16 + } + + /** Unmarshals a 32-bit integer from this buffer. */ + pub fn readInt(&mut self) -> u32 { + self.read_num(4) as u32 + } + + /** Unmarshals a 64-bit integer from this buffer. */ + pub fn readInt64(&mut self) -> u64 { + self.read_num(8) + } + + /** Marshalls the given byte buffer with no length prefix. */ + pub fn writeByteBuf(&mut self, data: &Vec) { + let data_size = data.len(); + if data_size == 0 || !self.check_len(data_size) { + return; + } + for i in 0..data_size { + self.buf[self.pos + i] = data[i]; + } + self.pos += data_size; + } + + /** Unmarshalls a byte buffer of the given size (no marshaled length prefix). */ + pub fn readByteBuf(&mut self, size: usize) -> Vec { + if !self.check_len(size) { + return Vec::new().into(); + } + let mut new_buf = Vec::with_capacity(size); + for i in 0..size { + new_buf.push(self.buf[self.pos + i]); + } + self.pos += size; + new_buf + } + + /** Marshalls the given byte buffer with a length prefix. */ + pub fn writeSizedByteBuf(&mut self, data: &Vec, size_len: usize) { + self.write_num(data.len() as u64, size_len); + self.writeByteBuf(data); + } + + /** Unmarshals a byte buffer from its size-prefixed representation in the TPM wire format. */ + pub fn readSizedByteBuf(&mut self, size_len: usize) -> Vec { + let size = self.read_num(size_len) as usize; + self.readByteBuf(size) + } + + pub fn createObj(&mut self) -> Result { + let mut new_obj = T::default(); + new_obj.initFromTpm(self)?; + Ok(new_obj) + } + + pub fn writeSizedObj(&mut self, obj: &T) -> Result<(), TpmError> { + const LEN_SIZE: usize = 2; // Length of the object size is always 2 bytes + if !self.check_len(LEN_SIZE) { + return Ok(()); + } + + // Remember position to marshal the size of the data structure + let size_pos = self.pos; + // Account for the reserved size area + self.pos += LEN_SIZE; + // Marshal the object + obj.toTpm(self)?; + // Calc marshaled object len + let obj_size = self.pos - (size_pos + LEN_SIZE); + // Marshal it in the appropriate position + self.pos = size_pos; + self.writeShort(obj_size as u16); + self.pos += obj_size; + + Ok(()) + } + + pub fn readSizedObj( + &mut self, + obj: &mut T, + ) -> Result<(), TpmError> { + let size = self.readShort(); + if size == 0 { + return Ok(()); + } + + self.sized_struct_sizes.push(SizedStructInfo { + start_pos: self.pos, + size: size as usize, + }); + + obj.initFromTpm(self)?; + + self.sized_struct_sizes.pop(); + Ok(()) + } + + pub fn writeObjArr(&mut self, arr: &[T]) -> Result<(), TpmError> { + self.writeInt(arr.len() as u32); + for elt in arr { + if !self.isOk() { + break; + } + elt.toTpm(self)?; + } + + Ok(()) + } + + pub fn readObjArr( + &mut self, + arr: &mut Vec, + ) -> Result<(), TpmError> { + let len = self.readInt(); + if len == 0 { + return Ok(arr.clear()); + } + + arr.resize_with(len as usize, T::default); + for elt in arr { + if !self.isOk() { + break; + } + elt.initFromTpm(self)?; + } + + Ok(()) + } + + pub fn writeValArr(&mut self, arr: &[T], val_size: usize) + where + T: TpmEnum + Default, + U: Into, + { + // Length of the array size is always 4 bytes + self.writeInt(arr.len() as u32); + for val in arr { + if !self.isOk() { + break; + } + self.write_num(val.get_value().into(), val_size); + } + } + + pub fn readValArr(&mut self, arr: &mut Vec, val_size: usize) -> Result<(), TpmError> + where + T: TpmEnum + Default, + U: Into, + { + // Length of the array size is always 4 bytes + let len = self.readInt(); + if len == 0 { + return Ok(arr.clear()); + } + + arr.resize_with(len as usize, Default::default); + + for elt in arr { + if !self.isOk() { + break; + } + + *elt = T::new_from_trait((self.read_num(val_size) as u32).into())?; + } + + Ok(()) + } +} diff --git a/TSS.Rust/src/tpm_extensions.rs.snips b/TSS.Rust/src/tpm_extensions.rs.snips new file mode 100644 index 00000000..30868a49 --- /dev/null +++ b/TSS.Rust/src/tpm_extensions.rs.snips @@ -0,0 +1,13 @@ +/* + This file contains source-code snippets that the code-generator inserts into the + appropriate Rust type implementation file. Note - only fields are added to the + relevant structs. Extension methods implementations may be found in tpm_type_extensions.rs +*/ + +>> TPM_HANDLE + +/// The authorization value associated with this handle +pub auth_value: Vec, + +/// The name associated with this handle +pub name: Vec, diff --git a/TSS.Rust/src/tpm_structure.rs b/TSS.Rust/src/tpm_structure.rs new file mode 100644 index 00000000..1d23d8f6 --- /dev/null +++ b/TSS.Rust/src/tpm_structure.rs @@ -0,0 +1,109 @@ +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See the LICENSE file in the project root for full license information. + */ + +#![allow(unused_variables)] + +//! TPM type definitions + +use crate::error::*; +use crate::tpm_buffer::*; +use crate::tpm_types::*; + +/// Trait for structures that can be marshaled to/from TPM wire format +pub trait TpmStructure: TpmMarshaller { + fn serialize(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError>; + fn deserialize(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError>; + #[allow(non_snake_case)] + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError>; + #[allow(non_snake_case)] + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError>; +} + +/// Common trait for all TPM enumeration types +pub trait TpmEnum { + /// Get the numeric value of the enum + fn get_value(&self) -> T; + /// Create enum from a numeric value + fn try_from_trait(value: u64) -> Result + where + Self: Sized; + fn new_from_trait(value: u64) -> Result + where + Self: Sized; +} + +/// Trait for TPM union types +pub trait TpmUnion: TpmStructure {} + +/// Parameters of the TPM command request data structure field, to which session +/// based encryption can be applied (i.e. the first non-handle field marshaled in size-prefixed +/// form, if any) +pub struct SessEncInfo { + /// Length of the size prefix in bytes. The size prefix contains the number of + /// elements in the sized area filed (normally just bytes). + pub size_len: u16, + + /// Length of an element of the sized area in bytes (in most cases 1) + pub val_len: u16, +} + +/// Base class for custom (not TPM 2.0 spec defined) auto-generated classes +/// representing a TPM command or response parameters and handles, if any. +/// +/// These data structures differ from the spec-defined ones derived directly from +/// the TpmStructure class in that their handle fields are not marshaled by their toTpm() and +/// initFrom() methods, but rather are acceesed and manipulated via an interface defined by +/// this structs and its derivatives ReqStructure and RespStructure. +pub trait CmdStructure: TpmStructure { + /// Number of TPM handles contained (as fields) in this data structure + fn num_handles(&self) -> u16 { + 0 + } + + /// Non-zero size info of the encryptable command/response parameter if session + /// based encryption can be applied to this object (i.e. its first non-handle field is + /// marshaled in size-prefixed form). Otherwise returns zero initialized struct. + fn sess_enc_info(&self) -> SessEncInfo { + SessEncInfo { + size_len: 0, + val_len: 0, + } + } +} + +/// Base class for custom (not TPM 2.0 spec defined) auto-generated data structures +/// representing a TPM command parameters and handles, if any. +pub trait ReqStructure: CmdStructure { + /// A vector of TPM handles contained in this request data structure + fn get_handles(&self) -> Vec; + + /// Number of authorization TPM handles contained in this data structure + fn num_auth_handles(&self) -> u16 { + 0 + } + + /// Serializable method + fn type_name(&self) -> String { + "ReqStructure".to_string() + } +} + +/// Base class for custom (not TPM 2.0 spec defined) auto-generated data structures +/// representing a TPM response parameters and handles, if any. +pub trait RespStructure: CmdStructure { + /// this structure's handle field value + fn get_handle(&self) -> TPM_HANDLE; + + /// Sets this structure's handle field (TPM_HANDLE) if it is present + fn set_handle(&mut self, _handle: &TPM_HANDLE) {} + + /// Returns the name field from the response, if present + fn get_resp_name(&self) -> Vec { Vec::new() } + + /// Serializable method + fn type_name(&self) -> String { + "RespStructure".to_string() + } +} diff --git a/TSS.Rust/src/tpm_type_extensions.rs b/TSS.Rust/src/tpm_type_extensions.rs new file mode 100644 index 00000000..ed444e5e --- /dev/null +++ b/TSS.Rust/src/tpm_type_extensions.rs @@ -0,0 +1,450 @@ +use crate::crypto::Crypto; +use crate::error::TpmError; +use crate::tpm2_helpers::int_to_tpm; +use crate::tpm_buffer::*; +use crate::tpm_structure::TpmEnum; +use crate::tpm_types::CertifyResponse; +use crate::tpm_types::*; +use rsa::{BigUint, RsaPublicKey, RsaPrivateKey, Oaep, Pkcs1v15Sign}; +use rsa::traits::{PublicKeyParts, PrivateKeyParts}; +use rand::rngs::OsRng; +use zeroize::Zeroize; + +/// Activation data returned from create_activation +#[derive(Debug)] +pub struct ActivationData { + pub credential_blob: TPMS_ID_OBJECT, + pub secret: Vec, // Encrypted seed (ENCRYPTED_SECRET) +} + +impl TPMT_PUBLIC { + pub fn get_name(&self) -> Result, TpmError> { + let mut buffer = TpmBuffer::new(None); + self.toTpm(&mut buffer)?; + + let mut pub_hash = Crypto::hash(self.nameAlg, buffer.trim())?; + let hash_alg = int_to_tpm(self.nameAlg.get_value()); + + pub_hash.splice(0..0, hash_alg.iter().cloned()); + + Ok(pub_hash) + } + + pub fn get_signing_hash_alg(&self) -> Result { + let rsa_params = if let Some(TPMU_PUBLIC_PARMS::rsaDetail(rsa_params)) = &self.parameters { + rsa_params + } else { + return Err(TpmError::NotSupported( + "Get signing hash algorithm is only supported for RSA".to_string(), + )); + }; + + let scheme = if let Some(TPMU_ASYM_SCHEME::rsassa(scheme)) = &rsa_params.scheme { + scheme + } else { + return Err(TpmError::NotSupported( + "Get signing hash algorithm is only supported for RSA-SSA".to_string(), + )); + }; + + Ok(scheme.hashAlg) + } + + pub fn validate_certify( + &self, + certified_key: &TPMT_PUBLIC, + nonce: &[u8], + certify_response: &CertifyResponse, + ) -> Result { + let hash_alg = self.get_signing_hash_alg()?; + let attest = &certify_response.certifyInfo; + + if (attest.extraData != nonce) { + return Ok(false); + } + + if (attest.magic != TPM_GENERATED::VALUE) { + return Ok(false); + } + + if let Some(TPMU_ATTEST::certify(quote_info)) = &attest.attested { + if (quote_info.name != certified_key.get_name()?) { + return Ok(false); + } + } else { + return Ok(false); + } + + // And finally, check the signature + let signed_blob = { + let mut buffer = TpmBuffer::new(None); + certify_response.certifyInfo.toTpm(&mut buffer)?; + buffer.trim().to_vec() + }; + + let signed_blob_hash = Crypto::hash(hash_alg, &signed_blob)?; + + Crypto::validate_signature(self, signed_blob_hash, &certify_response.signature) + } + + /// Implements the TPM2_MakeCredential command functionality: + /// 1. Generate random seed + /// 2. RSA-OAEP encrypt seed with label "IDENTITY" + /// 3. Derive symmetric key via KDFa + /// 4. Encrypt credential + create integrity HMAC + pub fn create_activation( + &self, + credential: &[u8], + activated_name: &[u8], + ) -> Result { + // Verify we have an RSA key with correct parameters + let rsa_params = if let Some(TPMU_PUBLIC_PARMS::rsaDetail(params)) = &self.parameters { + params + } else { + return Err(TpmError::NotSupported("Only RSA activation supported".to_string())); + }; + + // Check symmetric definition + let sym_def = &rsa_params.symmetric; + if sym_def.algorithm != TPM_ALG_ID::AES + || sym_def.keyBits != 128 + || sym_def.mode != TPM_ALG_ID::CFB { + return Err(TpmError::NotSupported("Unsupported wrapping scheme".to_string())); + } + + // Generate random 16-byte seed + let mut seed = Crypto::get_random(16); + + // Get RSA public key components for encrypting the seed + let rsa_pub_n = if let Some(TPMU_PUBLIC_ID::rsa(unique)) = &self.unique { + &unique.buffer + } else { + return Err(TpmError::NotSupported("Invalid RSA public key".to_string())); + }; + + let rsa_public_key = RsaPublicKey::new( + BigUint::from_bytes_be(rsa_pub_n), + BigUint::from_bytes_be(&[1, 0, 1]) // e = 65537 + ).map_err(|_| TpmError::GenericError("Invalid RSA parameters".to_string()))?; + + // Encrypt seed with label "IDENTITY" using OAEP-SHA1 + let padding = Oaep::new_with_label::("IDENTITY\0"); + let secret = rsa_public_key + .encrypt(&mut OsRng, padding, &seed) + .map_err(|_| TpmError::GenericError("Failed to encrypt seed".to_string()))?; + + // Make the credential blob: + + // 1. Create the symmetric key via KDFa + let mut sym_key = Crypto::kdfa( + self.nameAlg, + &seed, + "STORAGE", + activated_name, + &[], + 128, // 128-bit AES key + )?; + + // 2. Take credential and prepend size + let mut credential_with_size = Vec::with_capacity(2 + credential.len()); + credential_with_size.extend_from_slice(&(credential.len() as u16).to_be_bytes()); + credential_with_size.extend_from_slice(credential); + + // 3. Encrypt the credential + let enc_credential = Crypto::cfb_xcrypt( + true, + &sym_key, + &vec![0u8; 16], // Zero IV + &credential_with_size + )?; + + // 4. Generate the integrity HMAC key + let mut hmac_key = Crypto::kdfa( + self.nameAlg, + &seed, + "INTEGRITY", + &[], + &[], + Crypto::digestSize(self.nameAlg) * 8, + )?; + + // 5. Calculate outer HMAC + let mut to_hmac = Vec::new(); + to_hmac.extend_from_slice(&enc_credential); + to_hmac.extend_from_slice(activated_name); + + let integrity_hmac = Crypto::hmac( + self.nameAlg, + &hmac_key, + &to_hmac + )?; + + // Cleanup sensitive data + seed.zeroize(); + hmac_key.zeroize(); + sym_key.zeroize(); + + Ok(ActivationData { + credential_blob: TPMS_ID_OBJECT::new(&integrity_hmac, &enc_credential), + secret, + }) + } + + // Performs RSA encryption of the given data using the public key + pub fn encrypt( + &self, + data: &[u8], + ) -> Result, TpmError> { + // Verify we have an RSA key with correct parameters + let rsa_params = if let Some(TPMU_PUBLIC_PARMS::rsaDetail(params)) = &self.parameters { + params + } else { + return Err(TpmError::NotSupported("Only RSA encryption supported".to_string())); + }; + + // Check symmetric definition + let sym_def = &rsa_params.symmetric; + if sym_def.algorithm != TPM_ALG_ID::AES + || sym_def.keyBits != 128 + || sym_def.mode != TPM_ALG_ID::CFB { + return Err(TpmError::NotSupported("Unsupported wrapping scheme".to_string())); + } + + // Get RSA public key components + let rsa_pub_n = if let Some(TPMU_PUBLIC_ID::rsa(unique)) = &self.unique { + &unique.buffer + } else { + return Err(TpmError::NotSupported("Invalid RSA public key".to_string())); + }; + + // Create RSA public key (usually e = 65537) + let rsa_public_key = RsaPublicKey::new( + BigUint::from_bytes_be(rsa_pub_n), + BigUint::from_bytes_be(&[1, 0, 1]) // e = 65537 + ).map_err(|_| TpmError::InvalidArraySize("Invalid RSA parameters".to_string()))?; + + // Encrypt the data using OAEP padding with SHA-1 hash function + let padding = Oaep::new_with_label::("IDENTITY\0"); + let encrypted_data = rsa_public_key + .encrypt(&mut OsRng, padding, data) + .map_err(|_| TpmError::GenericError("Failed to encrypt data".to_string()))?; + + Ok(encrypted_data) + } + + /// Encrypt a session salt for use with salted auth sessions. + /// Uses RSA-OAEP with the nameAlg hash and label "SECRET\0". + pub fn encrypt_session_salt(&self, salt: &[u8]) -> Result, TpmError> { + let rsa_pub_n = if let Some(TPMU_PUBLIC_ID::rsa(unique)) = &self.unique { + &unique.buffer + } else { + return Err(TpmError::NotSupported("Only RSA keys can encrypt session salt".to_string())); + }; + + let rsa_public_key = RsaPublicKey::new( + BigUint::from_bytes_be(rsa_pub_n), + BigUint::from_bytes_be(&[1, 0, 1]), + ).map_err(|_| TpmError::InvalidArraySize("Invalid RSA parameters".to_string()))?; + + let padding = match self.nameAlg { + TPM_ALG_ID::SHA1 => Oaep::new_with_label::("SECRET\0"), + TPM_ALG_ID::SHA256 => Oaep::new_with_label::("SECRET\0"), + _ => return Err(TpmError::NotSupported(format!("Unsupported nameAlg for session salt: {:?}", self.nameAlg))), + }; + + rsa_public_key + .encrypt(&mut OsRng, padding, salt) + .map_err(|e| TpmError::GenericError(format!("Failed to encrypt session salt: {}", e))) + } +} + +impl TPMS_PCR_SELECTION { + /// Get a PCR-selection array naming exactly one PCR in one bank + pub fn get_selection_array(hash_alg: TPM_ALG_ID, pcr: u32) -> Vec { + vec![TPMS_PCR_SELECTION::new_from_pcr_u32(hash_alg, pcr)] + } + + /// Create a TPMS_PCR_SELECTION naming a single-PCR + pub fn new_from_pcr_u32(hash_alg: TPM_ALG_ID, pcr: u32) -> Self { + let mut size = 3; + + let pcr_bytes = pcr / 8; + if ((pcr_bytes / 8) + 1) > size { + size = pcr_bytes + 1; + } + + let mut pcr_select = vec![0; size as usize]; + pcr_select[pcr_bytes as usize] = 1 << (pcr % 8); + + TPMS_PCR_SELECTION::new(hash_alg, &pcr_select) + } + + /// Create a TPMS_PCR_SELECTION for a set of PCRs in a single bank + pub fn new_from_pcrs_vec(hash_alg: TPM_ALG_ID, pcrs: &[u32]) -> Self { + let mut pcr_max = *pcrs.iter().max().unwrap_or(&0); + + if (pcr_max < 23) { + pcr_max = 23; + } + + let mut pcr_select = vec![0; (pcr_max / 8 + 1) as usize]; + for pcr in pcrs { + pcr_select[*pcr as usize / 8] |= 1 << (*pcr % 8); + } + + TPMS_PCR_SELECTION::new(hash_alg, &pcr_select) + } +} + +impl TPM_HANDLE { + /// Creates a handle for a persistent object + pub fn persistent(handle_offset: u32) -> Self { + Self::new(((TPM_HT::PERSISTENT.get_value() as u32) << 24) + handle_offset) + } + + /// Creates a handle for a PCR + pub fn pcr(pcr_index: u32) -> Self { + Self::new(pcr_index) + } + + /// Creates a handle for an NV slot + pub fn nv(nv_index: u32) -> Self { + Self::new(((TPM_HT::NV_INDEX.get_value() as u32) << 24) + nv_index) + } + + /// Set the authorization value for this TPM_HANDLE. The default auth-value is NULL + pub fn set_auth(&mut self, auth_val: &[u8]) { + self.auth_value = auth_val.to_vec(); + } + + /// Returns this handle's type + pub fn get_type(&self) -> TPM_HT { + // The handle type is the top byte of the handle value + unsafe { std::mem::transmute((self.handle >> 24) as u8) } + } + + pub fn set_name(&mut self, name: &[u8]) -> Result<(), TpmError> { + let handle_type = self.get_type(); + + if (handle_type == TPM_HT::NV_INDEX + || handle_type == TPM_HT::TRANSIENT + || handle_type == TPM_HT::PERSISTENT + || handle_type == TPM_HT::PERSISTENT) + { + self.name = name.to_vec(); + return Ok(()); + } + + if (name != self.get_name()?) { + return Err(TpmError::GenericError(format!("Setting an invalid name of an entity with the name defined by the handle value, handle type: {}", handle_type))); + } + + Ok(()) + } + + /// Get the TPM name of this handle + pub fn get_name(&self) -> Result, TpmError> { + let handle_type = self.get_type(); + + // Per spec: handles of these types have their handle value as their name + if handle_type == TPM_HT::PCR + || handle_type == TPM_HT::HMAC_SESSION + || handle_type == TPM_HT::POLICY_SESSION + || handle_type == TPM_HT::PERMANENT + { + let mut name = Vec::with_capacity(4); + name.extend_from_slice(&self.handle.to_be_bytes()); + return Ok(name); + } + + if handle_type == TPM_HT::NV_INDEX + || handle_type == TPM_HT::TRANSIENT + || handle_type == TPM_HT::PERSISTENT + { + if (self.name.is_empty()) { + return Err(TpmError::GenericError(format!( + "Name is not set for handle, handle type: {}", + handle_type + ))); + } + return Ok(self.name.clone()); + } + + Err(TpmError::GenericError(format!( + "Unknown handle type, handle type: {}", + handle_type + ))) + } + + /// Get a string representation of this handle + pub fn to_string(&self) -> String { + format!("{}:0x{:x}", self.get_type(), self.handle) + } +} + +impl TSS_KEY { + /// Generate an RSA key pair in software. + /// Populates publicPart.unique with the modulus and privatePart with the first prime (p). + pub fn create_key(&mut self) -> Result<(), TpmError> { + let rsa_params = if let Some(TPMU_PUBLIC_PARMS::rsaDetail(ref params)) = self.publicPart.parameters { + params.clone() + } else { + return Err(TpmError::GenericError("Only RSA key creation is supported".to_string())); + }; + + let key_bits = rsa_params.keyBits as usize; + let priv_key = RsaPrivateKey::new(&mut OsRng, key_bits) + .map_err(|e| TpmError::GenericError(format!("RSA key generation failed: {}", e)))?; + + // Store modulus (n) in publicPart.unique + let n_bytes = priv_key.n().to_bytes_be(); + self.publicPart.unique = Some(TPMU_PUBLIC_ID::rsa(TPM2B_PUBLIC_KEY_RSA { buffer: n_bytes })); + + // Store first prime (p) as privatePart + let primes = priv_key.primes(); + self.privatePart = primes[0].to_bytes_be(); + + Ok(()) + } + + /// Sign a digest using the software key (RSASSA-PKCS1-v1_5). + /// `digest` should be the hash of the data to sign. + /// Returns a TPMT_SIGNATURE with RSASSA scheme. + pub fn sign(&self, digest: &[u8], hash_alg: TPM_ALG_ID) -> Result { + if !matches!(&self.publicPart.parameters, Some(TPMU_PUBLIC_PARMS::rsaDetail(_))) { + return Err(TpmError::GenericError("Only RSA signing is supported".to_string())); + } + + let n_bytes = if let Some(TPMU_PUBLIC_ID::rsa(ref pub_key)) = self.publicPart.unique { + pub_key.buffer.clone() + } else { + return Err(TpmError::GenericError("No public key available".to_string())); + }; + + // Reconstruct RSA private key from modulus + prime p + let n = BigUint::from_bytes_be(&n_bytes); + let p = BigUint::from_bytes_be(&self.privatePart); + let q = &n / &p; + let e = BigUint::from(65537u32); + + let priv_key = RsaPrivateKey::from_p_q(p, q, e) + .map_err(|e| TpmError::GenericError(format!("Failed to reconstruct RSA key: {}", e)))?; + + // Sign with PKCS#1 v1.5 + let scheme = match hash_alg { + TPM_ALG_ID::SHA1 => Pkcs1v15Sign::new::(), + TPM_ALG_ID::SHA256 => Pkcs1v15Sign::new::(), + _ => return Err(TpmError::GenericError(format!("Unsupported hash algorithm for signing: {:?}", hash_alg))), + }; + + let sig_bytes = priv_key.sign(scheme, digest) + .map_err(|e| TpmError::GenericError(format!("RSA signing failed: {}", e)))?; + + Ok(TPMT_SIGNATURE { + signature: Some(TPMU_SIGNATURE::rsassa(TPMS_SIGNATURE_RSASSA { + hash: hash_alg, + sig: sig_bytes, + })), + }) + } +} diff --git a/TSS.Rust/src/tpm_types.rs b/TSS.Rust/src/tpm_types.rs new file mode 100644 index 00000000..814df6f7 --- /dev/null +++ b/TSS.Rust/src/tpm_types.rs @@ -0,0 +1,34775 @@ +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See the LICENSE file in the project root for full license information. + */ + +/* + * NOTE: this file is partially auto generated! + * + * All code after the point marked with the '// <>' comment + * is autogenerated from the TPM 2.0 Specification docs. + * + * DO NOT EDIT AUTOGENERATED PART - all manual changes will be lost! + */ + +#![allow( + unused_variables, + non_snake_case, + non_camel_case_types, + non_upper_case_globals, + dead_code +)] + +//! TPM type definitions + +use crate::crypto::Crypto; +use crate::error::*; +use crate::tpm2_helpers::*; +use crate::tpm_buffer::*; +use crate::tpm_structure::*; +use std::collections::HashMap; +use std::fmt; +use std::fmt::Debug; +use derivative::Derivative; + +// <> +// ------------------------------------------------------------------------------------------------ +// DO NOT REMOVE the <> comment! +// DO NOT MODIFY any code below this point - all manual changes will be lost! +// ------------------------------------------------------------------------------------------------ + + +/// Table 2 is the list of algorithms to which the TCG has assigned an algorithm +/// identifier along with its numeric identifier. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)] +pub struct TPM_ALG_ID(pub u16); + +impl TPM_ALG_ID { + /// Should not occur + pub const ERROR: Self = Self(0x0); // Original value: 0x0000 + + /// An object type that contains an RSA key + pub const FIRST: Self = Self(0x1); // Original value: 0x0001 + + /// An object type that contains an RSA key + pub const RSA: Self = Self(0x1); // Original value: 0x0001 + + /// Block cipher with various key sizes (Triple Data Encryption Algorithm, commonly called + /// Triple Data Encryption Standard) + pub const TDES: Self = Self(0x3); // Original value: 0x0003 + + /// Hash algorithm producing a 160-bit digest + pub const SHA: Self = Self(0x4); // Original value: 0x0004 + + /// Redefinition for documentation consistency + pub const SHA1: Self = Self(0x4); // Original value: 0x0004 + + /// Hash Message Authentication Code (HMAC) algorithm + pub const HMAC: Self = Self(0x5); // Original value: 0x0005 + + /// Block cipher with various key sizes + pub const AES: Self = Self(0x6); // Original value: 0x0006 + + /// Hash-based mask-generation function + pub const MGF1: Self = Self(0x7); // Original value: 0x0007 + + /// An object type that may use XOR for encryption or an HMAC for signing and may also + /// refer to a data object that is neither signing nor encrypting + pub const KEYEDHASH: Self = Self(0x8); // Original value: 0x0008 + + /// Hash-based stream cipher + pub const XOR: Self = Self(0xA); // Original value: 0x000A + + /// Hash algorithm producing a 256-bit digest + pub const SHA256: Self = Self(0xB); // Original value: 0x000B + + /// Hash algorithm producing a 384-bit digest + pub const SHA384: Self = Self(0xC); // Original value: 0x000C + + /// Hash algorithm producing a 512-bit digest + pub const SHA512: Self = Self(0xD); // Original value: 0x000D + + /// Indication that no algorithm is selected + pub const NULL: Self = Self(0x10); // Original value: 0x0010 + + /// Hash algorithm producing a 256-bit digest + pub const SM3_256: Self = Self(0x12); // Original value: 0x0012 + + /// Symmetric block cipher with 128 bit key + pub const SM4: Self = Self(0x13); // Original value: 0x0013 + + /// A signature algorithm defined in section 8.2 (RSASSA-PKCS1-v1_5) + pub const RSASSA: Self = Self(0x14); // Original value: 0x0014 + + /// A padding algorithm defined in section 7.2 (RSAES-PKCS1-v1_5) + pub const RSAES: Self = Self(0x15); // Original value: 0x0015 + + /// A signature algorithm defined in section 8.1 (RSASSA-PSS) + pub const RSAPSS: Self = Self(0x16); // Original value: 0x0016 + + /// A padding algorithm defined in Section 7.1 (RSAES_OAEP) + pub const OAEP: Self = Self(0x17); // Original value: 0x0017 + + /// Signature algorithm using elliptic curve cryptography (ECC) + pub const ECDSA: Self = Self(0x18); // Original value: 0x0018 + + /// Secret sharing using ECC Based on context, this can be either One-Pass Diffie-Hellman, + /// C(1, 1, ECC CDH) defined in 6.2.2.2 or Full Unified Model C(2, 2, ECC CDH) defined in 6.1.1.2 + pub const ECDH: Self = Self(0x19); // Original value: 0x0019 + + /// Elliptic-curve based, anonymous signing scheme + pub const ECDAA: Self = Self(0x1A); // Original value: 0x001A + + /// Depending on context, either an elliptic-curve-based signature algorithm, encryption + /// algorithm, or key exchange protocol + pub const SM2: Self = Self(0x1B); // Original value: 0x001B + + /// Elliptic-curve based Schnorr signature + pub const ECSCHNORR: Self = Self(0x1C); // Original value: 0x001C + + /// Two-phase elliptic-curve key exchange C(2, 2, ECC MQV) Section 6.1.1.4 + pub const ECMQV: Self = Self(0x1D); // Original value: 0x001D + + /// Concatenation key derivation function (approved alternative 1) Section 5.8.1 + pub const KDF1_SP800_56A: Self = Self(0x20); // Original value: 0x0020 + + /// Key derivation function KDF2 Section 13.2 + pub const KDF2: Self = Self(0x21); // Original value: 0x0021 + + /// A key derivation method SP800-108, Section 5.1 KDF in Counter Mode + pub const KDF1_SP800_108: Self = Self(0x22); // Original value: 0x0022 + + /// Prime field ECC + pub const ECC: Self = Self(0x23); // Original value: 0x0023 + + /// The object type for a symmetric block cipher key + pub const SYMCIPHER: Self = Self(0x25); // Original value: 0x0025 + + /// Symmetric block cipher with various key sizes + pub const CAMELLIA: Self = Self(0x26); // Original value: 0x0026 + + /// Hash algorithm producing a 256-bit digest + pub const SHA3_256: Self = Self(0x27); // Original value: 0x0027 + + /// Hash algorithm producing a 384-bit digest + pub const SHA3_384: Self = Self(0x28); // Original value: 0x0028 + + /// Hash algorithm producing a 512-bit digest + pub const SHA3_512: Self = Self(0x29); // Original value: 0x0029 + pub const CMAC: Self = Self(0x3F); // Original value: 0x003F + + /// Counter mode if implemented, all symmetric block ciphers (S type) implemented shall be + /// capable of using this mode. + pub const CTR: Self = Self(0x40); // Original value: 0x0040 + + /// Output Feedback mode if implemented, all symmetric block ciphers (S type) implemented + /// shall be capable of using this mode. + pub const OFB: Self = Self(0x41); // Original value: 0x0041 + + /// Cipher Block Chaining mode if implemented, all symmetric block ciphers (S type) + /// implemented shall be capable of using this mode. + pub const CBC: Self = Self(0x42); // Original value: 0x0042 + + /// Cipher Feedback mode if implemented, all symmetric block ciphers (S type) implemented + /// shall be capable of using this mode. + pub const CFB: Self = Self(0x43); // Original value: 0x0043 + + /// Electronic Codebook mode if implemented, all implemented symmetric block ciphers (S + /// type) shall be capable of using this mode. + /// NOTE This mode is not recommended for uses unless the key is frequently rotated such + /// as in video codecs + pub const ECB: Self = Self(0x44); // Original value: 0x0044 + pub const LAST: Self = Self(0x44); // Original value: 0x0044 + + /// Phony alg ID to be used for the first union member with no selector + pub const ANY: Self = Self(0x7FFF); + + /// Phony alg ID to be used for the second union member with no selector + pub const ANY2: Self = Self(0x7FFE); + + pub fn try_from(value: u16) -> Result { + match value { + 0 => Ok(Self::ERROR), // Original value: 0x0000 + 1 => Ok(Self::RSA), // Original value: 0x0001 + 3 => Ok(Self::TDES), // Original value: 0x0003 + 4 => Ok(Self::SHA1), // Original value: 0x0004 + 5 => Ok(Self::HMAC), // Original value: 0x0005 + 6 => Ok(Self::AES), // Original value: 0x0006 + 7 => Ok(Self::MGF1), // Original value: 0x0007 + 8 => Ok(Self::KEYEDHASH), // Original value: 0x0008 + 10 => Ok(Self::XOR), // Original value: 0x000A + 11 => Ok(Self::SHA256), // Original value: 0x000B + 12 => Ok(Self::SHA384), // Original value: 0x000C + 13 => Ok(Self::SHA512), // Original value: 0x000D + 16 => Ok(Self::NULL), // Original value: 0x0010 + 18 => Ok(Self::SM3_256), // Original value: 0x0012 + 19 => Ok(Self::SM4), // Original value: 0x0013 + 20 => Ok(Self::RSASSA), // Original value: 0x0014 + 21 => Ok(Self::RSAES), // Original value: 0x0015 + 22 => Ok(Self::RSAPSS), // Original value: 0x0016 + 23 => Ok(Self::OAEP), // Original value: 0x0017 + 24 => Ok(Self::ECDSA), // Original value: 0x0018 + 25 => Ok(Self::ECDH), // Original value: 0x0019 + 26 => Ok(Self::ECDAA), // Original value: 0x001A + 27 => Ok(Self::SM2), // Original value: 0x001B + 28 => Ok(Self::ECSCHNORR), // Original value: 0x001C + 29 => Ok(Self::ECMQV), // Original value: 0x001D + 32 => Ok(Self::KDF1_SP800_56A), // Original value: 0x0020 + 33 => Ok(Self::KDF2), // Original value: 0x0021 + 34 => Ok(Self::KDF1_SP800_108), // Original value: 0x0022 + 35 => Ok(Self::ECC), // Original value: 0x0023 + 37 => Ok(Self::SYMCIPHER), // Original value: 0x0025 + 38 => Ok(Self::CAMELLIA), // Original value: 0x0026 + 39 => Ok(Self::SHA3_256), // Original value: 0x0027 + 40 => Ok(Self::SHA3_384), // Original value: 0x0028 + 41 => Ok(Self::SHA3_512), // Original value: 0x0029 + 63 => Ok(Self::CMAC), // Original value: 0x003F + 64 => Ok(Self::CTR), // Original value: 0x0040 + 65 => Ok(Self::OFB), // Original value: 0x0041 + 66 => Ok(Self::CBC), // Original value: 0x0042 + 67 => Ok(Self::CFB), // Original value: 0x0043 + 68 => Ok(Self::LAST), // Original value: 0x0044 + 32767 => Ok(Self::ANY), // Original value: 0x7FFF + 32766 => Ok(Self::ANY2), // Original value: 0x7FFE + _ => Err(TpmError::InvalidEnumValue), + } + } +} + +impl TpmEnum for TPM_ALG_ID { + fn get_value(&self) -> u16 { + self.0.into() + } + + fn try_from_trait(value: u64) -> Result where Self: Sized { + TPM_ALG_ID::try_from(value as u16) + } + + fn new_from_trait(value: u64) -> Result where Self: Sized { + Ok(TPM_ALG_ID(value as u16)) + } +} + +impl From for u16 { + fn from(value: TPM_ALG_ID) -> Self { + value.0 as u16 + } +} + +impl From for i16 { + fn from(value: TPM_ALG_ID) -> Self { + value.0 as i16 + } +} + +impl fmt::Display for TPM_ALG_ID { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self.0 { + 0 => write!(f, "ERROR"), + 1 => write!(f, "RSA"), + 3 => write!(f, "TDES"), + 4 => write!(f, "SHA1"), + 5 => write!(f, "HMAC"), + 6 => write!(f, "AES"), + 7 => write!(f, "MGF1"), + 8 => write!(f, "KEYEDHASH"), + 10 => write!(f, "XOR"), + 11 => write!(f, "SHA256"), + 12 => write!(f, "SHA384"), + 13 => write!(f, "SHA512"), + 16 => write!(f, "NULL"), + 18 => write!(f, "SM3_256"), + 19 => write!(f, "SM4"), + 20 => write!(f, "RSASSA"), + 21 => write!(f, "RSAES"), + 22 => write!(f, "RSAPSS"), + 23 => write!(f, "OAEP"), + 24 => write!(f, "ECDSA"), + 25 => write!(f, "ECDH"), + 26 => write!(f, "ECDAA"), + 27 => write!(f, "SM2"), + 28 => write!(f, "ECSCHNORR"), + 29 => write!(f, "ECMQV"), + 32 => write!(f, "KDF1_SP800_56A"), + 33 => write!(f, "KDF2"), + 34 => write!(f, "KDF1_SP800_108"), + 35 => write!(f, "ECC"), + 37 => write!(f, "SYMCIPHER"), + 38 => write!(f, "CAMELLIA"), + 39 => write!(f, "SHA3_256"), + 40 => write!(f, "SHA3_384"), + 41 => write!(f, "SHA3_512"), + 63 => write!(f, "CMAC"), + 64 => write!(f, "CTR"), + 65 => write!(f, "OFB"), + 66 => write!(f, "CBC"), + 67 => write!(f, "CFB"), + 68 => write!(f, "LAST"), + 32767 => write!(f, "ANY"), + 32766 => write!(f, "ANY2"), + _ => write!(f, "{}", enum_to_str(self.0 as u64, std::any::TypeId::of::())), + } + } +} + +/// Table 4 is the list of identifiers for TCG-registered curve ID values for elliptic +/// curve cryptography. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)] +pub struct TPM_ECC_CURVE(pub u16); + +impl TPM_ECC_CURVE { + pub const NONE: Self = Self(0x0); // Original value: 0x0000 + pub const NIST_P192: Self = Self(0x1); // Original value: 0x0001 + pub const NIST_P224: Self = Self(0x2); // Original value: 0x0002 + pub const NIST_P256: Self = Self(0x3); // Original value: 0x0003 + pub const NIST_P384: Self = Self(0x4); // Original value: 0x0004 + pub const NIST_P521: Self = Self(0x5); // Original value: 0x0005 + + /// Curve to support ECDAA + pub const BN_P256: Self = Self(0x10); // Original value: 0x0010 + + /// Curve to support ECDAA + pub const BN_P638: Self = Self(0x11); // Original value: 0x0011 + pub const SM2_P256: Self = Self(0x20); // Original value: 0x0020 + pub const TEST_P192: Self = Self(0x21); // Original value: 0x0021 + + pub fn try_from(value: u16) -> Result { + match value { + 0 => Ok(Self::NONE), // Original value: 0x0000 + 1 => Ok(Self::NIST_P192), // Original value: 0x0001 + 2 => Ok(Self::NIST_P224), // Original value: 0x0002 + 3 => Ok(Self::NIST_P256), // Original value: 0x0003 + 4 => Ok(Self::NIST_P384), // Original value: 0x0004 + 5 => Ok(Self::NIST_P521), // Original value: 0x0005 + 16 => Ok(Self::BN_P256), // Original value: 0x0010 + 17 => Ok(Self::BN_P638), // Original value: 0x0011 + 32 => Ok(Self::SM2_P256), // Original value: 0x0020 + 33 => Ok(Self::TEST_P192), // Original value: 0x0021 + _ => Err(TpmError::InvalidEnumValue), + } + } +} + +impl TpmEnum for TPM_ECC_CURVE { + fn get_value(&self) -> u16 { + self.0.into() + } + + fn try_from_trait(value: u64) -> Result where Self: Sized { + TPM_ECC_CURVE::try_from(value as u16) + } + + fn new_from_trait(value: u64) -> Result where Self: Sized { + Ok(TPM_ECC_CURVE(value as u16)) + } +} + +impl From for u16 { + fn from(value: TPM_ECC_CURVE) -> Self { + value.0 as u16 + } +} + +impl From for i16 { + fn from(value: TPM_ECC_CURVE) -> Self { + value.0 as i16 + } +} + +impl fmt::Display for TPM_ECC_CURVE { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self.0 { + 0 => write!(f, "NONE"), + 1 => write!(f, "NIST_P192"), + 2 => write!(f, "NIST_P224"), + 3 => write!(f, "NIST_P256"), + 4 => write!(f, "NIST_P384"), + 5 => write!(f, "NIST_P521"), + 16 => write!(f, "BN_P256"), + 17 => write!(f, "BN_P638"), + 32 => write!(f, "SM2_P256"), + 33 => write!(f, "TEST_P192"), + _ => write!(f, "{}", enum_to_str(self.0 as u64, std::any::TypeId::of::())), + } + } +} + +/// Table 13 Defines for SHA1 Hash Values +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)] +pub struct SHA1(pub u32); + +impl SHA1 { + /// Size of digest in octets + pub const DIGEST_SIZE: Self = Self(0x14); // Original value: 20 + + /// Size of hash block in octets + pub const BLOCK_SIZE: Self = Self(0x40); // Original value: 64 + + pub fn try_from(value: u32) -> Result { + match value { + 20 => Ok(Self::DIGEST_SIZE), // Original value: 20 + 64 => Ok(Self::BLOCK_SIZE), // Original value: 64 + _ => Err(TpmError::InvalidEnumValue), + } + } +} + +impl TpmEnum for SHA1 { + fn get_value(&self) -> u32 { + self.0.into() + } + + fn try_from_trait(value: u64) -> Result where Self: Sized { + SHA1::try_from(value as u32) + } + + fn new_from_trait(value: u64) -> Result where Self: Sized { + Ok(SHA1(value as u32)) + } +} + +impl From for u32 { + fn from(value: SHA1) -> Self { + value.0 as u32 + } +} + +impl From for i32 { + fn from(value: SHA1) -> Self { + value.0 as i32 + } +} + +impl fmt::Display for SHA1 { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self.0 { + 20 => write!(f, "DIGEST_SIZE"), + 64 => write!(f, "BLOCK_SIZE"), + _ => write!(f, "{}", enum_to_str(self.0 as u64, std::any::TypeId::of::())), + } + } +} + +/// Table 14 Defines for SHA256 Hash Values +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)] +pub struct SHA256(pub u32); + +impl SHA256 { + /// Size of digest + pub const DIGEST_SIZE: Self = Self(0x20); // Original value: 32 + + /// Size of hash block + pub const BLOCK_SIZE: Self = Self(0x40); // Original value: 64 + + pub fn try_from(value: u32) -> Result { + match value { + 32 => Ok(Self::DIGEST_SIZE), // Original value: 32 + 64 => Ok(Self::BLOCK_SIZE), // Original value: 64 + _ => Err(TpmError::InvalidEnumValue), + } + } +} + +impl TpmEnum for SHA256 { + fn get_value(&self) -> u32 { + self.0.into() + } + + fn try_from_trait(value: u64) -> Result where Self: Sized { + SHA256::try_from(value as u32) + } + + fn new_from_trait(value: u64) -> Result where Self: Sized { + Ok(SHA256(value as u32)) + } +} + +impl From for u32 { + fn from(value: SHA256) -> Self { + value.0 as u32 + } +} + +impl From for i32 { + fn from(value: SHA256) -> Self { + value.0 as i32 + } +} + +impl fmt::Display for SHA256 { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self.0 { + 32 => write!(f, "DIGEST_SIZE"), + 64 => write!(f, "BLOCK_SIZE"), + _ => write!(f, "{}", enum_to_str(self.0 as u64, std::any::TypeId::of::())), + } + } +} + +/// Table 15 Defines for SHA384 Hash Values +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)] +pub struct SHA384(pub u32); + +impl SHA384 { + /// Size of digest in octets + pub const DIGEST_SIZE: Self = Self(0x30); // Original value: 48 + + /// Size of hash block in octets + pub const BLOCK_SIZE: Self = Self(0x80); // Original value: 128 + + pub fn try_from(value: u32) -> Result { + match value { + 48 => Ok(Self::DIGEST_SIZE), // Original value: 48 + 128 => Ok(Self::BLOCK_SIZE), // Original value: 128 + _ => Err(TpmError::InvalidEnumValue), + } + } +} + +impl TpmEnum for SHA384 { + fn get_value(&self) -> u32 { + self.0.into() + } + + fn try_from_trait(value: u64) -> Result where Self: Sized { + SHA384::try_from(value as u32) + } + + fn new_from_trait(value: u64) -> Result where Self: Sized { + Ok(SHA384(value as u32)) + } +} + +impl From for u32 { + fn from(value: SHA384) -> Self { + value.0 as u32 + } +} + +impl From for i32 { + fn from(value: SHA384) -> Self { + value.0 as i32 + } +} + +impl fmt::Display for SHA384 { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self.0 { + 48 => write!(f, "DIGEST_SIZE"), + 128 => write!(f, "BLOCK_SIZE"), + _ => write!(f, "{}", enum_to_str(self.0 as u64, std::any::TypeId::of::())), + } + } +} + +/// Table 16 Defines for SHA512 Hash Values +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)] +pub struct SHA512(pub u32); + +impl SHA512 { + /// Size of digest in octets + pub const DIGEST_SIZE: Self = Self(0x40); // Original value: 64 + + /// Size of hash block in octets + pub const BLOCK_SIZE: Self = Self(0x80); // Original value: 128 + + pub fn try_from(value: u32) -> Result { + match value { + 64 => Ok(Self::DIGEST_SIZE), // Original value: 64 + 128 => Ok(Self::BLOCK_SIZE), // Original value: 128 + _ => Err(TpmError::InvalidEnumValue), + } + } +} + +impl TpmEnum for SHA512 { + fn get_value(&self) -> u32 { + self.0.into() + } + + fn try_from_trait(value: u64) -> Result where Self: Sized { + SHA512::try_from(value as u32) + } + + fn new_from_trait(value: u64) -> Result where Self: Sized { + Ok(SHA512(value as u32)) + } +} + +impl From for u32 { + fn from(value: SHA512) -> Self { + value.0 as u32 + } +} + +impl From for i32 { + fn from(value: SHA512) -> Self { + value.0 as i32 + } +} + +impl fmt::Display for SHA512 { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self.0 { + 64 => write!(f, "DIGEST_SIZE"), + 128 => write!(f, "BLOCK_SIZE"), + _ => write!(f, "{}", enum_to_str(self.0 as u64, std::any::TypeId::of::())), + } + } +} + +/// Table 17 Defines for SM3_256 Hash Values +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)] +pub struct SM3_256(pub u32); + +impl SM3_256 { + /// Size of digest in octets + pub const DIGEST_SIZE: Self = Self(0x20); // Original value: 32 + + /// Size of hash block in octets + pub const BLOCK_SIZE: Self = Self(0x40); // Original value: 64 + + pub fn try_from(value: u32) -> Result { + match value { + 32 => Ok(Self::DIGEST_SIZE), // Original value: 32 + 64 => Ok(Self::BLOCK_SIZE), // Original value: 64 + _ => Err(TpmError::InvalidEnumValue), + } + } +} + +impl TpmEnum for SM3_256 { + fn get_value(&self) -> u32 { + self.0.into() + } + + fn try_from_trait(value: u64) -> Result where Self: Sized { + SM3_256::try_from(value as u32) + } + + fn new_from_trait(value: u64) -> Result where Self: Sized { + Ok(SM3_256(value as u32)) + } +} + +impl From for u32 { + fn from(value: SM3_256) -> Self { + value.0 as u32 + } +} + +impl From for i32 { + fn from(value: SM3_256) -> Self { + value.0 as i32 + } +} + +impl fmt::Display for SM3_256 { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self.0 { + 32 => write!(f, "DIGEST_SIZE"), + 64 => write!(f, "BLOCK_SIZE"), + _ => write!(f, "{}", enum_to_str(self.0 as u64, std::any::TypeId::of::())), + } + } +} + +/// Table 18 Defines for SHA3_256 Hash Values +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)] +pub struct SHA3_256(pub u32); + +impl SHA3_256 { + /// Size of digest in octets + pub const DIGEST_SIZE: Self = Self(0x20); // Original value: 32 + + /// Size of hash block in octets + pub const BLOCK_SIZE: Self = Self(0x88); // Original value: 136 + + pub fn try_from(value: u32) -> Result { + match value { + 32 => Ok(Self::DIGEST_SIZE), // Original value: 32 + 136 => Ok(Self::BLOCK_SIZE), // Original value: 136 + _ => Err(TpmError::InvalidEnumValue), + } + } +} + +impl TpmEnum for SHA3_256 { + fn get_value(&self) -> u32 { + self.0.into() + } + + fn try_from_trait(value: u64) -> Result where Self: Sized { + SHA3_256::try_from(value as u32) + } + + fn new_from_trait(value: u64) -> Result where Self: Sized { + Ok(SHA3_256(value as u32)) + } +} + +impl From for u32 { + fn from(value: SHA3_256) -> Self { + value.0 as u32 + } +} + +impl From for i32 { + fn from(value: SHA3_256) -> Self { + value.0 as i32 + } +} + +impl fmt::Display for SHA3_256 { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self.0 { + 32 => write!(f, "DIGEST_SIZE"), + 136 => write!(f, "BLOCK_SIZE"), + _ => write!(f, "{}", enum_to_str(self.0 as u64, std::any::TypeId::of::())), + } + } +} + +/// Table 19 Defines for SHA3_384 Hash Values +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)] +pub struct SHA3_384(pub u32); + +impl SHA3_384 { + /// Size of digest in octets + pub const DIGEST_SIZE: Self = Self(0x30); // Original value: 48 + + /// Size of hash block in octets + pub const BLOCK_SIZE: Self = Self(0x68); // Original value: 104 + + pub fn try_from(value: u32) -> Result { + match value { + 48 => Ok(Self::DIGEST_SIZE), // Original value: 48 + 104 => Ok(Self::BLOCK_SIZE), // Original value: 104 + _ => Err(TpmError::InvalidEnumValue), + } + } +} + +impl TpmEnum for SHA3_384 { + fn get_value(&self) -> u32 { + self.0.into() + } + + fn try_from_trait(value: u64) -> Result where Self: Sized { + SHA3_384::try_from(value as u32) + } + + fn new_from_trait(value: u64) -> Result where Self: Sized { + Ok(SHA3_384(value as u32)) + } +} + +impl From for u32 { + fn from(value: SHA3_384) -> Self { + value.0 as u32 + } +} + +impl From for i32 { + fn from(value: SHA3_384) -> Self { + value.0 as i32 + } +} + +impl fmt::Display for SHA3_384 { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self.0 { + 48 => write!(f, "DIGEST_SIZE"), + 104 => write!(f, "BLOCK_SIZE"), + _ => write!(f, "{}", enum_to_str(self.0 as u64, std::any::TypeId::of::())), + } + } +} + +/// Table 20 Defines for SHA3_512 Hash Values +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)] +pub struct SHA3_512(pub u32); + +impl SHA3_512 { + /// Size of digest in octets + pub const DIGEST_SIZE: Self = Self(0x40); // Original value: 64 + + /// Size of hash block in octets + pub const BLOCK_SIZE: Self = Self(0x48); // Original value: 72 + + pub fn try_from(value: u32) -> Result { + match value { + 64 => Ok(Self::DIGEST_SIZE), // Original value: 64 + 72 => Ok(Self::BLOCK_SIZE), // Original value: 72 + _ => Err(TpmError::InvalidEnumValue), + } + } +} + +impl TpmEnum for SHA3_512 { + fn get_value(&self) -> u32 { + self.0.into() + } + + fn try_from_trait(value: u64) -> Result where Self: Sized { + SHA3_512::try_from(value as u32) + } + + fn new_from_trait(value: u64) -> Result where Self: Sized { + Ok(SHA3_512(value as u32)) + } +} + +impl From for u32 { + fn from(value: SHA3_512) -> Self { + value.0 as u32 + } +} + +impl From for i32 { + fn from(value: SHA3_512) -> Self { + value.0 as i32 + } +} + +impl fmt::Display for SHA3_512 { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self.0 { + 64 => write!(f, "DIGEST_SIZE"), + 72 => write!(f, "BLOCK_SIZE"), + _ => write!(f, "{}", enum_to_str(self.0 as u64, std::any::TypeId::of::())), + } + } +} + +/// Table 4 Defines for Logic Values +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)] +pub struct Logic(pub u8); + +impl Logic { + pub const TRUE: Self = Self(0x1); // Original value: 1 + pub const FALSE: Self = Self(0x0); // Original value: 0 + pub const YES: Self = Self(0x1); // Original value: 1 + pub const NO: Self = Self(0x0); // Original value: 0 + pub const SET: Self = Self(0x1); // Original value: 1 + pub const CLEAR: Self = Self(0x0); // Original value: 0 + + pub fn try_from(value: u8) -> Result { + match value { + 1 => Ok(Self::SET), // Original value: 1 + 0 => Ok(Self::CLEAR), // Original value: 0 + _ => Err(TpmError::InvalidEnumValue), + } + } +} + +impl TpmEnum for Logic { + fn get_value(&self) -> u8 { + self.0.into() + } + + fn try_from_trait(value: u64) -> Result where Self: Sized { + Logic::try_from(value as u8) + } + + fn new_from_trait(value: u64) -> Result where Self: Sized { + Ok(Logic(value as u8)) + } +} + +impl From for u8 { + fn from(value: Logic) -> Self { + value.0 as u8 + } +} + +impl From for i8 { + fn from(value: Logic) -> Self { + value.0 as i8 + } +} + +impl fmt::Display for Logic { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self.0 { + 1 => write!(f, "SET"), + 0 => write!(f, "CLEAR"), + _ => write!(f, "{}", enum_to_str(self.0 as u64, std::any::TypeId::of::())), + } + } +} + +/// These values are readable with TPM2_GetCapability() (see 6.13 for the format). +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)] +pub struct TPM_SPEC(pub u32); + +impl TPM_SPEC { + /// ASCII 2.0 with null terminator + pub const FAMILY: Self = Self(0x322E3000); + + /// The level number for the specification + pub const LEVEL: Self = Self(0x0); // Original value: 0 + + /// The version number of the spec (001.62 * 100) + pub const VERSION: Self = Self(0xA2); // Original value: 162 + + /// The year of the version + pub const YEAR: Self = Self(0x7E3); // Original value: 2019 + + /// The day of the year (December 26) + pub const DAY_OF_YEAR: Self = Self(0x168); // Original value: 360 + + pub fn try_from(value: u32) -> Result { + match value { + 841887744 => Ok(Self::FAMILY), // Original value: 0x322E3000 + 0 => Ok(Self::LEVEL), // Original value: 0 + 162 => Ok(Self::VERSION), // Original value: 162 + 2019 => Ok(Self::YEAR), // Original value: 2019 + 360 => Ok(Self::DAY_OF_YEAR), // Original value: 360 + _ => Err(TpmError::InvalidEnumValue), + } + } +} + +impl TpmEnum for TPM_SPEC { + fn get_value(&self) -> u32 { + self.0.into() + } + + fn try_from_trait(value: u64) -> Result where Self: Sized { + TPM_SPEC::try_from(value as u32) + } + + fn new_from_trait(value: u64) -> Result where Self: Sized { + Ok(TPM_SPEC(value as u32)) + } +} + +impl From for u32 { + fn from(value: TPM_SPEC) -> Self { + value.0 as u32 + } +} + +impl From for i32 { + fn from(value: TPM_SPEC) -> Self { + value.0 as i32 + } +} + +impl fmt::Display for TPM_SPEC { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self.0 { + 841887744 => write!(f, "FAMILY"), + 0 => write!(f, "LEVEL"), + 162 => write!(f, "VERSION"), + 2019 => write!(f, "YEAR"), + 360 => write!(f, "DAY_OF_YEAR"), + _ => write!(f, "{}", enum_to_str(self.0 as u64, std::any::TypeId::of::())), + } + } +} + +/// This constant value differentiates TPM-generated structures from non-TPM structures. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)] +pub struct TPM_GENERATED(pub u32); + +impl TPM_GENERATED { + /// 0xFF TCG (FF 54 43 4716) + pub const VALUE: Self = Self(0xFF544347); // Original value: 0xff544347 + + pub fn try_from(value: u32) -> Result { + match value { + 4283712327 => Ok(Self::VALUE), // Original value: 0xff544347 + _ => Err(TpmError::InvalidEnumValue), + } + } +} + +impl TpmEnum for TPM_GENERATED { + fn get_value(&self) -> u32 { + self.0.into() + } + + fn try_from_trait(value: u64) -> Result where Self: Sized { + TPM_GENERATED::try_from(value as u32) + } + + fn new_from_trait(value: u64) -> Result where Self: Sized { + Ok(TPM_GENERATED(value as u32)) + } +} + +impl From for u32 { + fn from(value: TPM_GENERATED) -> Self { + value.0 as u32 + } +} + +impl From for i32 { + fn from(value: TPM_GENERATED) -> Self { + value.0 as i32 + } +} + +impl fmt::Display for TPM_GENERATED { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self.0 { + 4283712327 => write!(f, "VALUE"), + _ => write!(f, "{}", enum_to_str(self.0 as u64, std::any::TypeId::of::())), + } + } +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)] +pub struct TPM_CC(pub u32); + +impl TPM_CC { + /// Compile variable. May decrease based on implementation. + pub const FIRST: Self = Self(0x11F); // Original value: 0x0000011F + pub const NV_UndefineSpaceSpecial: Self = Self(0x11F); // Original value: 0x0000011F + pub const EvictControl: Self = Self(0x120); // Original value: 0x00000120 + pub const HierarchyControl: Self = Self(0x121); // Original value: 0x00000121 + pub const NV_UndefineSpace: Self = Self(0x122); // Original value: 0x00000122 + pub const ChangeEPS: Self = Self(0x124); // Original value: 0x00000124 + pub const ChangePPS: Self = Self(0x125); // Original value: 0x00000125 + pub const Clear: Self = Self(0x126); // Original value: 0x00000126 + pub const ClearControl: Self = Self(0x127); // Original value: 0x00000127 + pub const ClockSet: Self = Self(0x128); // Original value: 0x00000128 + pub const HierarchyChangeAuth: Self = Self(0x129); // Original value: 0x00000129 + pub const NV_DefineSpace: Self = Self(0x12A); // Original value: 0x0000012A + pub const PCR_Allocate: Self = Self(0x12B); // Original value: 0x0000012B + pub const PCR_SetAuthPolicy: Self = Self(0x12C); // Original value: 0x0000012C + pub const PP_Commands: Self = Self(0x12D); // Original value: 0x0000012D + pub const SetPrimaryPolicy: Self = Self(0x12E); // Original value: 0x0000012E + pub const FieldUpgradeStart: Self = Self(0x12F); // Original value: 0x0000012F + pub const ClockRateAdjust: Self = Self(0x130); // Original value: 0x00000130 + pub const CreatePrimary: Self = Self(0x131); // Original value: 0x00000131 + pub const NV_GlobalWriteLock: Self = Self(0x132); // Original value: 0x00000132 + pub const GetCommandAuditDigest: Self = Self(0x133); // Original value: 0x00000133 + pub const NV_Increment: Self = Self(0x134); // Original value: 0x00000134 + pub const NV_SetBits: Self = Self(0x135); // Original value: 0x00000135 + pub const NV_Extend: Self = Self(0x136); // Original value: 0x00000136 + pub const NV_Write: Self = Self(0x137); // Original value: 0x00000137 + pub const NV_WriteLock: Self = Self(0x138); // Original value: 0x00000138 + pub const DictionaryAttackLockReset: Self = Self(0x139); // Original value: 0x00000139 + pub const DictionaryAttackParameters: Self = Self(0x13A); // Original value: 0x0000013A + pub const NV_ChangeAuth: Self = Self(0x13B); // Original value: 0x0000013B + + /// PCR + pub const PCR_Event: Self = Self(0x13C); // Original value: 0x0000013C + + /// PCR + pub const PCR_Reset: Self = Self(0x13D); // Original value: 0x0000013D + pub const SequenceComplete: Self = Self(0x13E); // Original value: 0x0000013E + pub const SetAlgorithmSet: Self = Self(0x13F); // Original value: 0x0000013F + pub const SetCommandCodeAuditStatus: Self = Self(0x140); // Original value: 0x00000140 + pub const FieldUpgradeData: Self = Self(0x141); // Original value: 0x00000141 + pub const IncrementalSelfTest: Self = Self(0x142); // Original value: 0x00000142 + pub const SelfTest: Self = Self(0x143); // Original value: 0x00000143 + pub const Startup: Self = Self(0x144); // Original value: 0x00000144 + pub const Shutdown: Self = Self(0x145); // Original value: 0x00000145 + pub const StirRandom: Self = Self(0x146); // Original value: 0x00000146 + pub const ActivateCredential: Self = Self(0x147); // Original value: 0x00000147 + pub const Certify: Self = Self(0x148); // Original value: 0x00000148 + + /// Policy + pub const PolicyNV: Self = Self(0x149); // Original value: 0x00000149 + pub const CertifyCreation: Self = Self(0x14A); // Original value: 0x0000014A + pub const Duplicate: Self = Self(0x14B); // Original value: 0x0000014B + pub const GetTime: Self = Self(0x14C); // Original value: 0x0000014C + pub const GetSessionAuditDigest: Self = Self(0x14D); // Original value: 0x0000014D + pub const NV_Read: Self = Self(0x14E); // Original value: 0x0000014E + pub const NV_ReadLock: Self = Self(0x14F); // Original value: 0x0000014F + pub const ObjectChangeAuth: Self = Self(0x150); // Original value: 0x00000150 + + /// Policy + pub const PolicySecret: Self = Self(0x151); // Original value: 0x00000151 + pub const Rewrap: Self = Self(0x152); // Original value: 0x00000152 + pub const Create: Self = Self(0x153); // Original value: 0x00000153 + pub const ECDH_ZGen: Self = Self(0x154); // Original value: 0x00000154 + + /// See NOTE 1 + pub const HMAC: Self = Self(0x155); // Original value: 0x00000155 + + /// See NOTE 1 + pub const MAC: Self = Self(0x155); // Original value: 0x00000155 + pub const Import: Self = Self(0x156); // Original value: 0x00000156 + pub const Load: Self = Self(0x157); // Original value: 0x00000157 + pub const Quote: Self = Self(0x158); // Original value: 0x00000158 + pub const RSA_Decrypt: Self = Self(0x159); // Original value: 0x00000159 + + /// See NOTE 1 + pub const HMAC_Start: Self = Self(0x15B); // Original value: 0x0000015B + + /// See NOTE 1 + pub const MAC_Start: Self = Self(0x15B); // Original value: 0x0000015B + pub const SequenceUpdate: Self = Self(0x15C); // Original value: 0x0000015C + pub const Sign: Self = Self(0x15D); // Original value: 0x0000015D + pub const Unseal: Self = Self(0x15E); // Original value: 0x0000015E + + /// Policy + pub const PolicySigned: Self = Self(0x160); // Original value: 0x00000160 + + /// Context + pub const ContextLoad: Self = Self(0x161); // Original value: 0x00000161 + + /// Context + pub const ContextSave: Self = Self(0x162); // Original value: 0x00000162 + pub const ECDH_KeyGen: Self = Self(0x163); // Original value: 0x00000163 + pub const EncryptDecrypt: Self = Self(0x164); // Original value: 0x00000164 + + /// Context + pub const FlushContext: Self = Self(0x165); // Original value: 0x00000165 + pub const LoadExternal: Self = Self(0x167); // Original value: 0x00000167 + pub const MakeCredential: Self = Self(0x168); // Original value: 0x00000168 + + /// NV + pub const NV_ReadPublic: Self = Self(0x169); // Original value: 0x00000169 + + /// Policy + pub const PolicyAuthorize: Self = Self(0x16A); // Original value: 0x0000016A + + /// Policy + pub const PolicyAuthValue: Self = Self(0x16B); // Original value: 0x0000016B + + /// Policy + pub const PolicyCommandCode: Self = Self(0x16C); // Original value: 0x0000016C + + /// Policy + pub const PolicyCounterTimer: Self = Self(0x16D); // Original value: 0x0000016D + + /// Policy + pub const PolicyCpHash: Self = Self(0x16E); // Original value: 0x0000016E + + /// Policy + pub const PolicyLocality: Self = Self(0x16F); // Original value: 0x0000016F + + /// Policy + pub const PolicyNameHash: Self = Self(0x170); // Original value: 0x00000170 + + /// Policy + pub const PolicyOR: Self = Self(0x171); // Original value: 0x00000171 + + /// Policy + pub const PolicyTicket: Self = Self(0x172); // Original value: 0x00000172 + pub const ReadPublic: Self = Self(0x173); // Original value: 0x00000173 + pub const RSA_Encrypt: Self = Self(0x174); // Original value: 0x00000174 + pub const StartAuthSession: Self = Self(0x176); // Original value: 0x00000176 + pub const VerifySignature: Self = Self(0x177); // Original value: 0x00000177 + pub const ECC_Parameters: Self = Self(0x178); // Original value: 0x00000178 + pub const FirmwareRead: Self = Self(0x179); // Original value: 0x00000179 + pub const GetCapability: Self = Self(0x17A); // Original value: 0x0000017A + pub const GetRandom: Self = Self(0x17B); // Original value: 0x0000017B + pub const GetTestResult: Self = Self(0x17C); // Original value: 0x0000017C + pub const Hash: Self = Self(0x17D); // Original value: 0x0000017D + + /// PCR + pub const PCR_Read: Self = Self(0x17E); // Original value: 0x0000017E + + /// Policy + pub const PolicyPCR: Self = Self(0x17F); // Original value: 0x0000017F + pub const PolicyRestart: Self = Self(0x180); // Original value: 0x00000180 + pub const ReadClock: Self = Self(0x181); // Original value: 0x00000181 + pub const PCR_Extend: Self = Self(0x182); // Original value: 0x00000182 + pub const PCR_SetAuthValue: Self = Self(0x183); // Original value: 0x00000183 + pub const NV_Certify: Self = Self(0x184); // Original value: 0x00000184 + pub const EventSequenceComplete: Self = Self(0x185); // Original value: 0x00000185 + pub const HashSequenceStart: Self = Self(0x186); // Original value: 0x00000186 + + /// Policy + pub const PolicyPhysicalPresence: Self = Self(0x187); // Original value: 0x00000187 + + /// Policy + pub const PolicyDuplicationSelect: Self = Self(0x188); // Original value: 0x00000188 + + /// Policy + pub const PolicyGetDigest: Self = Self(0x189); // Original value: 0x00000189 + pub const TestParms: Self = Self(0x18A); // Original value: 0x0000018A + pub const Commit: Self = Self(0x18B); // Original value: 0x0000018B + + /// Policy + pub const PolicyPassword: Self = Self(0x18C); // Original value: 0x0000018C + pub const ZGen_2Phase: Self = Self(0x18D); // Original value: 0x0000018D + pub const EC_Ephemeral: Self = Self(0x18E); // Original value: 0x0000018E + + /// Policy + pub const PolicyNvWritten: Self = Self(0x18F); // Original value: 0x0000018F + + /// Policy + pub const PolicyTemplate: Self = Self(0x190); // Original value: 0x00000190 + pub const CreateLoaded: Self = Self(0x191); // Original value: 0x00000191 + + /// Policy + pub const PolicyAuthorizeNV: Self = Self(0x192); // Original value: 0x00000192 + pub const EncryptDecrypt2: Self = Self(0x193); // Original value: 0x00000193 + pub const AC_GetCapability: Self = Self(0x194); // Original value: 0x00000194 + pub const AC_Send: Self = Self(0x195); // Original value: 0x00000195 + + /// Policy + pub const Policy_AC_SendSelect: Self = Self(0x196); // Original value: 0x00000196 + pub const CertifyX509: Self = Self(0x197); // Original value: 0x00000197 + pub const ACT_SetTimeout: Self = Self(0x198); // Original value: 0x00000198 + pub const ECC_Encrypt: Self = Self(0x199); // Original value: 0x00000199 + pub const ECC_Decrypt: Self = Self(0x19A); // Original value: 0x0000019A + + /// Compile variable. May increase based on implementation. + pub const LAST: Self = Self(0x19A); // Original value: 0x0000019A + pub const CC_VEND: Self = Self(0x20000000); + + /// Used for testing of command dispatch + pub const Vendor_TCG_Test: Self = Self(0x20000000); // Original value: CC_VEND.into()+0x0000 + + pub fn try_from(value: u32) -> Result { + match value { + 287 => Ok(Self::NV_UndefineSpaceSpecial), // Original value: 0x0000011F + 288 => Ok(Self::EvictControl), // Original value: 0x00000120 + 289 => Ok(Self::HierarchyControl), // Original value: 0x00000121 + 290 => Ok(Self::NV_UndefineSpace), // Original value: 0x00000122 + 292 => Ok(Self::ChangeEPS), // Original value: 0x00000124 + 293 => Ok(Self::ChangePPS), // Original value: 0x00000125 + 294 => Ok(Self::Clear), // Original value: 0x00000126 + 295 => Ok(Self::ClearControl), // Original value: 0x00000127 + 296 => Ok(Self::ClockSet), // Original value: 0x00000128 + 297 => Ok(Self::HierarchyChangeAuth), // Original value: 0x00000129 + 298 => Ok(Self::NV_DefineSpace), // Original value: 0x0000012A + 299 => Ok(Self::PCR_Allocate), // Original value: 0x0000012B + 300 => Ok(Self::PCR_SetAuthPolicy), // Original value: 0x0000012C + 301 => Ok(Self::PP_Commands), // Original value: 0x0000012D + 302 => Ok(Self::SetPrimaryPolicy), // Original value: 0x0000012E + 303 => Ok(Self::FieldUpgradeStart), // Original value: 0x0000012F + 304 => Ok(Self::ClockRateAdjust), // Original value: 0x00000130 + 305 => Ok(Self::CreatePrimary), // Original value: 0x00000131 + 306 => Ok(Self::NV_GlobalWriteLock), // Original value: 0x00000132 + 307 => Ok(Self::GetCommandAuditDigest), // Original value: 0x00000133 + 308 => Ok(Self::NV_Increment), // Original value: 0x00000134 + 309 => Ok(Self::NV_SetBits), // Original value: 0x00000135 + 310 => Ok(Self::NV_Extend), // Original value: 0x00000136 + 311 => Ok(Self::NV_Write), // Original value: 0x00000137 + 312 => Ok(Self::NV_WriteLock), // Original value: 0x00000138 + 313 => Ok(Self::DictionaryAttackLockReset), // Original value: 0x00000139 + 314 => Ok(Self::DictionaryAttackParameters), // Original value: 0x0000013A + 315 => Ok(Self::NV_ChangeAuth), // Original value: 0x0000013B + 316 => Ok(Self::PCR_Event), // Original value: 0x0000013C + 317 => Ok(Self::PCR_Reset), // Original value: 0x0000013D + 318 => Ok(Self::SequenceComplete), // Original value: 0x0000013E + 319 => Ok(Self::SetAlgorithmSet), // Original value: 0x0000013F + 320 => Ok(Self::SetCommandCodeAuditStatus), // Original value: 0x00000140 + 321 => Ok(Self::FieldUpgradeData), // Original value: 0x00000141 + 322 => Ok(Self::IncrementalSelfTest), // Original value: 0x00000142 + 323 => Ok(Self::SelfTest), // Original value: 0x00000143 + 324 => Ok(Self::Startup), // Original value: 0x00000144 + 325 => Ok(Self::Shutdown), // Original value: 0x00000145 + 326 => Ok(Self::StirRandom), // Original value: 0x00000146 + 327 => Ok(Self::ActivateCredential), // Original value: 0x00000147 + 328 => Ok(Self::Certify), // Original value: 0x00000148 + 329 => Ok(Self::PolicyNV), // Original value: 0x00000149 + 330 => Ok(Self::CertifyCreation), // Original value: 0x0000014A + 331 => Ok(Self::Duplicate), // Original value: 0x0000014B + 332 => Ok(Self::GetTime), // Original value: 0x0000014C + 333 => Ok(Self::GetSessionAuditDigest), // Original value: 0x0000014D + 334 => Ok(Self::NV_Read), // Original value: 0x0000014E + 335 => Ok(Self::NV_ReadLock), // Original value: 0x0000014F + 336 => Ok(Self::ObjectChangeAuth), // Original value: 0x00000150 + 337 => Ok(Self::PolicySecret), // Original value: 0x00000151 + 338 => Ok(Self::Rewrap), // Original value: 0x00000152 + 339 => Ok(Self::Create), // Original value: 0x00000153 + 340 => Ok(Self::ECDH_ZGen), // Original value: 0x00000154 + 341 => Ok(Self::MAC), // Original value: 0x00000155 + 342 => Ok(Self::Import), // Original value: 0x00000156 + 343 => Ok(Self::Load), // Original value: 0x00000157 + 344 => Ok(Self::Quote), // Original value: 0x00000158 + 345 => Ok(Self::RSA_Decrypt), // Original value: 0x00000159 + 347 => Ok(Self::MAC_Start), // Original value: 0x0000015B + 348 => Ok(Self::SequenceUpdate), // Original value: 0x0000015C + 349 => Ok(Self::Sign), // Original value: 0x0000015D + 350 => Ok(Self::Unseal), // Original value: 0x0000015E + 352 => Ok(Self::PolicySigned), // Original value: 0x00000160 + 353 => Ok(Self::ContextLoad), // Original value: 0x00000161 + 354 => Ok(Self::ContextSave), // Original value: 0x00000162 + 355 => Ok(Self::ECDH_KeyGen), // Original value: 0x00000163 + 356 => Ok(Self::EncryptDecrypt), // Original value: 0x00000164 + 357 => Ok(Self::FlushContext), // Original value: 0x00000165 + 359 => Ok(Self::LoadExternal), // Original value: 0x00000167 + 360 => Ok(Self::MakeCredential), // Original value: 0x00000168 + 361 => Ok(Self::NV_ReadPublic), // Original value: 0x00000169 + 362 => Ok(Self::PolicyAuthorize), // Original value: 0x0000016A + 363 => Ok(Self::PolicyAuthValue), // Original value: 0x0000016B + 364 => Ok(Self::PolicyCommandCode), // Original value: 0x0000016C + 365 => Ok(Self::PolicyCounterTimer), // Original value: 0x0000016D + 366 => Ok(Self::PolicyCpHash), // Original value: 0x0000016E + 367 => Ok(Self::PolicyLocality), // Original value: 0x0000016F + 368 => Ok(Self::PolicyNameHash), // Original value: 0x00000170 + 369 => Ok(Self::PolicyOR), // Original value: 0x00000171 + 370 => Ok(Self::PolicyTicket), // Original value: 0x00000172 + 371 => Ok(Self::ReadPublic), // Original value: 0x00000173 + 372 => Ok(Self::RSA_Encrypt), // Original value: 0x00000174 + 374 => Ok(Self::StartAuthSession), // Original value: 0x00000176 + 375 => Ok(Self::VerifySignature), // Original value: 0x00000177 + 376 => Ok(Self::ECC_Parameters), // Original value: 0x00000178 + 377 => Ok(Self::FirmwareRead), // Original value: 0x00000179 + 378 => Ok(Self::GetCapability), // Original value: 0x0000017A + 379 => Ok(Self::GetRandom), // Original value: 0x0000017B + 380 => Ok(Self::GetTestResult), // Original value: 0x0000017C + 381 => Ok(Self::Hash), // Original value: 0x0000017D + 382 => Ok(Self::PCR_Read), // Original value: 0x0000017E + 383 => Ok(Self::PolicyPCR), // Original value: 0x0000017F + 384 => Ok(Self::PolicyRestart), // Original value: 0x00000180 + 385 => Ok(Self::ReadClock), // Original value: 0x00000181 + 386 => Ok(Self::PCR_Extend), // Original value: 0x00000182 + 387 => Ok(Self::PCR_SetAuthValue), // Original value: 0x00000183 + 388 => Ok(Self::NV_Certify), // Original value: 0x00000184 + 389 => Ok(Self::EventSequenceComplete), // Original value: 0x00000185 + 390 => Ok(Self::HashSequenceStart), // Original value: 0x00000186 + 391 => Ok(Self::PolicyPhysicalPresence), // Original value: 0x00000187 + 392 => Ok(Self::PolicyDuplicationSelect), // Original value: 0x00000188 + 393 => Ok(Self::PolicyGetDigest), // Original value: 0x00000189 + 394 => Ok(Self::TestParms), // Original value: 0x0000018A + 395 => Ok(Self::Commit), // Original value: 0x0000018B + 396 => Ok(Self::PolicyPassword), // Original value: 0x0000018C + 397 => Ok(Self::ZGen_2Phase), // Original value: 0x0000018D + 398 => Ok(Self::EC_Ephemeral), // Original value: 0x0000018E + 399 => Ok(Self::PolicyNvWritten), // Original value: 0x0000018F + 400 => Ok(Self::PolicyTemplate), // Original value: 0x00000190 + 401 => Ok(Self::CreateLoaded), // Original value: 0x00000191 + 402 => Ok(Self::PolicyAuthorizeNV), // Original value: 0x00000192 + 403 => Ok(Self::EncryptDecrypt2), // Original value: 0x00000193 + 404 => Ok(Self::AC_GetCapability), // Original value: 0x00000194 + 405 => Ok(Self::AC_Send), // Original value: 0x00000195 + 406 => Ok(Self::Policy_AC_SendSelect), // Original value: 0x00000196 + 407 => Ok(Self::CertifyX509), // Original value: 0x00000197 + 408 => Ok(Self::ACT_SetTimeout), // Original value: 0x00000198 + 409 => Ok(Self::ECC_Encrypt), // Original value: 0x00000199 + 410 => Ok(Self::LAST), // Original value: 0x0000019A + 536870912 => Ok(Self::Vendor_TCG_Test), // Original value: CC_VEND.into()+0x0000 + _ => Err(TpmError::InvalidEnumValue), + } + } +} + +impl TpmEnum for TPM_CC { + fn get_value(&self) -> u32 { + self.0.into() + } + + fn try_from_trait(value: u64) -> Result where Self: Sized { + TPM_CC::try_from(value as u32) + } + + fn new_from_trait(value: u64) -> Result where Self: Sized { + Ok(TPM_CC(value as u32)) + } +} + +impl From for u32 { + fn from(value: TPM_CC) -> Self { + value.0 as u32 + } +} + +impl From for i32 { + fn from(value: TPM_CC) -> Self { + value.0 as i32 + } +} + +impl fmt::Display for TPM_CC { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self.0 { + 287 => write!(f, "NV_UndefineSpaceSpecial"), + 288 => write!(f, "EvictControl"), + 289 => write!(f, "HierarchyControl"), + 290 => write!(f, "NV_UndefineSpace"), + 292 => write!(f, "ChangeEPS"), + 293 => write!(f, "ChangePPS"), + 294 => write!(f, "Clear"), + 295 => write!(f, "ClearControl"), + 296 => write!(f, "ClockSet"), + 297 => write!(f, "HierarchyChangeAuth"), + 298 => write!(f, "NV_DefineSpace"), + 299 => write!(f, "PCR_Allocate"), + 300 => write!(f, "PCR_SetAuthPolicy"), + 301 => write!(f, "PP_Commands"), + 302 => write!(f, "SetPrimaryPolicy"), + 303 => write!(f, "FieldUpgradeStart"), + 304 => write!(f, "ClockRateAdjust"), + 305 => write!(f, "CreatePrimary"), + 306 => write!(f, "NV_GlobalWriteLock"), + 307 => write!(f, "GetCommandAuditDigest"), + 308 => write!(f, "NV_Increment"), + 309 => write!(f, "NV_SetBits"), + 310 => write!(f, "NV_Extend"), + 311 => write!(f, "NV_Write"), + 312 => write!(f, "NV_WriteLock"), + 313 => write!(f, "DictionaryAttackLockReset"), + 314 => write!(f, "DictionaryAttackParameters"), + 315 => write!(f, "NV_ChangeAuth"), + 316 => write!(f, "PCR_Event"), + 317 => write!(f, "PCR_Reset"), + 318 => write!(f, "SequenceComplete"), + 319 => write!(f, "SetAlgorithmSet"), + 320 => write!(f, "SetCommandCodeAuditStatus"), + 321 => write!(f, "FieldUpgradeData"), + 322 => write!(f, "IncrementalSelfTest"), + 323 => write!(f, "SelfTest"), + 324 => write!(f, "Startup"), + 325 => write!(f, "Shutdown"), + 326 => write!(f, "StirRandom"), + 327 => write!(f, "ActivateCredential"), + 328 => write!(f, "Certify"), + 329 => write!(f, "PolicyNV"), + 330 => write!(f, "CertifyCreation"), + 331 => write!(f, "Duplicate"), + 332 => write!(f, "GetTime"), + 333 => write!(f, "GetSessionAuditDigest"), + 334 => write!(f, "NV_Read"), + 335 => write!(f, "NV_ReadLock"), + 336 => write!(f, "ObjectChangeAuth"), + 337 => write!(f, "PolicySecret"), + 338 => write!(f, "Rewrap"), + 339 => write!(f, "Create"), + 340 => write!(f, "ECDH_ZGen"), + 341 => write!(f, "MAC"), + 342 => write!(f, "Import"), + 343 => write!(f, "Load"), + 344 => write!(f, "Quote"), + 345 => write!(f, "RSA_Decrypt"), + 347 => write!(f, "MAC_Start"), + 348 => write!(f, "SequenceUpdate"), + 349 => write!(f, "Sign"), + 350 => write!(f, "Unseal"), + 352 => write!(f, "PolicySigned"), + 353 => write!(f, "ContextLoad"), + 354 => write!(f, "ContextSave"), + 355 => write!(f, "ECDH_KeyGen"), + 356 => write!(f, "EncryptDecrypt"), + 357 => write!(f, "FlushContext"), + 359 => write!(f, "LoadExternal"), + 360 => write!(f, "MakeCredential"), + 361 => write!(f, "NV_ReadPublic"), + 362 => write!(f, "PolicyAuthorize"), + 363 => write!(f, "PolicyAuthValue"), + 364 => write!(f, "PolicyCommandCode"), + 365 => write!(f, "PolicyCounterTimer"), + 366 => write!(f, "PolicyCpHash"), + 367 => write!(f, "PolicyLocality"), + 368 => write!(f, "PolicyNameHash"), + 369 => write!(f, "PolicyOR"), + 370 => write!(f, "PolicyTicket"), + 371 => write!(f, "ReadPublic"), + 372 => write!(f, "RSA_Encrypt"), + 374 => write!(f, "StartAuthSession"), + 375 => write!(f, "VerifySignature"), + 376 => write!(f, "ECC_Parameters"), + 377 => write!(f, "FirmwareRead"), + 378 => write!(f, "GetCapability"), + 379 => write!(f, "GetRandom"), + 380 => write!(f, "GetTestResult"), + 381 => write!(f, "Hash"), + 382 => write!(f, "PCR_Read"), + 383 => write!(f, "PolicyPCR"), + 384 => write!(f, "PolicyRestart"), + 385 => write!(f, "ReadClock"), + 386 => write!(f, "PCR_Extend"), + 387 => write!(f, "PCR_SetAuthValue"), + 388 => write!(f, "NV_Certify"), + 389 => write!(f, "EventSequenceComplete"), + 390 => write!(f, "HashSequenceStart"), + 391 => write!(f, "PolicyPhysicalPresence"), + 392 => write!(f, "PolicyDuplicationSelect"), + 393 => write!(f, "PolicyGetDigest"), + 394 => write!(f, "TestParms"), + 395 => write!(f, "Commit"), + 396 => write!(f, "PolicyPassword"), + 397 => write!(f, "ZGen_2Phase"), + 398 => write!(f, "EC_Ephemeral"), + 399 => write!(f, "PolicyNvWritten"), + 400 => write!(f, "PolicyTemplate"), + 401 => write!(f, "CreateLoaded"), + 402 => write!(f, "PolicyAuthorizeNV"), + 403 => write!(f, "EncryptDecrypt2"), + 404 => write!(f, "AC_GetCapability"), + 405 => write!(f, "AC_Send"), + 406 => write!(f, "Policy_AC_SendSelect"), + 407 => write!(f, "CertifyX509"), + 408 => write!(f, "ACT_SetTimeout"), + 409 => write!(f, "ECC_Encrypt"), + 410 => write!(f, "LAST"), + 536870912 => write!(f, "Vendor_TCG_Test"), + _ => write!(f, "{}", enum_to_str(self.0 as u64, std::any::TypeId::of::())), + } + } +} + +/// Architecturally defined constants +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)] +pub struct ImplementationConstants(pub u32); + +impl ImplementationConstants { + pub const Ossl: Self = Self(0x1); // Original value: 1 + pub const Ltc: Self = Self(0x2); // Original value: 2 + pub const Msbn: Self = Self(0x3); // Original value: 3 + pub const Symcrypt: Self = Self(0x4); // Original value: 4 + pub const HASH_COUNT: Self = Self(0x3); // Original value: 3 + pub const MAX_SYM_KEY_BITS: Self = Self(0x100); // Original value: 256 + pub const MAX_SYM_KEY_BYTES: Self = Self(0x20); // Original value: ((MAX_SYM_KEY_BITS.into() + 7) / 8) + pub const MAX_SYM_BLOCK_SIZE: Self = Self(0x10); // Original value: 16 + pub const MAX_CAP_CC: Self = Self(0x19A); // Original value: TPM_CC::LAST.into() + pub const MAX_RSA_KEY_BYTES: Self = Self(0x100); // Original value: 256 + pub const MAX_AES_KEY_BYTES: Self = Self(0x20); // Original value: 32 + pub const MAX_ECC_KEY_BYTES: Self = Self(0x30); // Original value: 48 + pub const LABEL_MAX_BUFFER: Self = Self(0x20); // Original value: 32 + pub const _TPM_CAP_SIZE: Self = Self(0x4); // Original value: 0x4 /* sizeof(UINT32) */ + pub const MAX_CAP_DATA: Self = Self(0x3F8); // Original value: (Implementation::MAX_CAP_BUFFER.into()-_TPM_CAP_SIZE.into()-0x4) /* (MAX_CAP_BUFFER-_TPM_CAP_SIZE-sizeof(UINT32)) */ + pub const MAX_CAP_ALGS: Self = Self(0xA9); // Original value: (MAX_CAP_DATA.into() / 0x6) /* (MAX_CAP_DATA / sizeof(TPMS_ALG_PROPERTY)) */ + pub const MAX_CAP_HANDLES: Self = Self(0xFE); // Original value: (MAX_CAP_DATA.into() / 0x4) /* (MAX_CAP_DATA / sizeof(TPM_HANDLE)) */ + pub const MAX_TPM_PROPERTIES: Self = Self(0x7F); // Original value: (MAX_CAP_DATA.into() / 0x8) /* (MAX_CAP_DATA / sizeof(TPMS_TAGGED_PROPERTY)) */ + pub const MAX_PCR_PROPERTIES: Self = Self(0xCB); // Original value: (MAX_CAP_DATA.into() / 0x5) /* (MAX_CAP_DATA / sizeof(TPMS_TAGGED_PCR_SELECT)) */ + pub const MAX_ECC_CURVES: Self = Self(0x1FC); // Original value: (MAX_CAP_DATA.into() / 0x2) /* (MAX_CAP_DATA / sizeof(TPM_ECC_CURVE)) */ + pub const MAX_TAGGED_POLICIES: Self = Self(0xE); // Original value: (MAX_CAP_DATA.into() / 0x46) /* (MAX_CAP_DATA / sizeof(TPMS_TAGGED_POLICY)) */ + pub const MAX_AC_CAPABILITIES: Self = Self(0x7F); // Original value: (MAX_CAP_DATA.into() / 0x8) /* (MAX_CAP_DATA / sizeof(TPMS_AC_OUTPUT)) */ + pub const MAX_ACT_DATA: Self = Self(0x54); // Original value: MAX_CAP_DATA.into() / 0xC /* MAX_CAP_DATA / sizeof(TPMS_ACT_DATA) */ + + pub fn try_from(value: u32) -> Result { + match value { + 1 => Ok(Self::Ossl), // Original value: 1 + 2 => Ok(Self::Ltc), // Original value: 2 + 3 => Ok(Self::HASH_COUNT), // Original value: 3 + 4 => Ok(Self::_TPM_CAP_SIZE), // Original value: 0x4 /* sizeof(UINT32) */ + 256 => Ok(Self::MAX_RSA_KEY_BYTES), // Original value: 256 + 32 => Ok(Self::LABEL_MAX_BUFFER), // Original value: 32 + 16 => Ok(Self::MAX_SYM_BLOCK_SIZE), // Original value: 16 + 410 => Ok(Self::MAX_CAP_CC), // Original value: TPM_CC::LAST.into() + 48 => Ok(Self::MAX_ECC_KEY_BYTES), // Original value: 48 + 1016 => Ok(Self::MAX_CAP_DATA), // Original value: (Implementation::MAX_CAP_BUFFER.into()-_TPM_CAP_SIZE.into()-0x4) /* (MAX_CAP_BUFFER-_TPM_CAP_SIZE-sizeof(UINT32)) */ + 169 => Ok(Self::MAX_CAP_ALGS), // Original value: (MAX_CAP_DATA.into() / 0x6) /* (MAX_CAP_DATA / sizeof(TPMS_ALG_PROPERTY)) */ + 254 => Ok(Self::MAX_CAP_HANDLES), // Original value: (MAX_CAP_DATA.into() / 0x4) /* (MAX_CAP_DATA / sizeof(TPM_HANDLE)) */ + 127 => Ok(Self::MAX_AC_CAPABILITIES), // Original value: (MAX_CAP_DATA.into() / 0x8) /* (MAX_CAP_DATA / sizeof(TPMS_AC_OUTPUT)) */ + 203 => Ok(Self::MAX_PCR_PROPERTIES), // Original value: (MAX_CAP_DATA.into() / 0x5) /* (MAX_CAP_DATA / sizeof(TPMS_TAGGED_PCR_SELECT)) */ + 508 => Ok(Self::MAX_ECC_CURVES), // Original value: (MAX_CAP_DATA.into() / 0x2) /* (MAX_CAP_DATA / sizeof(TPM_ECC_CURVE)) */ + 14 => Ok(Self::MAX_TAGGED_POLICIES), // Original value: (MAX_CAP_DATA.into() / 0x46) /* (MAX_CAP_DATA / sizeof(TPMS_TAGGED_POLICY)) */ + 84 => Ok(Self::MAX_ACT_DATA), // Original value: MAX_CAP_DATA.into() / 0xC /* MAX_CAP_DATA / sizeof(TPMS_ACT_DATA) */ + _ => Err(TpmError::InvalidEnumValue), + } + } +} + +impl TpmEnum for ImplementationConstants { + fn get_value(&self) -> u32 { + self.0.into() + } + + fn try_from_trait(value: u64) -> Result where Self: Sized { + ImplementationConstants::try_from(value as u32) + } + + fn new_from_trait(value: u64) -> Result where Self: Sized { + Ok(ImplementationConstants(value as u32)) + } +} + +impl From for u32 { + fn from(value: ImplementationConstants) -> Self { + value.0 as u32 + } +} + +impl From for i32 { + fn from(value: ImplementationConstants) -> Self { + value.0 as i32 + } +} + +impl fmt::Display for ImplementationConstants { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self.0 { + 1 => write!(f, "Ossl"), + 2 => write!(f, "Ltc"), + 3 => write!(f, "HASH_COUNT"), + 4 => write!(f, "_TPM_CAP_SIZE"), + 256 => write!(f, "MAX_RSA_KEY_BYTES"), + 32 => write!(f, "LABEL_MAX_BUFFER"), + 16 => write!(f, "MAX_SYM_BLOCK_SIZE"), + 410 => write!(f, "MAX_CAP_CC"), + 48 => write!(f, "MAX_ECC_KEY_BYTES"), + 1016 => write!(f, "MAX_CAP_DATA"), + 169 => write!(f, "MAX_CAP_ALGS"), + 254 => write!(f, "MAX_CAP_HANDLES"), + 127 => write!(f, "MAX_AC_CAPABILITIES"), + 203 => write!(f, "MAX_PCR_PROPERTIES"), + 508 => write!(f, "MAX_ECC_CURVES"), + 14 => write!(f, "MAX_TAGGED_POLICIES"), + 84 => write!(f, "MAX_ACT_DATA"), + _ => write!(f, "{}", enum_to_str(self.0 as u64, std::any::TypeId::of::())), + } + } +} + +/// In general, response codes defined in TPM 2.0 Part 2 will be unmarshaling errors and +/// will have the F (format) bit SET. Codes that are unique to TPM 2.0 Part 3 will have +/// the F bit CLEAR but the V (version) attribute will be SET to indicate that it is a TPM +/// 2.0 response code. See Response Code Details in TPM 2.0 Part 1. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)] +pub struct TPM_RC(pub u32); + +impl TPM_RC { + pub const SUCCESS: Self = Self(0x0); // Original value: 0x000 + + /// Defined for compatibility with TPM 1.2 + pub const BAD_TAG: Self = Self(0x1E); // Original value: 0x01E + + /// Set for all format 0 response codes + pub const RC_VER1: Self = Self(0x100); + + /// TPM not initialized by TPM2_Startup or already initialized + pub const INITIALIZE: Self = Self(0x100); // Original value: RC_VER1.into() + 0x000 + + /// Commands not being accepted because of a TPM failure + /// NOTE This may be returned by TPM2_GetTestResult() as the testResult parameter. + pub const FAILURE: Self = Self(0x101); // Original value: RC_VER1.into() + 0x001 + + /// Improper use of a sequence handle + pub const SEQUENCE: Self = Self(0x103); // Original value: RC_VER1.into() + 0x003 + + /// Not currently used + pub const PRIVATE: Self = Self(0x10B); // Original value: RC_VER1.into() + 0x00B + + /// Not currently used + pub const HMAC: Self = Self(0x119); // Original value: RC_VER1.into() + 0x019 + + /// The command is disabled + pub const DISABLED: Self = Self(0x120); // Original value: RC_VER1.into() + 0x020 + + /// Command failed because audit sequence required exclusivity + pub const EXCLUSIVE: Self = Self(0x121); // Original value: RC_VER1.into() + 0x021 + + /// Authorization handle is not correct for command + pub const AUTH_TYPE: Self = Self(0x124); // Original value: RC_VER1.into() + 0x024 + + /// Command requires an authorization session for handle and it is not present. + pub const AUTH_MISSING: Self = Self(0x125); // Original value: RC_VER1.into() + 0x025 + + /// Policy failure in math operation or an invalid authPolicy value + pub const POLICY: Self = Self(0x126); // Original value: RC_VER1.into() + 0x026 + + /// PCR check fail + pub const PCR: Self = Self(0x127); // Original value: RC_VER1.into() + 0x027 + + /// PCR have changed since checked. + pub const PCR_CHANGED: Self = Self(0x128); // Original value: RC_VER1.into() + 0x028 + + /// For all commands other than TPM2_FieldUpgradeData(), this code indicates that the TPM + /// is in field upgrade mode; for TPM2_FieldUpgradeData(), this code indicates that the + /// TPM is not in field upgrade mode + pub const UPGRADE: Self = Self(0x12D); // Original value: RC_VER1.into() + 0x02D + + /// Context ID counter is at maximum. + pub const TOO_MANY_CONTEXTS: Self = Self(0x12E); // Original value: RC_VER1.into() + 0x02E + + /// AuthValue or authPolicy is not available for selected entity. + pub const AUTH_UNAVAILABLE: Self = Self(0x12F); // Original value: RC_VER1.into() + 0x02F + + /// A _TPM_Init and Startup(CLEAR) is required before the TPM can resume operation. + pub const REBOOT: Self = Self(0x130); // Original value: RC_VER1.into() + 0x030 + + /// The protection algorithms (hash and symmetric) are not reasonably balanced. The digest + /// size of the hash must be larger than the key size of the symmetric algorithm. + pub const UNBALANCED: Self = Self(0x131); // Original value: RC_VER1.into() + 0x031 + + /// Command commandSize value is inconsistent with contents of the command buffer; either + /// the size is not the same as the octets loaded by the hardware interface layer or the + /// value is not large enough to hold a command header + pub const COMMAND_SIZE: Self = Self(0x142); // Original value: RC_VER1.into() + 0x042 + + /// Command code not supported + pub const COMMAND_CODE: Self = Self(0x143); // Original value: RC_VER1.into() + 0x043 + + /// The value of authorizationSize is out of range or the number of octets in the + /// Authorization Area is greater than required + pub const AUTHSIZE: Self = Self(0x144); // Original value: RC_VER1.into() + 0x044 + + /// Use of an authorization session with a context command or another command that cannot + /// have an authorization session. + pub const AUTH_CONTEXT: Self = Self(0x145); // Original value: RC_VER1.into() + 0x045 + + /// NV offset+size is out of range. + pub const NV_RANGE: Self = Self(0x146); // Original value: RC_VER1.into() + 0x046 + + /// Requested allocation size is larger than allowed. + pub const NV_SIZE: Self = Self(0x147); // Original value: RC_VER1.into() + 0x047 + + /// NV access locked. + pub const NV_LOCKED: Self = Self(0x148); // Original value: RC_VER1.into() + 0x048 + + /// NV access authorization fails in command actions (this failure does not affect lockout.action) + pub const NV_AUTHORIZATION: Self = Self(0x149); // Original value: RC_VER1.into() + 0x049 + + /// An NV Index is used before being initialized or the state saved by + /// TPM2_Shutdown(STATE) could not be restored + pub const NV_UNINITIALIZED: Self = Self(0x14A); // Original value: RC_VER1.into() + 0x04A + + /// Insufficient space for NV allocation + pub const NV_SPACE: Self = Self(0x14B); // Original value: RC_VER1.into() + 0x04B + + /// NV Index or persistent object already defined + pub const NV_DEFINED: Self = Self(0x14C); // Original value: RC_VER1.into() + 0x04C + + /// Context in TPM2_ContextLoad() is not valid + pub const BAD_CONTEXT: Self = Self(0x150); // Original value: RC_VER1.into() + 0x050 + + /// CpHash value already set or not correct for use + pub const CPHASH: Self = Self(0x151); // Original value: RC_VER1.into() + 0x051 + + /// Handle for parent is not a valid parent + pub const PARENT: Self = Self(0x152); // Original value: RC_VER1.into() + 0x052 + + /// Some function needs testing. + pub const NEEDS_TEST: Self = Self(0x153); // Original value: RC_VER1.into() + 0x053 + + /// Returned when an internal function cannot process a request due to an unspecified + /// problem. This code is usually related to invalid parameters that are not properly + /// filtered by the input unmarshaling code. + pub const NO_RESULT: Self = Self(0x154); // Original value: RC_VER1.into() + 0x054 + + /// The sensitive area did not unmarshal correctly after decryption this code is used in + /// lieu of the other unmarshaling errors so that an attacker cannot determine where the + /// unmarshaling error occurred + pub const SENSITIVE: Self = Self(0x155); // Original value: RC_VER1.into() + 0x055 + + /// Largest version 1 code that is not a warning + pub const RC_MAX_FM0: Self = Self(0x17F); // Original value: RC_VER1.into() + 0x07F + + /// This bit is SET in all format 1 response codes + /// The codes in this group may have a value added to them to indicate the handle, + /// session, or parameter to which they apply. + pub const RC_FMT1: Self = Self(0x80); // Original value: 0x080 + + /// Asymmetric algorithm not supported or not correct + pub const ASYMMETRIC: Self = Self(0x81); // Original value: RC_FMT1.into() + 0x001 + + /// Inconsistent attributes + pub const ATTRIBUTES: Self = Self(0x82); // Original value: RC_FMT1.into() + 0x002 + + /// Hash algorithm not supported or not appropriate + pub const HASH: Self = Self(0x83); // Original value: RC_FMT1.into() + 0x003 + + /// Value is out of range or is not correct for the context + pub const VALUE: Self = Self(0x84); // Original value: RC_FMT1.into() + 0x004 + + /// Hierarchy is not enabled or is not correct for the use + pub const HIERARCHY: Self = Self(0x85); // Original value: RC_FMT1.into() + 0x005 + + /// Key size is not supported + pub const KEY_SIZE: Self = Self(0x87); // Original value: RC_FMT1.into() + 0x007 + + /// Mask generation function not supported + pub const MGF: Self = Self(0x88); // Original value: RC_FMT1.into() + 0x008 + + /// Mode of operation not supported + pub const MODE: Self = Self(0x89); // Original value: RC_FMT1.into() + 0x009 + + /// The type of the value is not appropriate for the use + pub const TYPE: Self = Self(0x8A); // Original value: RC_FMT1.into() + 0x00A + + /// The handle is not correct for the use + pub const HANDLE: Self = Self(0x8B); // Original value: RC_FMT1.into() + 0x00B + + /// Unsupported key derivation function or function not appropriate for use + pub const KDF: Self = Self(0x8C); // Original value: RC_FMT1.into() + 0x00C + + /// Value was out of allowed range. + pub const RANGE: Self = Self(0x8D); // Original value: RC_FMT1.into() + 0x00D + + /// The authorization HMAC check failed and DA counter incremented + pub const AUTH_FAIL: Self = Self(0x8E); // Original value: RC_FMT1.into() + 0x00E + + /// Invalid nonce size or nonce value mismatch + pub const NONCE: Self = Self(0x8F); // Original value: RC_FMT1.into() + 0x00F + + /// Authorization requires assertion of PP + pub const PP: Self = Self(0x90); // Original value: RC_FMT1.into() + 0x010 + + /// Unsupported or incompatible scheme + pub const SCHEME: Self = Self(0x92); // Original value: RC_FMT1.into() + 0x012 + + /// Structure is the wrong size + pub const SIZE: Self = Self(0x95); // Original value: RC_FMT1.into() + 0x015 + + /// Unsupported symmetric algorithm or key size, or not appropriate for instance + pub const SYMMETRIC: Self = Self(0x96); // Original value: RC_FMT1.into() + 0x016 + + /// Incorrect structure tag + pub const TAG: Self = Self(0x97); // Original value: RC_FMT1.into() + 0x017 + + /// Union selector is incorrect + pub const SELECTOR: Self = Self(0x98); // Original value: RC_FMT1.into() + 0x018 + + /// The TPM was unable to unmarshal a value because there were not enough octets in the + /// input buffer + pub const INSUFFICIENT: Self = Self(0x9A); // Original value: RC_FMT1.into() + 0x01A + + /// The signature is not valid + pub const SIGNATURE: Self = Self(0x9B); // Original value: RC_FMT1.into() + 0x01B + + /// Key fields are not compatible with the selected use + pub const KEY: Self = Self(0x9C); // Original value: RC_FMT1.into() + 0x01C + + /// A policy check failed + pub const POLICY_FAIL: Self = Self(0x9D); // Original value: RC_FMT1.into() + 0x01D + + /// Integrity check failed + pub const INTEGRITY: Self = Self(0x9F); // Original value: RC_FMT1.into() + 0x01F + + /// Invalid ticket + pub const TICKET: Self = Self(0xA0); // Original value: RC_FMT1.into() + 0x020 + + /// Reserved bits not set to zero as required + pub const RESERVED_BITS: Self = Self(0xA1); // Original value: RC_FMT1.into() + 0x021 + + /// Authorization failure without DA implications + pub const BAD_AUTH: Self = Self(0xA2); // Original value: RC_FMT1.into() + 0x022 + + /// The policy has expired + pub const EXPIRED: Self = Self(0xA3); // Original value: RC_FMT1.into() + 0x023 + + /// The commandCode in the policy is not the commandCode of the command or the command + /// code in a policy command references a command that is not implemented + pub const POLICY_CC: Self = Self(0xA4); // Original value: RC_FMT1.into() + 0x024 + + /// Public and sensitive portions of an object are not cryptographically bound + pub const BINDING: Self = Self(0xA5); // Original value: RC_FMT1.into() + 0x025 + + /// Curve not supported + pub const CURVE: Self = Self(0xA6); // Original value: RC_FMT1.into() + 0x026 + + /// Point is not on the required curve. + pub const ECC_POINT: Self = Self(0xA7); // Original value: RC_FMT1.into() + 0x027 + + /// Set for warning response codes + pub const RC_WARN: Self = Self(0x900); + + /// Gap for context ID is too large + pub const CONTEXT_GAP: Self = Self(0x901); // Original value: RC_WARN.into() + 0x001 + + /// Out of memory for object contexts + pub const OBJECT_MEMORY: Self = Self(0x902); // Original value: RC_WARN.into() + 0x002 + + /// Out of memory for session contexts + pub const SESSION_MEMORY: Self = Self(0x903); // Original value: RC_WARN.into() + 0x003 + + /// Out of shared object/session memory or need space for internal operations + pub const MEMORY: Self = Self(0x904); // Original value: RC_WARN.into() + 0x004 + + /// Out of session handles a session must be flushed before a new session may be created + pub const SESSION_HANDLES: Self = Self(0x905); // Original value: RC_WARN.into() + 0x005 + + /// Out of object handles the handle space for objects is depleted and a reboot is required + /// NOTE 1 This cannot occur on the reference implementation. + /// NOTE 2 There is no reason why an implementation would implement a design that would + /// deplete handle space. Platform specifications are encouraged to forbid it. + pub const OBJECT_HANDLES: Self = Self(0x906); // Original value: RC_WARN.into() + 0x006 + + /// Bad locality + pub const LOCALITY: Self = Self(0x907); // Original value: RC_WARN.into() + 0x007 + + /// The TPM has suspended operation on the command; forward progress was made and the + /// command may be retried + /// See TPM 2.0 Part 1, Multi-tasking. + /// NOTE This cannot occur on the reference implementation. + pub const YIELDED: Self = Self(0x908); // Original value: RC_WARN.into() + 0x008 + + /// The command was canceled + pub const CANCELED: Self = Self(0x909); // Original value: RC_WARN.into() + 0x009 + + /// TPM is performing self-tests + pub const TESTING: Self = Self(0x90A); // Original value: RC_WARN.into() + 0x00A + + /// The 1st handle in the handle area references a transient object or session that is not + /// loaded + pub const REFERENCE_H0: Self = Self(0x910); // Original value: RC_WARN.into() + 0x010 + + /// The 2nd handle in the handle area references a transient object or session that is not + /// loaded + pub const REFERENCE_H1: Self = Self(0x911); // Original value: RC_WARN.into() + 0x011 + + /// The 3rd handle in the handle area references a transient object or session that is not + /// loaded + pub const REFERENCE_H2: Self = Self(0x912); // Original value: RC_WARN.into() + 0x012 + + /// The 4th handle in the handle area references a transient object or session that is not + /// loaded + pub const REFERENCE_H3: Self = Self(0x913); // Original value: RC_WARN.into() + 0x013 + + /// The 5th handle in the handle area references a transient object or session that is not + /// loaded + pub const REFERENCE_H4: Self = Self(0x914); // Original value: RC_WARN.into() + 0x014 + + /// The 6th handle in the handle area references a transient object or session that is not + /// loaded + pub const REFERENCE_H5: Self = Self(0x915); // Original value: RC_WARN.into() + 0x015 + + /// The 7th handle in the handle area references a transient object or session that is not + /// loaded + pub const REFERENCE_H6: Self = Self(0x916); // Original value: RC_WARN.into() + 0x016 + + /// The 1st authorization session handle references a session that is not loaded + pub const REFERENCE_S0: Self = Self(0x918); // Original value: RC_WARN.into() + 0x018 + + /// The 2nd authorization session handle references a session that is not loaded + pub const REFERENCE_S1: Self = Self(0x919); // Original value: RC_WARN.into() + 0x019 + + /// The 3rd authorization session handle references a session that is not loaded + pub const REFERENCE_S2: Self = Self(0x91A); // Original value: RC_WARN.into() + 0x01A + + /// The 4th authorization session handle references a session that is not loaded + pub const REFERENCE_S3: Self = Self(0x91B); // Original value: RC_WARN.into() + 0x01B + + /// The 5th session handle references a session that is not loaded + pub const REFERENCE_S4: Self = Self(0x91C); // Original value: RC_WARN.into() + 0x01C + + /// The 6th session handle references a session that is not loaded + pub const REFERENCE_S5: Self = Self(0x91D); // Original value: RC_WARN.into() + 0x01D + + /// The 7th authorization session handle references a session that is not loaded + pub const REFERENCE_S6: Self = Self(0x91E); // Original value: RC_WARN.into() + 0x01E + + /// The TPM is rate-limiting accesses to prevent wearout of NV + pub const NV_RATE: Self = Self(0x920); // Original value: RC_WARN.into() + 0x020 + + /// Authorizations for objects subject to DA protection are not allowed at this time + /// because the TPM is in DA lockout mode + pub const LOCKOUT: Self = Self(0x921); // Original value: RC_WARN.into() + 0x021 + + /// The TPM was not able to start the command + pub const RETRY: Self = Self(0x922); // Original value: RC_WARN.into() + 0x022 + + /// The command may require writing of NV and NV is not current accessible + pub const NV_UNAVAILABLE: Self = Self(0x923); // Original value: RC_WARN.into() + 0x023 + + /// This value is reserved and shall not be returned by the TPM + pub const NOT_USED: Self = Self(0x97F); // Original value: RC_WARN.into() + 0x7F + + /// Add to a handle-related error + pub const H: Self = Self(0x0); // Original value: 0x000 + + /// Add to a parameter-related error + pub const P: Self = Self(0x40); // Original value: 0x040 + + /// Add to a session-related error + pub const S: Self = Self(0x800); + + /// Add to a parameter-, handle-, or session-related error + pub const _1: Self = Self(0x100); + + /// Add to a parameter-, handle-, or session-related error + pub const _2: Self = Self(0x200); + + /// Add to a parameter-, handle-, or session-related error + pub const _3: Self = Self(0x300); + + /// Add to a parameter-, handle-, or session-related error + pub const _4: Self = Self(0x400); + + /// Add to a parameter-, handle-, or session-related error + pub const _5: Self = Self(0x500); + + /// Add to a parameter-, handle-, or session-related error + pub const _6: Self = Self(0x600); + + /// Add to a parameter-, handle-, or session-related error + pub const _7: Self = Self(0x700); + + /// Add to a parameter-related error + pub const _8: Self = Self(0x800); + + /// Add to a parameter-related error + pub const _9: Self = Self(0x900); + + /// Add to a parameter-related error + pub const A: Self = Self(0xA00); + + /// Add to a parameter-related error + pub const B: Self = Self(0xB00); + + /// Add to a parameter-related error + pub const C: Self = Self(0xC00); + + /// Add to a parameter-related error + pub const D: Self = Self(0xD00); + + /// Add to a parameter-related error + pub const E: Self = Self(0xE00); + + /// Add to a parameter-related error + pub const F: Self = Self(0xF00); + + /// Number mask + pub const N_MASK: Self = Self(0xF00); + + /// Response buffer returned by the TPM is too short + pub const TSS_TCP_BAD_HANDSHAKE_RESP: Self = Self(0x40280001); + + /// Too old TCP server version + pub const TSS_TCP_SERVER_TOO_OLD: Self = Self(0x40280002); + + /// Bad ack from the TCP end point + pub const TSS_TCP_BAD_ACK: Self = Self(0x40280003); + + /// Wrong length of the response buffer returned by the TPM + pub const TSS_TCP_BAD_RESP_LEN: Self = Self(0x40280004); + + /// TPM2_Startup returned unexpected response code + pub const TSS_TCP_UNEXPECTED_STARTUP_RESP: Self = Self(0x40280005); + + /// Invalid size tag in the TPM response TCP packet + pub const TSS_TCP_INVALID_SIZE_TAG: Self = Self(0x40280006); + + /// TPM over TCP device is not connected + pub const TSS_TCP_DISCONNECTED: Self = Self(0x40280007); + + /// General TPM command dispatch failure + pub const TSS_DISPATCH_FAILED: Self = Self(0x40280010); + + /// Sending data to TPM failed + pub const TSS_SEND_OP_FAILED: Self = Self(0x40280011); + + /// Response buffer returned by the TPM is too short + pub const TSS_RESP_BUF_TOO_SHORT: Self = Self(0x40280021); + + /// Invalid tag in the response buffer returned by the TPM + pub const TSS_RESP_BUF_INVALID_SESSION_TAG: Self = Self(0x40280022); + + /// Inconsistent TPM response parameters size + pub const TSS_RESP_BUF_INVALID_SIZE: Self = Self(0x40280023); + + /// Windows TBS error TPM_E_COMMAND_BLOCKED + pub const TBS_COMMAND_BLOCKED: Self = Self(0x80280400); + + /// Windows TBS error TPM_E_INVALID_HANDLE + pub const TBS_INVALID_HANDLE: Self = Self(0x80280401); + + /// Windows TBS error TPM_E_DUPLICATE_VHANDLE + pub const TBS_DUPLICATE_V_HANDLE: Self = Self(0x80280402); + + /// Windows TBS error TPM_E_EMBEDDED_COMMAND_BLOCKED + pub const TBS_EMBEDDED_COMMAND_BLOCKED: Self = Self(0x80280403); + + /// Windows TBS error TPM_E_EMBEDDED_COMMAND_UNSUPPORTED + pub const TBS_EMBEDDED_COMMAND_UNSUPPORTED: Self = Self(0x80280404); + + /// Windows TBS returned success but empty response buffer + pub const TBS_UNKNOWN_ERROR: Self = Self(0x80284000); + + /// Windows TBS error TBS_E_INTERNAL_ERROR + pub const TBS_INTERNAL_ERROR: Self = Self(0x80284001); + + /// Windows TBS error TBS_E_BAD_PARAMETER + pub const TBS_BAD_PARAMETER: Self = Self(0x80284002); + + /// Windows TBS error TBS_E_INVALID_OUTPUT_POINTER + pub const TBS_INVALID_OUTPUT_POINTER: Self = Self(0x80284003); + + /// Windows TBS error TBS_E_INVALID_CONTEXT + pub const TBS_INVALID_CONTEXT: Self = Self(0x80284004); + + /// Windows TBS error TBS_E_INSUFFICIENT_BUFFER + pub const TBS_INSUFFICIENT_BUFFER: Self = Self(0x80284005); + + /// Windows TBS error TBS_E_IOERROR + pub const TBS_IO_ERROR: Self = Self(0x80284006); + + /// Windows TBS error TBS_E_INVALID_CONTEXT_PARAM + pub const TBS_INVALID_CONTEXT_PARAM: Self = Self(0x80284007); + + /// Windows TBS error TBS_E_SERVICE_NOT_RUNNING + pub const TBS_SERVICE_NOT_RUNNING: Self = Self(0x80284008); + + /// Windows TBS error TBS_E_TOO_MANY_TBS_CONTEXTS + pub const TBS_TOO_MANY_CONTEXTS: Self = Self(0x80284009); + + /// Windows TBS error TBS_E_TOO_MANY_TBS_RESOURCES + pub const TBS_TOO_MANY_RESOURCES: Self = Self(0x8028400A); + + /// Windows TBS error TBS_E_SERVICE_START_PENDING + pub const TBS_SERVICE_START_PENDING: Self = Self(0x8028400B); + + /// Windows TBS error TBS_E_PPI_NOT_SUPPORTED + pub const TBS_PPI_NOT_SUPPORTED: Self = Self(0x8028400C); + + /// Windows TBS error TBS_E_COMMAND_CANCELED + pub const TBS_COMMAND_CANCELED: Self = Self(0x8028400D); + + /// Windows TBS error TBS_E_BUFFER_TOO_LARGE + pub const TBS_BUFFER_TOO_LARGE: Self = Self(0x8028400E); + + /// Windows TBS error TBS_E_TPM_NOT_FOUND + pub const TBS_TPM_NOT_FOUND: Self = Self(0x8028400F); + + /// Windows TBS error TBS_E_SERVICE_DISABLED + pub const TBS_SERVICE_DISABLED: Self = Self(0x80284010); + + /// Windows TBS error TBS_E_ACCESS_DENIED + pub const TBS_ACCESS_DENIED: Self = Self(0x80284012); + + /// Windows TBS error TBS_E_PPI_FUNCTION_UNSUPPORTED + pub const TBS_PPI_FUNCTION_NOT_SUPPORTED: Self = Self(0x80284014); + + /// Windows TBS error TBS_E_OWNERAUTH_NOT_FOUND + pub const TBS_OWNER_AUTH_NOT_FOUND: Self = Self(0x80284015); + + pub fn try_from(value: u32) -> Result { + match value { + 0 => Ok(Self::H), // Original value: 0x000 + 30 => Ok(Self::BAD_TAG), // Original value: 0x01E + 256 => Ok(Self::_1), // Original value: 0x100 + 257 => Ok(Self::FAILURE), // Original value: RC_VER1.into() + 0x001 + 259 => Ok(Self::SEQUENCE), // Original value: RC_VER1.into() + 0x003 + 267 => Ok(Self::PRIVATE), // Original value: RC_VER1.into() + 0x00B + 281 => Ok(Self::HMAC), // Original value: RC_VER1.into() + 0x019 + 288 => Ok(Self::DISABLED), // Original value: RC_VER1.into() + 0x020 + 289 => Ok(Self::EXCLUSIVE), // Original value: RC_VER1.into() + 0x021 + 292 => Ok(Self::AUTH_TYPE), // Original value: RC_VER1.into() + 0x024 + 293 => Ok(Self::AUTH_MISSING), // Original value: RC_VER1.into() + 0x025 + 294 => Ok(Self::POLICY), // Original value: RC_VER1.into() + 0x026 + 295 => Ok(Self::PCR), // Original value: RC_VER1.into() + 0x027 + 296 => Ok(Self::PCR_CHANGED), // Original value: RC_VER1.into() + 0x028 + 301 => Ok(Self::UPGRADE), // Original value: RC_VER1.into() + 0x02D + 302 => Ok(Self::TOO_MANY_CONTEXTS), // Original value: RC_VER1.into() + 0x02E + 303 => Ok(Self::AUTH_UNAVAILABLE), // Original value: RC_VER1.into() + 0x02F + 304 => Ok(Self::REBOOT), // Original value: RC_VER1.into() + 0x030 + 305 => Ok(Self::UNBALANCED), // Original value: RC_VER1.into() + 0x031 + 322 => Ok(Self::COMMAND_SIZE), // Original value: RC_VER1.into() + 0x042 + 323 => Ok(Self::COMMAND_CODE), // Original value: RC_VER1.into() + 0x043 + 324 => Ok(Self::AUTHSIZE), // Original value: RC_VER1.into() + 0x044 + 325 => Ok(Self::AUTH_CONTEXT), // Original value: RC_VER1.into() + 0x045 + 326 => Ok(Self::NV_RANGE), // Original value: RC_VER1.into() + 0x046 + 327 => Ok(Self::NV_SIZE), // Original value: RC_VER1.into() + 0x047 + 328 => Ok(Self::NV_LOCKED), // Original value: RC_VER1.into() + 0x048 + 329 => Ok(Self::NV_AUTHORIZATION), // Original value: RC_VER1.into() + 0x049 + 330 => Ok(Self::NV_UNINITIALIZED), // Original value: RC_VER1.into() + 0x04A + 331 => Ok(Self::NV_SPACE), // Original value: RC_VER1.into() + 0x04B + 332 => Ok(Self::NV_DEFINED), // Original value: RC_VER1.into() + 0x04C + 336 => Ok(Self::BAD_CONTEXT), // Original value: RC_VER1.into() + 0x050 + 337 => Ok(Self::CPHASH), // Original value: RC_VER1.into() + 0x051 + 338 => Ok(Self::PARENT), // Original value: RC_VER1.into() + 0x052 + 339 => Ok(Self::NEEDS_TEST), // Original value: RC_VER1.into() + 0x053 + 340 => Ok(Self::NO_RESULT), // Original value: RC_VER1.into() + 0x054 + 341 => Ok(Self::SENSITIVE), // Original value: RC_VER1.into() + 0x055 + 383 => Ok(Self::RC_MAX_FM0), // Original value: RC_VER1.into() + 0x07F + 128 => Ok(Self::RC_FMT1), // Original value: 0x080 + 129 => Ok(Self::ASYMMETRIC), // Original value: RC_FMT1.into() + 0x001 + 130 => Ok(Self::ATTRIBUTES), // Original value: RC_FMT1.into() + 0x002 + 131 => Ok(Self::HASH), // Original value: RC_FMT1.into() + 0x003 + 132 => Ok(Self::VALUE), // Original value: RC_FMT1.into() + 0x004 + 133 => Ok(Self::HIERARCHY), // Original value: RC_FMT1.into() + 0x005 + 135 => Ok(Self::KEY_SIZE), // Original value: RC_FMT1.into() + 0x007 + 136 => Ok(Self::MGF), // Original value: RC_FMT1.into() + 0x008 + 137 => Ok(Self::MODE), // Original value: RC_FMT1.into() + 0x009 + 138 => Ok(Self::TYPE), // Original value: RC_FMT1.into() + 0x00A + 139 => Ok(Self::HANDLE), // Original value: RC_FMT1.into() + 0x00B + 140 => Ok(Self::KDF), // Original value: RC_FMT1.into() + 0x00C + 141 => Ok(Self::RANGE), // Original value: RC_FMT1.into() + 0x00D + 142 => Ok(Self::AUTH_FAIL), // Original value: RC_FMT1.into() + 0x00E + 143 => Ok(Self::NONCE), // Original value: RC_FMT1.into() + 0x00F + 144 => Ok(Self::PP), // Original value: RC_FMT1.into() + 0x010 + 146 => Ok(Self::SCHEME), // Original value: RC_FMT1.into() + 0x012 + 149 => Ok(Self::SIZE), // Original value: RC_FMT1.into() + 0x015 + 150 => Ok(Self::SYMMETRIC), // Original value: RC_FMT1.into() + 0x016 + 151 => Ok(Self::TAG), // Original value: RC_FMT1.into() + 0x017 + 152 => Ok(Self::SELECTOR), // Original value: RC_FMT1.into() + 0x018 + 154 => Ok(Self::INSUFFICIENT), // Original value: RC_FMT1.into() + 0x01A + 155 => Ok(Self::SIGNATURE), // Original value: RC_FMT1.into() + 0x01B + 156 => Ok(Self::KEY), // Original value: RC_FMT1.into() + 0x01C + 157 => Ok(Self::POLICY_FAIL), // Original value: RC_FMT1.into() + 0x01D + 159 => Ok(Self::INTEGRITY), // Original value: RC_FMT1.into() + 0x01F + 160 => Ok(Self::TICKET), // Original value: RC_FMT1.into() + 0x020 + 161 => Ok(Self::RESERVED_BITS), // Original value: RC_FMT1.into() + 0x021 + 162 => Ok(Self::BAD_AUTH), // Original value: RC_FMT1.into() + 0x022 + 163 => Ok(Self::EXPIRED), // Original value: RC_FMT1.into() + 0x023 + 164 => Ok(Self::POLICY_CC), // Original value: RC_FMT1.into() + 0x024 + 165 => Ok(Self::BINDING), // Original value: RC_FMT1.into() + 0x025 + 166 => Ok(Self::CURVE), // Original value: RC_FMT1.into() + 0x026 + 167 => Ok(Self::ECC_POINT), // Original value: RC_FMT1.into() + 0x027 + 2304 => Ok(Self::_9), // Original value: 0x900 + 2305 => Ok(Self::CONTEXT_GAP), // Original value: RC_WARN.into() + 0x001 + 2306 => Ok(Self::OBJECT_MEMORY), // Original value: RC_WARN.into() + 0x002 + 2307 => Ok(Self::SESSION_MEMORY), // Original value: RC_WARN.into() + 0x003 + 2308 => Ok(Self::MEMORY), // Original value: RC_WARN.into() + 0x004 + 2309 => Ok(Self::SESSION_HANDLES), // Original value: RC_WARN.into() + 0x005 + 2310 => Ok(Self::OBJECT_HANDLES), // Original value: RC_WARN.into() + 0x006 + 2311 => Ok(Self::LOCALITY), // Original value: RC_WARN.into() + 0x007 + 2312 => Ok(Self::YIELDED), // Original value: RC_WARN.into() + 0x008 + 2313 => Ok(Self::CANCELED), // Original value: RC_WARN.into() + 0x009 + 2314 => Ok(Self::TESTING), // Original value: RC_WARN.into() + 0x00A + 2320 => Ok(Self::REFERENCE_H0), // Original value: RC_WARN.into() + 0x010 + 2321 => Ok(Self::REFERENCE_H1), // Original value: RC_WARN.into() + 0x011 + 2322 => Ok(Self::REFERENCE_H2), // Original value: RC_WARN.into() + 0x012 + 2323 => Ok(Self::REFERENCE_H3), // Original value: RC_WARN.into() + 0x013 + 2324 => Ok(Self::REFERENCE_H4), // Original value: RC_WARN.into() + 0x014 + 2325 => Ok(Self::REFERENCE_H5), // Original value: RC_WARN.into() + 0x015 + 2326 => Ok(Self::REFERENCE_H6), // Original value: RC_WARN.into() + 0x016 + 2328 => Ok(Self::REFERENCE_S0), // Original value: RC_WARN.into() + 0x018 + 2329 => Ok(Self::REFERENCE_S1), // Original value: RC_WARN.into() + 0x019 + 2330 => Ok(Self::REFERENCE_S2), // Original value: RC_WARN.into() + 0x01A + 2331 => Ok(Self::REFERENCE_S3), // Original value: RC_WARN.into() + 0x01B + 2332 => Ok(Self::REFERENCE_S4), // Original value: RC_WARN.into() + 0x01C + 2333 => Ok(Self::REFERENCE_S5), // Original value: RC_WARN.into() + 0x01D + 2334 => Ok(Self::REFERENCE_S6), // Original value: RC_WARN.into() + 0x01E + 2336 => Ok(Self::NV_RATE), // Original value: RC_WARN.into() + 0x020 + 2337 => Ok(Self::LOCKOUT), // Original value: RC_WARN.into() + 0x021 + 2338 => Ok(Self::RETRY), // Original value: RC_WARN.into() + 0x022 + 2339 => Ok(Self::NV_UNAVAILABLE), // Original value: RC_WARN.into() + 0x023 + 2431 => Ok(Self::NOT_USED), // Original value: RC_WARN.into() + 0x7F + 64 => Ok(Self::P), // Original value: 0x040 + 2048 => Ok(Self::_8), // Original value: 0x800 + 512 => Ok(Self::_2), // Original value: 0x200 + 768 => Ok(Self::_3), // Original value: 0x300 + 1024 => Ok(Self::_4), // Original value: 0x400 + 1280 => Ok(Self::_5), // Original value: 0x500 + 1536 => Ok(Self::_6), // Original value: 0x600 + 1792 => Ok(Self::_7), // Original value: 0x700 + 2560 => Ok(Self::A), // Original value: 0xA00 + 2816 => Ok(Self::B), // Original value: 0xB00 + 3072 => Ok(Self::C), // Original value: 0xC00 + 3328 => Ok(Self::D), // Original value: 0xD00 + 3584 => Ok(Self::E), // Original value: 0xE00 + 3840 => Ok(Self::N_MASK), // Original value: 0xF00 + 1076363265 => Ok(Self::TSS_TCP_BAD_HANDSHAKE_RESP), // Original value: 0x40280001 + 1076363266 => Ok(Self::TSS_TCP_SERVER_TOO_OLD), // Original value: 0x40280002 + 1076363267 => Ok(Self::TSS_TCP_BAD_ACK), // Original value: 0x40280003 + 1076363268 => Ok(Self::TSS_TCP_BAD_RESP_LEN), // Original value: 0x40280004 + 1076363269 => Ok(Self::TSS_TCP_UNEXPECTED_STARTUP_RESP), // Original value: 0x40280005 + 1076363270 => Ok(Self::TSS_TCP_INVALID_SIZE_TAG), // Original value: 0x40280006 + 1076363271 => Ok(Self::TSS_TCP_DISCONNECTED), // Original value: 0x40280007 + 1076363280 => Ok(Self::TSS_DISPATCH_FAILED), // Original value: 0x40280010 + 1076363281 => Ok(Self::TSS_SEND_OP_FAILED), // Original value: 0x40280011 + 1076363297 => Ok(Self::TSS_RESP_BUF_TOO_SHORT), // Original value: 0x40280021 + 1076363298 => Ok(Self::TSS_RESP_BUF_INVALID_SESSION_TAG), // Original value: 0x40280022 + 1076363299 => Ok(Self::TSS_RESP_BUF_INVALID_SIZE), // Original value: 0x40280023 + 2150106112 => Ok(Self::TBS_COMMAND_BLOCKED), // Original value: 0x80280400 + 2150106113 => Ok(Self::TBS_INVALID_HANDLE), // Original value: 0x80280401 + 2150106114 => Ok(Self::TBS_DUPLICATE_V_HANDLE), // Original value: 0x80280402 + 2150106115 => Ok(Self::TBS_EMBEDDED_COMMAND_BLOCKED), // Original value: 0x80280403 + 2150106116 => Ok(Self::TBS_EMBEDDED_COMMAND_UNSUPPORTED), // Original value: 0x80280404 + 2150121472 => Ok(Self::TBS_UNKNOWN_ERROR), // Original value: 0x80284000 + 2150121473 => Ok(Self::TBS_INTERNAL_ERROR), // Original value: 0x80284001 + 2150121474 => Ok(Self::TBS_BAD_PARAMETER), // Original value: 0x80284002 + 2150121475 => Ok(Self::TBS_INVALID_OUTPUT_POINTER), // Original value: 0x80284003 + 2150121476 => Ok(Self::TBS_INVALID_CONTEXT), // Original value: 0x80284004 + 2150121477 => Ok(Self::TBS_INSUFFICIENT_BUFFER), // Original value: 0x80284005 + 2150121478 => Ok(Self::TBS_IO_ERROR), // Original value: 0x80284006 + 2150121479 => Ok(Self::TBS_INVALID_CONTEXT_PARAM), // Original value: 0x80284007 + 2150121480 => Ok(Self::TBS_SERVICE_NOT_RUNNING), // Original value: 0x80284008 + 2150121481 => Ok(Self::TBS_TOO_MANY_CONTEXTS), // Original value: 0x80284009 + 2150121482 => Ok(Self::TBS_TOO_MANY_RESOURCES), // Original value: 0x8028400A + 2150121483 => Ok(Self::TBS_SERVICE_START_PENDING), // Original value: 0x8028400B + 2150121484 => Ok(Self::TBS_PPI_NOT_SUPPORTED), // Original value: 0x8028400C + 2150121485 => Ok(Self::TBS_COMMAND_CANCELED), // Original value: 0x8028400D + 2150121486 => Ok(Self::TBS_BUFFER_TOO_LARGE), // Original value: 0x8028400E + 2150121487 => Ok(Self::TBS_TPM_NOT_FOUND), // Original value: 0x8028400F + 2150121488 => Ok(Self::TBS_SERVICE_DISABLED), // Original value: 0x80284010 + 2150121490 => Ok(Self::TBS_ACCESS_DENIED), // Original value: 0x80284012 + 2150121492 => Ok(Self::TBS_PPI_FUNCTION_NOT_SUPPORTED), // Original value: 0x80284014 + 2150121493 => Ok(Self::TBS_OWNER_AUTH_NOT_FOUND), // Original value: 0x80284015 + _ => Err(TpmError::InvalidEnumValue), + } + } +} + +impl TpmEnum for TPM_RC { + fn get_value(&self) -> u32 { + self.0.into() + } + + fn try_from_trait(value: u64) -> Result where Self: Sized { + TPM_RC::try_from(value as u32) + } + + fn new_from_trait(value: u64) -> Result where Self: Sized { + Ok(TPM_RC(value as u32)) + } +} + +impl From for u32 { + fn from(value: TPM_RC) -> Self { + value.0 as u32 + } +} + +impl From for i32 { + fn from(value: TPM_RC) -> Self { + value.0 as i32 + } +} + +impl fmt::Display for TPM_RC { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self.0 { + 0 => write!(f, "H"), + 30 => write!(f, "BAD_TAG"), + 256 => write!(f, "_1"), + 257 => write!(f, "FAILURE"), + 259 => write!(f, "SEQUENCE"), + 267 => write!(f, "PRIVATE"), + 281 => write!(f, "HMAC"), + 288 => write!(f, "DISABLED"), + 289 => write!(f, "EXCLUSIVE"), + 292 => write!(f, "AUTH_TYPE"), + 293 => write!(f, "AUTH_MISSING"), + 294 => write!(f, "POLICY"), + 295 => write!(f, "PCR"), + 296 => write!(f, "PCR_CHANGED"), + 301 => write!(f, "UPGRADE"), + 302 => write!(f, "TOO_MANY_CONTEXTS"), + 303 => write!(f, "AUTH_UNAVAILABLE"), + 304 => write!(f, "REBOOT"), + 305 => write!(f, "UNBALANCED"), + 322 => write!(f, "COMMAND_SIZE"), + 323 => write!(f, "COMMAND_CODE"), + 324 => write!(f, "AUTHSIZE"), + 325 => write!(f, "AUTH_CONTEXT"), + 326 => write!(f, "NV_RANGE"), + 327 => write!(f, "NV_SIZE"), + 328 => write!(f, "NV_LOCKED"), + 329 => write!(f, "NV_AUTHORIZATION"), + 330 => write!(f, "NV_UNINITIALIZED"), + 331 => write!(f, "NV_SPACE"), + 332 => write!(f, "NV_DEFINED"), + 336 => write!(f, "BAD_CONTEXT"), + 337 => write!(f, "CPHASH"), + 338 => write!(f, "PARENT"), + 339 => write!(f, "NEEDS_TEST"), + 340 => write!(f, "NO_RESULT"), + 341 => write!(f, "SENSITIVE"), + 383 => write!(f, "RC_MAX_FM0"), + 128 => write!(f, "RC_FMT1"), + 129 => write!(f, "ASYMMETRIC"), + 130 => write!(f, "ATTRIBUTES"), + 131 => write!(f, "HASH"), + 132 => write!(f, "VALUE"), + 133 => write!(f, "HIERARCHY"), + 135 => write!(f, "KEY_SIZE"), + 136 => write!(f, "MGF"), + 137 => write!(f, "MODE"), + 138 => write!(f, "TYPE"), + 139 => write!(f, "HANDLE"), + 140 => write!(f, "KDF"), + 141 => write!(f, "RANGE"), + 142 => write!(f, "AUTH_FAIL"), + 143 => write!(f, "NONCE"), + 144 => write!(f, "PP"), + 146 => write!(f, "SCHEME"), + 149 => write!(f, "SIZE"), + 150 => write!(f, "SYMMETRIC"), + 151 => write!(f, "TAG"), + 152 => write!(f, "SELECTOR"), + 154 => write!(f, "INSUFFICIENT"), + 155 => write!(f, "SIGNATURE"), + 156 => write!(f, "KEY"), + 157 => write!(f, "POLICY_FAIL"), + 159 => write!(f, "INTEGRITY"), + 160 => write!(f, "TICKET"), + 161 => write!(f, "RESERVED_BITS"), + 162 => write!(f, "BAD_AUTH"), + 163 => write!(f, "EXPIRED"), + 164 => write!(f, "POLICY_CC"), + 165 => write!(f, "BINDING"), + 166 => write!(f, "CURVE"), + 167 => write!(f, "ECC_POINT"), + 2304 => write!(f, "_9"), + 2305 => write!(f, "CONTEXT_GAP"), + 2306 => write!(f, "OBJECT_MEMORY"), + 2307 => write!(f, "SESSION_MEMORY"), + 2308 => write!(f, "MEMORY"), + 2309 => write!(f, "SESSION_HANDLES"), + 2310 => write!(f, "OBJECT_HANDLES"), + 2311 => write!(f, "LOCALITY"), + 2312 => write!(f, "YIELDED"), + 2313 => write!(f, "CANCELED"), + 2314 => write!(f, "TESTING"), + 2320 => write!(f, "REFERENCE_H0"), + 2321 => write!(f, "REFERENCE_H1"), + 2322 => write!(f, "REFERENCE_H2"), + 2323 => write!(f, "REFERENCE_H3"), + 2324 => write!(f, "REFERENCE_H4"), + 2325 => write!(f, "REFERENCE_H5"), + 2326 => write!(f, "REFERENCE_H6"), + 2328 => write!(f, "REFERENCE_S0"), + 2329 => write!(f, "REFERENCE_S1"), + 2330 => write!(f, "REFERENCE_S2"), + 2331 => write!(f, "REFERENCE_S3"), + 2332 => write!(f, "REFERENCE_S4"), + 2333 => write!(f, "REFERENCE_S5"), + 2334 => write!(f, "REFERENCE_S6"), + 2336 => write!(f, "NV_RATE"), + 2337 => write!(f, "LOCKOUT"), + 2338 => write!(f, "RETRY"), + 2339 => write!(f, "NV_UNAVAILABLE"), + 2431 => write!(f, "NOT_USED"), + 64 => write!(f, "P"), + 2048 => write!(f, "_8"), + 512 => write!(f, "_2"), + 768 => write!(f, "_3"), + 1024 => write!(f, "_4"), + 1280 => write!(f, "_5"), + 1536 => write!(f, "_6"), + 1792 => write!(f, "_7"), + 2560 => write!(f, "A"), + 2816 => write!(f, "B"), + 3072 => write!(f, "C"), + 3328 => write!(f, "D"), + 3584 => write!(f, "E"), + 3840 => write!(f, "N_MASK"), + 1076363265 => write!(f, "TSS_TCP_BAD_HANDSHAKE_RESP"), + 1076363266 => write!(f, "TSS_TCP_SERVER_TOO_OLD"), + 1076363267 => write!(f, "TSS_TCP_BAD_ACK"), + 1076363268 => write!(f, "TSS_TCP_BAD_RESP_LEN"), + 1076363269 => write!(f, "TSS_TCP_UNEXPECTED_STARTUP_RESP"), + 1076363270 => write!(f, "TSS_TCP_INVALID_SIZE_TAG"), + 1076363271 => write!(f, "TSS_TCP_DISCONNECTED"), + 1076363280 => write!(f, "TSS_DISPATCH_FAILED"), + 1076363281 => write!(f, "TSS_SEND_OP_FAILED"), + 1076363297 => write!(f, "TSS_RESP_BUF_TOO_SHORT"), + 1076363298 => write!(f, "TSS_RESP_BUF_INVALID_SESSION_TAG"), + 1076363299 => write!(f, "TSS_RESP_BUF_INVALID_SIZE"), + 2150106112 => write!(f, "TBS_COMMAND_BLOCKED"), + 2150106113 => write!(f, "TBS_INVALID_HANDLE"), + 2150106114 => write!(f, "TBS_DUPLICATE_V_HANDLE"), + 2150106115 => write!(f, "TBS_EMBEDDED_COMMAND_BLOCKED"), + 2150106116 => write!(f, "TBS_EMBEDDED_COMMAND_UNSUPPORTED"), + 2150121472 => write!(f, "TBS_UNKNOWN_ERROR"), + 2150121473 => write!(f, "TBS_INTERNAL_ERROR"), + 2150121474 => write!(f, "TBS_BAD_PARAMETER"), + 2150121475 => write!(f, "TBS_INVALID_OUTPUT_POINTER"), + 2150121476 => write!(f, "TBS_INVALID_CONTEXT"), + 2150121477 => write!(f, "TBS_INSUFFICIENT_BUFFER"), + 2150121478 => write!(f, "TBS_IO_ERROR"), + 2150121479 => write!(f, "TBS_INVALID_CONTEXT_PARAM"), + 2150121480 => write!(f, "TBS_SERVICE_NOT_RUNNING"), + 2150121481 => write!(f, "TBS_TOO_MANY_CONTEXTS"), + 2150121482 => write!(f, "TBS_TOO_MANY_RESOURCES"), + 2150121483 => write!(f, "TBS_SERVICE_START_PENDING"), + 2150121484 => write!(f, "TBS_PPI_NOT_SUPPORTED"), + 2150121485 => write!(f, "TBS_COMMAND_CANCELED"), + 2150121486 => write!(f, "TBS_BUFFER_TOO_LARGE"), + 2150121487 => write!(f, "TBS_TPM_NOT_FOUND"), + 2150121488 => write!(f, "TBS_SERVICE_DISABLED"), + 2150121490 => write!(f, "TBS_ACCESS_DENIED"), + 2150121492 => write!(f, "TBS_PPI_FUNCTION_NOT_SUPPORTED"), + 2150121493 => write!(f, "TBS_OWNER_AUTH_NOT_FOUND"), + _ => write!(f, "{}", enum_to_str(self.0 as u64, std::any::TypeId::of::())), + } + } +} + +/// A TPM_CLOCK_ADJUST value is used to change the rate at which the TPM internal +/// oscillator is divided. A change to the divider will change the rate at which Clock and +/// Time change. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)] +pub struct TPM_CLOCK_ADJUST(pub i8); + +impl TPM_CLOCK_ADJUST { + /// Slow the Clock update rate by one coarse adjustment step. + pub const COARSE_SLOWER: Self = Self(-3); + + /// Slow the Clock update rate by one medium adjustment step. + pub const MEDIUM_SLOWER: Self = Self(-2); + + /// Slow the Clock update rate by one fine adjustment step. + pub const FINE_SLOWER: Self = Self(-1); + + /// No change to the Clock update rate. + pub const NO_CHANGE: Self = Self(0); + + /// Speed the Clock update rate by one fine adjustment step. + pub const FINE_FASTER: Self = Self(1); + + /// Speed the Clock update rate by one medium adjustment step. + pub const MEDIUM_FASTER: Self = Self(2); + + /// Speed the Clock update rate by one coarse adjustment step. + pub const COARSE_FASTER: Self = Self(3); + + pub fn try_from(value: i8) -> Result { + match value { + -3 => Ok(Self::COARSE_SLOWER), // Original value: -3 + -2 => Ok(Self::MEDIUM_SLOWER), // Original value: -2 + -1 => Ok(Self::FINE_SLOWER), // Original value: -1 + 0 => Ok(Self::NO_CHANGE), // Original value: 0 + 1 => Ok(Self::FINE_FASTER), // Original value: 1 + 2 => Ok(Self::MEDIUM_FASTER), // Original value: 2 + 3 => Ok(Self::COARSE_FASTER), // Original value: 3 + _ => Err(TpmError::InvalidEnumValue), + } + } +} + +impl TpmEnum for TPM_CLOCK_ADJUST { + fn get_value(&self) -> i8 { + self.0.into() + } + + fn try_from_trait(value: u64) -> Result where Self: Sized { + TPM_CLOCK_ADJUST::try_from(value as i8) + } + + fn new_from_trait(value: u64) -> Result where Self: Sized { + Ok(TPM_CLOCK_ADJUST(value as i8)) + } +} + +impl From for u8 { + fn from(value: TPM_CLOCK_ADJUST) -> Self { + value.0 as u8 + } +} + +impl From for i8 { + fn from(value: TPM_CLOCK_ADJUST) -> Self { + value.0 as i8 + } +} + +impl fmt::Display for TPM_CLOCK_ADJUST { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self.0 { + -3 => write!(f, "COARSE_SLOWER"), + -2 => write!(f, "MEDIUM_SLOWER"), + -1 => write!(f, "FINE_SLOWER"), + 0 => write!(f, "NO_CHANGE"), + 1 => write!(f, "FINE_FASTER"), + 2 => write!(f, "MEDIUM_FASTER"), + 3 => write!(f, "COARSE_FASTER"), + _ => write!(f, "{}", enum_to_str(self.0 as u64, std::any::TypeId::of::())), + } + } +} + +/// Table 18 Definition of (UINT16) TPM_EO Constants [IN/OUT] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)] +pub struct TPM_EO(pub u16); + +impl TPM_EO { + /// A = B + pub const EQ: Self = Self(0x0); // Original value: 0x0000 + + /// A B + pub const NEQ: Self = Self(0x1); // Original value: 0x0001 + + /// A ˃ B signed + pub const SIGNED_GT: Self = Self(0x2); // Original value: 0x0002 + + /// A ˃ B unsigned + pub const UNSIGNED_GT: Self = Self(0x3); // Original value: 0x0003 + + /// A ˂ B signed + pub const SIGNED_LT: Self = Self(0x4); // Original value: 0x0004 + + /// A ˂ B unsigned + pub const UNSIGNED_LT: Self = Self(0x5); // Original value: 0x0005 + + /// A B signed + pub const SIGNED_GE: Self = Self(0x6); // Original value: 0x0006 + + /// A B unsigned + pub const UNSIGNED_GE: Self = Self(0x7); // Original value: 0x0007 + + /// A B signed + pub const SIGNED_LE: Self = Self(0x8); // Original value: 0x0008 + + /// A B unsigned + pub const UNSIGNED_LE: Self = Self(0x9); // Original value: 0x0009 + + /// All bits SET in B are SET in A. ((A∧B)=B) + pub const BITSET: Self = Self(0xA); // Original value: 0x000A + + /// All bits SET in B are CLEAR in A. ((A∧B)=0) + pub const BITCLEAR: Self = Self(0xB); // Original value: 0x000B + + pub fn try_from(value: u16) -> Result { + match value { + 0 => Ok(Self::EQ), // Original value: 0x0000 + 1 => Ok(Self::NEQ), // Original value: 0x0001 + 2 => Ok(Self::SIGNED_GT), // Original value: 0x0002 + 3 => Ok(Self::UNSIGNED_GT), // Original value: 0x0003 + 4 => Ok(Self::SIGNED_LT), // Original value: 0x0004 + 5 => Ok(Self::UNSIGNED_LT), // Original value: 0x0005 + 6 => Ok(Self::SIGNED_GE), // Original value: 0x0006 + 7 => Ok(Self::UNSIGNED_GE), // Original value: 0x0007 + 8 => Ok(Self::SIGNED_LE), // Original value: 0x0008 + 9 => Ok(Self::UNSIGNED_LE), // Original value: 0x0009 + 10 => Ok(Self::BITSET), // Original value: 0x000A + 11 => Ok(Self::BITCLEAR), // Original value: 0x000B + _ => Err(TpmError::InvalidEnumValue), + } + } +} + +impl TpmEnum for TPM_EO { + fn get_value(&self) -> u16 { + self.0.into() + } + + fn try_from_trait(value: u64) -> Result where Self: Sized { + TPM_EO::try_from(value as u16) + } + + fn new_from_trait(value: u64) -> Result where Self: Sized { + Ok(TPM_EO(value as u16)) + } +} + +impl From for u16 { + fn from(value: TPM_EO) -> Self { + value.0 as u16 + } +} + +impl From for i16 { + fn from(value: TPM_EO) -> Self { + value.0 as i16 + } +} + +impl fmt::Display for TPM_EO { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self.0 { + 0 => write!(f, "EQ"), + 1 => write!(f, "NEQ"), + 2 => write!(f, "SIGNED_GT"), + 3 => write!(f, "UNSIGNED_GT"), + 4 => write!(f, "SIGNED_LT"), + 5 => write!(f, "UNSIGNED_LT"), + 6 => write!(f, "SIGNED_GE"), + 7 => write!(f, "UNSIGNED_GE"), + 8 => write!(f, "SIGNED_LE"), + 9 => write!(f, "UNSIGNED_LE"), + 10 => write!(f, "BITSET"), + 11 => write!(f, "BITCLEAR"), + _ => write!(f, "{}", enum_to_str(self.0 as u64, std::any::TypeId::of::())), + } + } +} + +/// Structure tags are used to disambiguate structures. They are 16-bit values with the +/// most significant bit SET so that they do not overlap TPM_ALG_ID values. A single +/// exception is made for the value associated with TPM_ST_RSP_COMMAND (0x00C4), which has +/// the same value as the TPM_TAG_RSP_COMMAND tag from earlier versions of this +/// specification. This value is used when the TPM is compatible with a previous TPM +/// specification and the TPM cannot determine which family of response code to return +/// because the command tag is not valid. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)] +pub struct TPM_ST(pub u16); + +impl TPM_ST { + /// Tag value for a response; used when there is an error in the tag. This is also the + /// value returned from a TPM 1.2 when an error occurs. This value is used in this + /// specification because an error in the command tag may prevent determination of the + /// family. When this tag is used in the response, the response code will be + /// TPM_RC_BAD_TAG (0 1E16), which has the same numeric value as the TPM 1.2 response code + /// for TPM_BADTAG. + /// NOTE In a previously published version of this specification, TPM_RC_BAD_TAG was + /// incorrectly assigned a value of 0x030 instead of 30 (0x01e). Some implementations my + /// return the old value instead of the new value. + pub const RSP_COMMAND: Self = Self(0xC4); // Original value: 0x00C4 + + /// No structure type specified + pub const NULL: Self = Self(0x8000); // Original value: 0X8000 + + /// Tag value for a command/response for a command defined in this specification; + /// indicating that the command/response has no attached sessions and no + /// authorizationSize/parameterSize value is present + /// If the responseCode from the TPM is not TPM_RC_SUCCESS, then the response tag shall + /// have this value. + pub const NO_SESSIONS: Self = Self(0x8001); + + /// Tag value for a command/response for a command defined in this specification; + /// indicating that the command/response has one or more attached sessions and the + /// authorizationSize/parameterSize field is present + pub const SESSIONS: Self = Self(0x8002); + + /// Tag for an attestation structure + pub const ATTEST_NV: Self = Self(0x8014); + + /// Tag for an attestation structure + pub const ATTEST_COMMAND_AUDIT: Self = Self(0x8015); + + /// Tag for an attestation structure + pub const ATTEST_SESSION_AUDIT: Self = Self(0x8016); + + /// Tag for an attestation structure + pub const ATTEST_CERTIFY: Self = Self(0x8017); + + /// Tag for an attestation structure + pub const ATTEST_QUOTE: Self = Self(0x8018); + + /// Tag for an attestation structure + pub const ATTEST_TIME: Self = Self(0x8019); + + /// Tag for an attestation structure + pub const ATTEST_CREATION: Self = Self(0x801A); + + /// Tag for an attestation structure + pub const ATTEST_NV_DIGEST: Self = Self(0x801C); + + /// Tag for a ticket type + pub const CREATION: Self = Self(0x8021); + + /// Tag for a ticket type + pub const VERIFIED: Self = Self(0x8022); + + /// Tag for a ticket type + pub const AUTH_SECRET: Self = Self(0x8023); + + /// Tag for a ticket type + pub const HASHCHECK: Self = Self(0x8024); + + /// Tag for a ticket type + pub const AUTH_SIGNED: Self = Self(0x8025); + + /// Tag for a structure describing a Field Upgrade Policy + pub const FU_MANIFEST: Self = Self(0x8029); + + pub fn try_from(value: u16) -> Result { + match value { + 196 => Ok(Self::RSP_COMMAND), // Original value: 0x00C4 + 32768 => Ok(Self::NULL), // Original value: 0X8000 + 32769 => Ok(Self::NO_SESSIONS), // Original value: 0x8001 + 32770 => Ok(Self::SESSIONS), // Original value: 0x8002 + 32788 => Ok(Self::ATTEST_NV), // Original value: 0x8014 + 32789 => Ok(Self::ATTEST_COMMAND_AUDIT), // Original value: 0x8015 + 32790 => Ok(Self::ATTEST_SESSION_AUDIT), // Original value: 0x8016 + 32791 => Ok(Self::ATTEST_CERTIFY), // Original value: 0x8017 + 32792 => Ok(Self::ATTEST_QUOTE), // Original value: 0x8018 + 32793 => Ok(Self::ATTEST_TIME), // Original value: 0x8019 + 32794 => Ok(Self::ATTEST_CREATION), // Original value: 0x801A + 32796 => Ok(Self::ATTEST_NV_DIGEST), // Original value: 0x801C + 32801 => Ok(Self::CREATION), // Original value: 0x8021 + 32802 => Ok(Self::VERIFIED), // Original value: 0x8022 + 32803 => Ok(Self::AUTH_SECRET), // Original value: 0x8023 + 32804 => Ok(Self::HASHCHECK), // Original value: 0x8024 + 32805 => Ok(Self::AUTH_SIGNED), // Original value: 0x8025 + 32809 => Ok(Self::FU_MANIFEST), // Original value: 0x8029 + _ => Err(TpmError::InvalidEnumValue), + } + } +} + +impl TpmEnum for TPM_ST { + fn get_value(&self) -> u16 { + self.0.into() + } + + fn try_from_trait(value: u64) -> Result where Self: Sized { + TPM_ST::try_from(value as u16) + } + + fn new_from_trait(value: u64) -> Result where Self: Sized { + Ok(TPM_ST(value as u16)) + } +} + +impl From for u16 { + fn from(value: TPM_ST) -> Self { + value.0 as u16 + } +} + +impl From for i16 { + fn from(value: TPM_ST) -> Self { + value.0 as i16 + } +} + +impl fmt::Display for TPM_ST { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self.0 { + 196 => write!(f, "RSP_COMMAND"), + 32768 => write!(f, "NULL"), + 32769 => write!(f, "NO_SESSIONS"), + 32770 => write!(f, "SESSIONS"), + 32788 => write!(f, "ATTEST_NV"), + 32789 => write!(f, "ATTEST_COMMAND_AUDIT"), + 32790 => write!(f, "ATTEST_SESSION_AUDIT"), + 32791 => write!(f, "ATTEST_CERTIFY"), + 32792 => write!(f, "ATTEST_QUOTE"), + 32793 => write!(f, "ATTEST_TIME"), + 32794 => write!(f, "ATTEST_CREATION"), + 32796 => write!(f, "ATTEST_NV_DIGEST"), + 32801 => write!(f, "CREATION"), + 32802 => write!(f, "VERIFIED"), + 32803 => write!(f, "AUTH_SECRET"), + 32804 => write!(f, "HASHCHECK"), + 32805 => write!(f, "AUTH_SIGNED"), + 32809 => write!(f, "FU_MANIFEST"), + _ => write!(f, "{}", enum_to_str(self.0 as u64, std::any::TypeId::of::())), + } + } +} + +/// These values are used in TPM2_Startup() to indicate the shutdown and startup mode. The +/// defined startup sequences are: +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)] +pub struct TPM_SU(pub u16); + +impl TPM_SU { + /// On TPM2_Shutdown(), indicates that the TPM should prepare for loss of power and save + /// state required for an orderly startup (TPM Reset). + /// on TPM2_Startup(), indicates that the TPM should perform TPM Reset or TPM Restart + pub const CLEAR: Self = Self(0x0); // Original value: 0x0000 + + /// On TPM2_Shutdown(), indicates that the TPM should prepare for loss of power and save + /// state required for an orderly startup (TPM Restart or TPM Resume) + /// on TPM2_Startup(), indicates that the TPM should restore the state saved by + /// TPM2_Shutdown(TPM_SU_STATE) + pub const STATE: Self = Self(0x1); // Original value: 0x0001 + + pub fn try_from(value: u16) -> Result { + match value { + 0 => Ok(Self::CLEAR), // Original value: 0x0000 + 1 => Ok(Self::STATE), // Original value: 0x0001 + _ => Err(TpmError::InvalidEnumValue), + } + } +} + +impl TpmEnum for TPM_SU { + fn get_value(&self) -> u16 { + self.0.into() + } + + fn try_from_trait(value: u64) -> Result where Self: Sized { + TPM_SU::try_from(value as u16) + } + + fn new_from_trait(value: u64) -> Result where Self: Sized { + Ok(TPM_SU(value as u16)) + } +} + +impl From for u16 { + fn from(value: TPM_SU) -> Self { + value.0 as u16 + } +} + +impl From for i16 { + fn from(value: TPM_SU) -> Self { + value.0 as i16 + } +} + +impl fmt::Display for TPM_SU { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self.0 { + 0 => write!(f, "CLEAR"), + 1 => write!(f, "STATE"), + _ => write!(f, "{}", enum_to_str(self.0 as u64, std::any::TypeId::of::())), + } + } +} + +/// This type is used in TPM2_StartAuthSession() to indicate the type of the session to be +/// created. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)] +pub struct TPM_SE(pub u8); + +impl TPM_SE { + pub const HMAC: Self = Self(0x0); // Original value: 0x00 + pub const POLICY: Self = Self(0x1); // Original value: 0x01 + + /// The policy session is being used to compute the policyHash and not for command authorization. + /// This setting modifies some policy commands and prevents session from being used to + /// authorize a command. + pub const TRIAL: Self = Self(0x3); // Original value: 0x03 + + pub fn try_from(value: u8) -> Result { + match value { + 0 => Ok(Self::HMAC), // Original value: 0x00 + 1 => Ok(Self::POLICY), // Original value: 0x01 + 3 => Ok(Self::TRIAL), // Original value: 0x03 + _ => Err(TpmError::InvalidEnumValue), + } + } +} + +impl TpmEnum for TPM_SE { + fn get_value(&self) -> u8 { + self.0.into() + } + + fn try_from_trait(value: u64) -> Result where Self: Sized { + TPM_SE::try_from(value as u8) + } + + fn new_from_trait(value: u64) -> Result where Self: Sized { + Ok(TPM_SE(value as u8)) + } +} + +impl From for u8 { + fn from(value: TPM_SE) -> Self { + value.0 as u8 + } +} + +impl From for i8 { + fn from(value: TPM_SE) -> Self { + value.0 as i8 + } +} + +impl fmt::Display for TPM_SE { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self.0 { + 0 => write!(f, "HMAC"), + 1 => write!(f, "POLICY"), + 3 => write!(f, "TRIAL"), + _ => write!(f, "{}", enum_to_str(self.0 as u64, std::any::TypeId::of::())), + } + } +} + +/// The TPM_CAP values are used in TPM2_GetCapability() to select the type of the value to +/// be returned. The format of the response varies according to the type of the value. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)] +pub struct TPM_CAP(pub u32); + +impl TPM_CAP { + pub const FIRST: Self = Self(0x0); // Original value: 0x00000000 + + /// TPML_ALG_PROPERTY + pub const ALGS: Self = Self(0x0); // Original value: 0x00000000 + + /// TPML_HANDLE + pub const HANDLES: Self = Self(0x1); // Original value: 0x00000001 + + /// TPML_CCA + pub const COMMANDS: Self = Self(0x2); // Original value: 0x00000002 + + /// TPML_CC + pub const PP_COMMANDS: Self = Self(0x3); // Original value: 0x00000003 + + /// TPML_CC + pub const AUDIT_COMMANDS: Self = Self(0x4); // Original value: 0x00000004 + + /// TPML_PCR_SELECTION + pub const PCRS: Self = Self(0x5); // Original value: 0x00000005 + + /// TPML_TAGGED_TPM_PROPERTY + pub const TPM_PROPERTIES: Self = Self(0x6); // Original value: 0x00000006 + + /// TPML_TAGGED_PCR_PROPERTY + pub const PCR_PROPERTIES: Self = Self(0x7); // Original value: 0x00000007 + + /// TPML_ECC_CURVE + pub const ECC_CURVES: Self = Self(0x8); // Original value: 0x00000008 + + /// TPML_TAGGED_POLICY + pub const AUTH_POLICIES: Self = Self(0x9); // Original value: 0x00000009 + + /// TPML_ACT_DATA + pub const ACT: Self = Self(0xA); // Original value: 0x0000000A + pub const LAST: Self = Self(0xA); // Original value: 0x0000000A + + /// Manufacturer-specific values + pub const VENDOR_PROPERTY: Self = Self(0x100); // Original value: 0x00000100 + + pub fn try_from(value: u32) -> Result { + match value { + 0 => Ok(Self::ALGS), // Original value: 0x00000000 + 1 => Ok(Self::HANDLES), // Original value: 0x00000001 + 2 => Ok(Self::COMMANDS), // Original value: 0x00000002 + 3 => Ok(Self::PP_COMMANDS), // Original value: 0x00000003 + 4 => Ok(Self::AUDIT_COMMANDS), // Original value: 0x00000004 + 5 => Ok(Self::PCRS), // Original value: 0x00000005 + 6 => Ok(Self::TPM_PROPERTIES), // Original value: 0x00000006 + 7 => Ok(Self::PCR_PROPERTIES), // Original value: 0x00000007 + 8 => Ok(Self::ECC_CURVES), // Original value: 0x00000008 + 9 => Ok(Self::AUTH_POLICIES), // Original value: 0x00000009 + 10 => Ok(Self::LAST), // Original value: 0x0000000A + 256 => Ok(Self::VENDOR_PROPERTY), // Original value: 0x00000100 + _ => Err(TpmError::InvalidEnumValue), + } + } +} + +impl TpmEnum for TPM_CAP { + fn get_value(&self) -> u32 { + self.0.into() + } + + fn try_from_trait(value: u64) -> Result where Self: Sized { + TPM_CAP::try_from(value as u32) + } + + fn new_from_trait(value: u64) -> Result where Self: Sized { + Ok(TPM_CAP(value as u32)) + } +} + +impl From for u32 { + fn from(value: TPM_CAP) -> Self { + value.0 as u32 + } +} + +impl From for i32 { + fn from(value: TPM_CAP) -> Self { + value.0 as i32 + } +} + +impl fmt::Display for TPM_CAP { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self.0 { + 0 => write!(f, "ALGS"), + 1 => write!(f, "HANDLES"), + 2 => write!(f, "COMMANDS"), + 3 => write!(f, "PP_COMMANDS"), + 4 => write!(f, "AUDIT_COMMANDS"), + 5 => write!(f, "PCRS"), + 6 => write!(f, "TPM_PROPERTIES"), + 7 => write!(f, "PCR_PROPERTIES"), + 8 => write!(f, "ECC_CURVES"), + 9 => write!(f, "AUTH_POLICIES"), + 10 => write!(f, "LAST"), + 256 => write!(f, "VENDOR_PROPERTY"), + _ => write!(f, "{}", enum_to_str(self.0 as u64, std::any::TypeId::of::())), + } + } +} + +/// The TPM_PT constants are used in TPM2_GetCapability(capability = +/// TPM_CAP_TPM_PROPERTIES) to indicate the property being selected or returned. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)] +pub struct TPM_PT(pub u32); + +impl TPM_PT { + /// Indicates no property type + pub const NONE: Self = Self(0x0); // Original value: 0x00000000 + + /// The number of properties in each group. + /// NOTE The first group with any properties is group 1 (PT_GROUP * 1). Group 0 is reserved. + pub const PT_GROUP: Self = Self(0x100); // Original value: 0x00000100 + + /// The group of fixed properties returned as TPMS_TAGGED_PROPERTY + /// The values in this group are only changed due to a firmware change in the TPM. + pub const PT_FIXED: Self = Self(0x100); // Original value: PT_GROUP.into() * 1 + + /// A 4-octet character string containing the TPM Family value (TPM_SPEC_FAMILY) + pub const FAMILY_INDICATOR: Self = Self(0x100); // Original value: PT_FIXED.into() + 0 + + /// The level of the specification + /// NOTE 1 For this specification, the level is zero. + /// NOTE 2 The level is on the title page of the specification. + pub const LEVEL: Self = Self(0x101); // Original value: PT_FIXED.into() + 1 + + /// The specification Revision times 100 + /// EXAMPLE Revision 01.01 would have a value of 101. + /// NOTE The Revision value is on the title page of the specification. + pub const REVISION: Self = Self(0x102); // Original value: PT_FIXED.into() + 2 + + /// The specification day of year using TCG calendar + /// EXAMPLE November 15, 2010, has a day of year value of 319 (0000013F16). + /// NOTE The specification date is on the title page of the specification or errata (see 6.1). + pub const DAY_OF_YEAR: Self = Self(0x103); // Original value: PT_FIXED.into() + 3 + + /// The specification year using the CE + /// EXAMPLE The year 2010 has a value of 000007DA16. + /// NOTE The specification date is on the title page of the specification or errata (see 6.1). + pub const YEAR: Self = Self(0x104); // Original value: PT_FIXED.into() + 4 + + /// The vendor ID unique to each TPM manufacturer + pub const MANUFACTURER: Self = Self(0x105); // Original value: PT_FIXED.into() + 5 + + /// The first four characters of the vendor ID string + /// NOTE When the vendor string is fewer than 16 octets, the additional property values do + /// not have to be present. A vendor string of 4 octets can be represented in one 32-bit + /// value and no null terminating character is required. + pub const VENDOR_STRING_1: Self = Self(0x106); // Original value: PT_FIXED.into() + 6 + + /// The second four characters of the vendor ID string + pub const VENDOR_STRING_2: Self = Self(0x107); // Original value: PT_FIXED.into() + 7 + + /// The third four characters of the vendor ID string + pub const VENDOR_STRING_3: Self = Self(0x108); // Original value: PT_FIXED.into() + 8 + + /// The fourth four characters of the vendor ID sting + pub const VENDOR_STRING_4: Self = Self(0x109); // Original value: PT_FIXED.into() + 9 + + /// Vendor-defined value indicating the TPM model + pub const VENDOR_TPM_TYPE: Self = Self(0x10A); // Original value: PT_FIXED.into() + 10 + + /// The most-significant 32 bits of a TPM vendor-specific value indicating the version + /// number of the firmware. See 10.12.2 and 10.12.12. + pub const FIRMWARE_VERSION_1: Self = Self(0x10B); // Original value: PT_FIXED.into() + 11 + + /// The least-significant 32 bits of a TPM vendor-specific value indicating the version + /// number of the firmware. See 10.12.2 and 10.12.12. + pub const FIRMWARE_VERSION_2: Self = Self(0x10C); // Original value: PT_FIXED.into() + 12 + + /// The maximum size of a parameter (typically, a TPM2B_MAX_BUFFER) + pub const INPUT_BUFFER: Self = Self(0x10D); // Original value: PT_FIXED.into() + 13 + + /// The minimum number of transient objects that can be held in TPM RAM + /// NOTE This minimum shall be no less than the minimum value required by the + /// platform-specific specification to which the TPM is built. + pub const HR_TRANSIENT_MIN: Self = Self(0x10E); // Original value: PT_FIXED.into() + 14 + + /// The minimum number of persistent objects that can be held in TPM NV memory + /// NOTE This minimum shall be no less than the minimum value required by the + /// platform-specific specification to which the TPM is built. + pub const HR_PERSISTENT_MIN: Self = Self(0x10F); // Original value: PT_FIXED.into() + 15 + + /// The minimum number of authorization sessions that can be held in TPM RAM + /// NOTE This minimum shall be no less than the minimum value required by the + /// platform-specific specification to which the TPM is built. + pub const HR_LOADED_MIN: Self = Self(0x110); // Original value: PT_FIXED.into() + 16 + + /// The number of authorization sessions that may be active at a time + /// A session is active when it has a context associated with its handle. The context may + /// either be in TPM RAM or be context saved. + /// NOTE This value shall be no less than the minimum value required by the + /// platform-specific specification to which the TPM is built. + pub const ACTIVE_SESSIONS_MAX: Self = Self(0x111); // Original value: PT_FIXED.into() + 17 + + /// The number of PCR implemented + /// NOTE This number is determined by the defined attributes, not the number of PCR that + /// are populated. + pub const PCR_COUNT: Self = Self(0x112); // Original value: PT_FIXED.into() + 18 + + /// The minimum number of octets in a TPMS_PCR_SELECT.sizeOfSelect + /// NOTE This value is not determined by the number of PCR implemented but by the number + /// of PCR required by the platform-specific specification with which the TPM is compliant + /// or by the implementer if not adhering to a platform-specific specification. + pub const PCR_SELECT_MIN: Self = Self(0x113); // Original value: PT_FIXED.into() + 19 + + /// The maximum allowed difference (unsigned) between the contextID values of two saved + /// session contexts + /// This value shall be 2n-1, where n is at least 16. + pub const CONTEXT_GAP_MAX: Self = Self(0x114); // Original value: PT_FIXED.into() + 20 + + /// The maximum number of NV Indexes that are allowed to have the TPM_NT_COUNTER attribute + /// NOTE 1 It is allowed for this value to be larger than the number of NV Indexes that + /// can be defined. This would be indicative of a TPM implementation that did not use + /// different implementation technology for different NV Index types. + /// NOTE 2 The value zero indicates that there is no fixed maximum. The number of counter + /// indexes is determined by the available NV memory pool. + pub const NV_COUNTERS_MAX: Self = Self(0x116); // Original value: PT_FIXED.into() + 22 + + /// The maximum size of an NV Index data area + pub const NV_INDEX_MAX: Self = Self(0x117); // Original value: PT_FIXED.into() + 23 + + /// A TPMA_MEMORY indicating the memory management method for the TPM + pub const MEMORY: Self = Self(0x118); // Original value: PT_FIXED.into() + 24 + + /// Interval, in milliseconds, between updates to the copy of TPMS_CLOCK_INFO.clock in NV + pub const CLOCK_UPDATE: Self = Self(0x119); // Original value: PT_FIXED.into() + 25 + + /// The algorithm used for the integrity HMAC on saved contexts and for hashing the fuData + /// of TPM2_FirmwareRead() + pub const CONTEXT_HASH: Self = Self(0x11A); // Original value: PT_FIXED.into() + 26 + + /// TPM_ALG_ID, the algorithm used for encryption of saved contexts + pub const CONTEXT_SYM: Self = Self(0x11B); // Original value: PT_FIXED.into() + 27 + + /// TPM_KEY_BITS, the size of the key used for encryption of saved contexts + pub const CONTEXT_SYM_SIZE: Self = Self(0x11C); // Original value: PT_FIXED.into() + 28 + + /// The modulus - 1 of the count for NV update of an orderly counter + /// The returned value is MAX_ORDERLY_COUNT. + /// This will have a value of 2N 1 where 1 N 32 + /// NOTE 1 An orderly counter is an NV Index with an TPM_NT of TPM_NV_COUNTER and + /// TPMA_NV_ORDERLY SET. + /// NOTE 2 When the low-order bits of a counter equal this value, an NV write occurs on + /// the next increment. + pub const ORDERLY_COUNT: Self = Self(0x11D); // Original value: PT_FIXED.into() + 29 + + /// The maximum value for commandSize in a command + pub const MAX_COMMAND_SIZE: Self = Self(0x11E); // Original value: PT_FIXED.into() + 30 + + /// The maximum value for responseSize in a response + pub const MAX_RESPONSE_SIZE: Self = Self(0x11F); // Original value: PT_FIXED.into() + 31 + + /// The maximum size of a digest that can be produced by the TPM + pub const MAX_DIGEST: Self = Self(0x120); // Original value: PT_FIXED.into() + 32 + + /// The maximum size of an object context that will be returned by TPM2_ContextSave + pub const MAX_OBJECT_CONTEXT: Self = Self(0x121); // Original value: PT_FIXED.into() + 33 + + /// The maximum size of a session context that will be returned by TPM2_ContextSave + pub const MAX_SESSION_CONTEXT: Self = Self(0x122); // Original value: PT_FIXED.into() + 34 + + /// Platform-specific family (a TPM_PS value)(see Table 25) + /// NOTE The platform-specific values for the TPM_PT_PS parameters are in the relevant + /// platform-specific specification. In the reference implementation, all of these values + /// are 0. + pub const PS_FAMILY_INDICATOR: Self = Self(0x123); // Original value: PT_FIXED.into() + 35 + + /// The level of the platform-specific specification + pub const PS_LEVEL: Self = Self(0x124); // Original value: PT_FIXED.into() + 36 + + /// A platform specific value + pub const PS_REVISION: Self = Self(0x125); // Original value: PT_FIXED.into() + 37 + + /// The platform-specific TPM specification day of year using TCG calendar + /// EXAMPLE November 15, 2010, has a day of year value of 319 (0000013F16). + pub const PS_DAY_OF_YEAR: Self = Self(0x126); // Original value: PT_FIXED.into() + 38 + + /// The platform-specific TPM specification year using the CE + /// EXAMPLE The year 2010 has a value of 000007DA16. + pub const PS_YEAR: Self = Self(0x127); // Original value: PT_FIXED.into() + 39 + + /// The number of split signing operations supported by the TPM + pub const SPLIT_MAX: Self = Self(0x128); // Original value: PT_FIXED.into() + 40 + + /// Total number of commands implemented in the TPM + pub const TOTAL_COMMANDS: Self = Self(0x129); // Original value: PT_FIXED.into() + 41 + + /// Number of commands from the TPM library that are implemented + pub const LIBRARY_COMMANDS: Self = Self(0x12A); // Original value: PT_FIXED.into() + 42 + + /// Number of vendor commands that are implemented + pub const VENDOR_COMMANDS: Self = Self(0x12B); // Original value: PT_FIXED.into() + 43 + + /// The maximum data size in one NV write, NV read, NV extend, or NV certify command + pub const NV_BUFFER_MAX: Self = Self(0x12C); // Original value: PT_FIXED.into() + 44 + + /// A TPMA_MODES value, indicating that the TPM is designed for these modes. + pub const MODES: Self = Self(0x12D); // Original value: PT_FIXED.into() + 45 + + /// The maximum size of a TPMS_CAPABILITY_DATA structure returned in TPM2_GetCapability(). + pub const MAX_CAP_BUFFER: Self = Self(0x12E); // Original value: PT_FIXED.into() + 46 + + /// The group of variable properties returned as TPMS_TAGGED_PROPERTY + /// The properties in this group change because of a Protected Capability other than a + /// firmware update. The values are not necessarily persistent across all power transitions. + pub const PT_VAR: Self = Self(0x200); // Original value: PT_GROUP.into() * 2 + + /// TPMA_PERMANENT + pub const PERMANENT: Self = Self(0x200); // Original value: PT_VAR.into() + 0 + + /// TPMA_STARTUP_CLEAR + pub const STARTUP_CLEAR: Self = Self(0x201); // Original value: PT_VAR.into() + 1 + + /// The number of NV Indexes currently defined + pub const HR_NV_INDEX: Self = Self(0x202); // Original value: PT_VAR.into() + 2 + + /// The number of authorization sessions currently loaded into TPM RAM + pub const HR_LOADED: Self = Self(0x203); // Original value: PT_VAR.into() + 3 + + /// The number of additional authorization sessions, of any type, that could be loaded + /// into TPM RAM + /// This value is an estimate. If this value is at least 1, then at least one + /// authorization session of any type may be loaded. Any command that changes the RAM + /// memory allocation can make this estimate invalid. + /// NOTE A valid implementation may return 1 even if more than one authorization session + /// would fit into RAM. + pub const HR_LOADED_AVAIL: Self = Self(0x204); // Original value: PT_VAR.into() + 4 + + /// The number of active authorization sessions currently being tracked by the TPM + /// This is the sum of the loaded and saved sessions. + pub const HR_ACTIVE: Self = Self(0x205); // Original value: PT_VAR.into() + 5 + + /// The number of additional authorization sessions, of any type, that could be created + /// This value is an estimate. If this value is at least 1, then at least one + /// authorization session of any type may be created. Any command that changes the RAM + /// memory allocation can make this estimate invalid. + /// NOTE A valid implementation may return 1 even if more than one authorization session + /// could be created. + pub const HR_ACTIVE_AVAIL: Self = Self(0x206); // Original value: PT_VAR.into() + 6 + + /// Estimate of the number of additional transient objects that could be loaded into TPM RAM + /// This value is an estimate. If this value is at least 1, then at least one object of + /// any type may be loaded. Any command that changes the memory allocation can make this + /// estimate invalid. + /// NOTE A valid implementation may return 1 even if more than one transient object would + /// fit into RAM. + pub const HR_TRANSIENT_AVAIL: Self = Self(0x207); // Original value: PT_VAR.into() + 7 + + /// The number of persistent objects currently loaded into TPM NV memory + pub const HR_PERSISTENT: Self = Self(0x208); // Original value: PT_VAR.into() + 8 + + /// The number of additional persistent objects that could be loaded into NV memory + /// This value is an estimate. If this value is at least 1, then at least one object of + /// any type may be made persistent. Any command that changes the NV memory allocation can + /// make this estimate invalid. + /// NOTE A valid implementation may return 1 even if more than one persistent object would + /// fit into NV memory. + pub const HR_PERSISTENT_AVAIL: Self = Self(0x209); // Original value: PT_VAR.into() + 9 + + /// The number of defined NV Indexes that have NV the TPM_NT_COUNTER attribute + pub const NV_COUNTERS: Self = Self(0x20A); // Original value: PT_VAR.into() + 10 + + /// The number of additional NV Indexes that can be defined with their TPM_NT of + /// TPM_NV_COUNTER and the TPMA_NV_ORDERLY attribute SET + /// This value is an estimate. If this value is at least 1, then at least one NV Index may + /// be created with a TPM_NT of TPM_NV_COUNTER and the TPMA_NV_ORDERLY attributes. Any + /// command that changes the NV memory allocation can make this estimate invalid. + /// NOTE A valid implementation may return 1 even if more than one NV counter could be defined. + pub const NV_COUNTERS_AVAIL: Self = Self(0x20B); // Original value: PT_VAR.into() + 11 + + /// Code that limits the algorithms that may be used with the TPM + pub const ALGORITHM_SET: Self = Self(0x20C); // Original value: PT_VAR.into() + 12 + + /// The number of loaded ECC curves + pub const LOADED_CURVES: Self = Self(0x20D); // Original value: PT_VAR.into() + 13 + + /// The current value of the lockout counter (failedTries) + pub const LOCKOUT_COUNTER: Self = Self(0x20E); // Original value: PT_VAR.into() + 14 + + /// The number of authorization failures before DA lockout is invoked + pub const MAX_AUTH_FAIL: Self = Self(0x20F); // Original value: PT_VAR.into() + 15 + + /// The number of seconds before the value reported by TPM_PT_LOCKOUT_COUNTER is decremented + pub const LOCKOUT_INTERVAL: Self = Self(0x210); // Original value: PT_VAR.into() + 16 + + /// The number of seconds after a lockoutAuth failure before use of lockoutAuth may be + /// attempted again + pub const LOCKOUT_RECOVERY: Self = Self(0x211); // Original value: PT_VAR.into() + 17 + + /// Number of milliseconds before the TPM will accept another command that will modify NV + /// This value is an approximation and may go up or down over time. + pub const NV_WRITE_RECOVERY: Self = Self(0x212); // Original value: PT_VAR.into() + 18 + + /// The high-order 32 bits of the command audit counter + pub const AUDIT_COUNTER_0: Self = Self(0x213); // Original value: PT_VAR.into() + 19 + + /// The low-order 32 bits of the command audit counter + pub const AUDIT_COUNTER_1: Self = Self(0x214); // Original value: PT_VAR.into() + 20 + + pub fn try_from(value: u32) -> Result { + match value { + 0 => Ok(Self::NONE), // Original value: 0x00000000 + 256 => Ok(Self::FAMILY_INDICATOR), // Original value: PT_FIXED.into() + 0 + 257 => Ok(Self::LEVEL), // Original value: PT_FIXED.into() + 1 + 258 => Ok(Self::REVISION), // Original value: PT_FIXED.into() + 2 + 259 => Ok(Self::DAY_OF_YEAR), // Original value: PT_FIXED.into() + 3 + 260 => Ok(Self::YEAR), // Original value: PT_FIXED.into() + 4 + 261 => Ok(Self::MANUFACTURER), // Original value: PT_FIXED.into() + 5 + 262 => Ok(Self::VENDOR_STRING_1), // Original value: PT_FIXED.into() + 6 + 263 => Ok(Self::VENDOR_STRING_2), // Original value: PT_FIXED.into() + 7 + 264 => Ok(Self::VENDOR_STRING_3), // Original value: PT_FIXED.into() + 8 + 265 => Ok(Self::VENDOR_STRING_4), // Original value: PT_FIXED.into() + 9 + 266 => Ok(Self::VENDOR_TPM_TYPE), // Original value: PT_FIXED.into() + 10 + 267 => Ok(Self::FIRMWARE_VERSION_1), // Original value: PT_FIXED.into() + 11 + 268 => Ok(Self::FIRMWARE_VERSION_2), // Original value: PT_FIXED.into() + 12 + 269 => Ok(Self::INPUT_BUFFER), // Original value: PT_FIXED.into() + 13 + 270 => Ok(Self::HR_TRANSIENT_MIN), // Original value: PT_FIXED.into() + 14 + 271 => Ok(Self::HR_PERSISTENT_MIN), // Original value: PT_FIXED.into() + 15 + 272 => Ok(Self::HR_LOADED_MIN), // Original value: PT_FIXED.into() + 16 + 273 => Ok(Self::ACTIVE_SESSIONS_MAX), // Original value: PT_FIXED.into() + 17 + 274 => Ok(Self::PCR_COUNT), // Original value: PT_FIXED.into() + 18 + 275 => Ok(Self::PCR_SELECT_MIN), // Original value: PT_FIXED.into() + 19 + 276 => Ok(Self::CONTEXT_GAP_MAX), // Original value: PT_FIXED.into() + 20 + 278 => Ok(Self::NV_COUNTERS_MAX), // Original value: PT_FIXED.into() + 22 + 279 => Ok(Self::NV_INDEX_MAX), // Original value: PT_FIXED.into() + 23 + 280 => Ok(Self::MEMORY), // Original value: PT_FIXED.into() + 24 + 281 => Ok(Self::CLOCK_UPDATE), // Original value: PT_FIXED.into() + 25 + 282 => Ok(Self::CONTEXT_HASH), // Original value: PT_FIXED.into() + 26 + 283 => Ok(Self::CONTEXT_SYM), // Original value: PT_FIXED.into() + 27 + 284 => Ok(Self::CONTEXT_SYM_SIZE), // Original value: PT_FIXED.into() + 28 + 285 => Ok(Self::ORDERLY_COUNT), // Original value: PT_FIXED.into() + 29 + 286 => Ok(Self::MAX_COMMAND_SIZE), // Original value: PT_FIXED.into() + 30 + 287 => Ok(Self::MAX_RESPONSE_SIZE), // Original value: PT_FIXED.into() + 31 + 288 => Ok(Self::MAX_DIGEST), // Original value: PT_FIXED.into() + 32 + 289 => Ok(Self::MAX_OBJECT_CONTEXT), // Original value: PT_FIXED.into() + 33 + 290 => Ok(Self::MAX_SESSION_CONTEXT), // Original value: PT_FIXED.into() + 34 + 291 => Ok(Self::PS_FAMILY_INDICATOR), // Original value: PT_FIXED.into() + 35 + 292 => Ok(Self::PS_LEVEL), // Original value: PT_FIXED.into() + 36 + 293 => Ok(Self::PS_REVISION), // Original value: PT_FIXED.into() + 37 + 294 => Ok(Self::PS_DAY_OF_YEAR), // Original value: PT_FIXED.into() + 38 + 295 => Ok(Self::PS_YEAR), // Original value: PT_FIXED.into() + 39 + 296 => Ok(Self::SPLIT_MAX), // Original value: PT_FIXED.into() + 40 + 297 => Ok(Self::TOTAL_COMMANDS), // Original value: PT_FIXED.into() + 41 + 298 => Ok(Self::LIBRARY_COMMANDS), // Original value: PT_FIXED.into() + 42 + 299 => Ok(Self::VENDOR_COMMANDS), // Original value: PT_FIXED.into() + 43 + 300 => Ok(Self::NV_BUFFER_MAX), // Original value: PT_FIXED.into() + 44 + 301 => Ok(Self::MODES), // Original value: PT_FIXED.into() + 45 + 302 => Ok(Self::MAX_CAP_BUFFER), // Original value: PT_FIXED.into() + 46 + 512 => Ok(Self::PERMANENT), // Original value: PT_VAR.into() + 0 + 513 => Ok(Self::STARTUP_CLEAR), // Original value: PT_VAR.into() + 1 + 514 => Ok(Self::HR_NV_INDEX), // Original value: PT_VAR.into() + 2 + 515 => Ok(Self::HR_LOADED), // Original value: PT_VAR.into() + 3 + 516 => Ok(Self::HR_LOADED_AVAIL), // Original value: PT_VAR.into() + 4 + 517 => Ok(Self::HR_ACTIVE), // Original value: PT_VAR.into() + 5 + 518 => Ok(Self::HR_ACTIVE_AVAIL), // Original value: PT_VAR.into() + 6 + 519 => Ok(Self::HR_TRANSIENT_AVAIL), // Original value: PT_VAR.into() + 7 + 520 => Ok(Self::HR_PERSISTENT), // Original value: PT_VAR.into() + 8 + 521 => Ok(Self::HR_PERSISTENT_AVAIL), // Original value: PT_VAR.into() + 9 + 522 => Ok(Self::NV_COUNTERS), // Original value: PT_VAR.into() + 10 + 523 => Ok(Self::NV_COUNTERS_AVAIL), // Original value: PT_VAR.into() + 11 + 524 => Ok(Self::ALGORITHM_SET), // Original value: PT_VAR.into() + 12 + 525 => Ok(Self::LOADED_CURVES), // Original value: PT_VAR.into() + 13 + 526 => Ok(Self::LOCKOUT_COUNTER), // Original value: PT_VAR.into() + 14 + 527 => Ok(Self::MAX_AUTH_FAIL), // Original value: PT_VAR.into() + 15 + 528 => Ok(Self::LOCKOUT_INTERVAL), // Original value: PT_VAR.into() + 16 + 529 => Ok(Self::LOCKOUT_RECOVERY), // Original value: PT_VAR.into() + 17 + 530 => Ok(Self::NV_WRITE_RECOVERY), // Original value: PT_VAR.into() + 18 + 531 => Ok(Self::AUDIT_COUNTER_0), // Original value: PT_VAR.into() + 19 + 532 => Ok(Self::AUDIT_COUNTER_1), // Original value: PT_VAR.into() + 20 + _ => Err(TpmError::InvalidEnumValue), + } + } +} + +impl TpmEnum for TPM_PT { + fn get_value(&self) -> u32 { + self.0.into() + } + + fn try_from_trait(value: u64) -> Result where Self: Sized { + TPM_PT::try_from(value as u32) + } + + fn new_from_trait(value: u64) -> Result where Self: Sized { + Ok(TPM_PT(value as u32)) + } +} + +impl From for u32 { + fn from(value: TPM_PT) -> Self { + value.0 as u32 + } +} + +impl From for i32 { + fn from(value: TPM_PT) -> Self { + value.0 as i32 + } +} + +impl fmt::Display for TPM_PT { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self.0 { + 0 => write!(f, "NONE"), + 256 => write!(f, "FAMILY_INDICATOR"), + 257 => write!(f, "LEVEL"), + 258 => write!(f, "REVISION"), + 259 => write!(f, "DAY_OF_YEAR"), + 260 => write!(f, "YEAR"), + 261 => write!(f, "MANUFACTURER"), + 262 => write!(f, "VENDOR_STRING_1"), + 263 => write!(f, "VENDOR_STRING_2"), + 264 => write!(f, "VENDOR_STRING_3"), + 265 => write!(f, "VENDOR_STRING_4"), + 266 => write!(f, "VENDOR_TPM_TYPE"), + 267 => write!(f, "FIRMWARE_VERSION_1"), + 268 => write!(f, "FIRMWARE_VERSION_2"), + 269 => write!(f, "INPUT_BUFFER"), + 270 => write!(f, "HR_TRANSIENT_MIN"), + 271 => write!(f, "HR_PERSISTENT_MIN"), + 272 => write!(f, "HR_LOADED_MIN"), + 273 => write!(f, "ACTIVE_SESSIONS_MAX"), + 274 => write!(f, "PCR_COUNT"), + 275 => write!(f, "PCR_SELECT_MIN"), + 276 => write!(f, "CONTEXT_GAP_MAX"), + 278 => write!(f, "NV_COUNTERS_MAX"), + 279 => write!(f, "NV_INDEX_MAX"), + 280 => write!(f, "MEMORY"), + 281 => write!(f, "CLOCK_UPDATE"), + 282 => write!(f, "CONTEXT_HASH"), + 283 => write!(f, "CONTEXT_SYM"), + 284 => write!(f, "CONTEXT_SYM_SIZE"), + 285 => write!(f, "ORDERLY_COUNT"), + 286 => write!(f, "MAX_COMMAND_SIZE"), + 287 => write!(f, "MAX_RESPONSE_SIZE"), + 288 => write!(f, "MAX_DIGEST"), + 289 => write!(f, "MAX_OBJECT_CONTEXT"), + 290 => write!(f, "MAX_SESSION_CONTEXT"), + 291 => write!(f, "PS_FAMILY_INDICATOR"), + 292 => write!(f, "PS_LEVEL"), + 293 => write!(f, "PS_REVISION"), + 294 => write!(f, "PS_DAY_OF_YEAR"), + 295 => write!(f, "PS_YEAR"), + 296 => write!(f, "SPLIT_MAX"), + 297 => write!(f, "TOTAL_COMMANDS"), + 298 => write!(f, "LIBRARY_COMMANDS"), + 299 => write!(f, "VENDOR_COMMANDS"), + 300 => write!(f, "NV_BUFFER_MAX"), + 301 => write!(f, "MODES"), + 302 => write!(f, "MAX_CAP_BUFFER"), + 512 => write!(f, "PERMANENT"), + 513 => write!(f, "STARTUP_CLEAR"), + 514 => write!(f, "HR_NV_INDEX"), + 515 => write!(f, "HR_LOADED"), + 516 => write!(f, "HR_LOADED_AVAIL"), + 517 => write!(f, "HR_ACTIVE"), + 518 => write!(f, "HR_ACTIVE_AVAIL"), + 519 => write!(f, "HR_TRANSIENT_AVAIL"), + 520 => write!(f, "HR_PERSISTENT"), + 521 => write!(f, "HR_PERSISTENT_AVAIL"), + 522 => write!(f, "NV_COUNTERS"), + 523 => write!(f, "NV_COUNTERS_AVAIL"), + 524 => write!(f, "ALGORITHM_SET"), + 525 => write!(f, "LOADED_CURVES"), + 526 => write!(f, "LOCKOUT_COUNTER"), + 527 => write!(f, "MAX_AUTH_FAIL"), + 528 => write!(f, "LOCKOUT_INTERVAL"), + 529 => write!(f, "LOCKOUT_RECOVERY"), + 530 => write!(f, "NV_WRITE_RECOVERY"), + 531 => write!(f, "AUDIT_COUNTER_0"), + 532 => write!(f, "AUDIT_COUNTER_1"), + _ => write!(f, "{}", enum_to_str(self.0 as u64, std::any::TypeId::of::())), + } + } +} + +/// The TPM_PT_PCR constants are used in TPM2_GetCapability() to indicate the property +/// being selected or returned. The PCR properties can be read when capability == +/// TPM_CAP_PCR_PROPERTIES. If there is no property that corresponds to the value of +/// property, the next higher value is returned, if it exists. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)] +pub struct TPM_PT_PCR(pub u32); + +impl TPM_PT_PCR { + /// Bottom of the range of TPM_PT_PCR properties + pub const FIRST: Self = Self(0x0); // Original value: 0x00000000 + + /// A SET bit in the TPMS_PCR_SELECT indicates that the PCR is saved and restored by TPM_SU_STATE + pub const SAVE: Self = Self(0x0); // Original value: 0x00000000 + + /// A SET bit in the TPMS_PCR_SELECT indicates that the PCR may be extended from locality 0 + /// This property is only present if a locality other than 0 is implemented. + pub const EXTEND_L0: Self = Self(0x1); // Original value: 0x00000001 + + /// A SET bit in the TPMS_PCR_SELECT indicates that the PCR may be reset by + /// TPM2_PCR_Reset() from locality 0 + pub const RESET_L0: Self = Self(0x2); // Original value: 0x00000002 + + /// A SET bit in the TPMS_PCR_SELECT indicates that the PCR may be extended from locality 1 + /// This property is only present if locality 1 is implemented. + pub const EXTEND_L1: Self = Self(0x3); // Original value: 0x00000003 + + /// A SET bit in the TPMS_PCR_SELECT indicates that the PCR may be reset by + /// TPM2_PCR_Reset() from locality 1 + /// This property is only present if locality 1 is implemented. + pub const RESET_L1: Self = Self(0x4); // Original value: 0x00000004 + + /// A SET bit in the TPMS_PCR_SELECT indicates that the PCR may be extended from locality 2 + /// This property is only present if localities 1 and 2 are implemented. + pub const EXTEND_L2: Self = Self(0x5); // Original value: 0x00000005 + + /// A SET bit in the TPMS_PCR_SELECT indicates that the PCR may be reset by + /// TPM2_PCR_Reset() from locality 2 + /// This property is only present if localities 1 and 2 are implemented. + pub const RESET_L2: Self = Self(0x6); // Original value: 0x00000006 + + /// A SET bit in the TPMS_PCR_SELECT indicates that the PCR may be extended from locality 3 + /// This property is only present if localities 1, 2, and 3 are implemented. + pub const EXTEND_L3: Self = Self(0x7); // Original value: 0x00000007 + + /// A SET bit in the TPMS_PCR_SELECT indicates that the PCR may be reset by + /// TPM2_PCR_Reset() from locality 3 + /// This property is only present if localities 1, 2, and 3 are implemented. + pub const RESET_L3: Self = Self(0x8); // Original value: 0x00000008 + + /// A SET bit in the TPMS_PCR_SELECT indicates that the PCR may be extended from locality 4 + /// This property is only present if localities 1, 2, 3, and 4 are implemented. + pub const EXTEND_L4: Self = Self(0x9); // Original value: 0x00000009 + + /// A SET bit in the TPMS_PCR_SELECT indicates that the PCR may be reset by + /// TPM2_PCR_Reset() from locality 4 + /// This property is only present if localities 1, 2, 3, and 4 are implemented. + pub const RESET_L4: Self = Self(0xA); // Original value: 0x0000000A + + /// A SET bit in the TPMS_PCR_SELECT indicates that modifications to this PCR (reset or + /// Extend) will not increment the pcrUpdateCounter + pub const NO_INCREMENT: Self = Self(0x11); // Original value: 0x00000011 + + /// A SET bit in the TPMS_PCR_SELECT indicates that the PCR is reset by a D-RTM event + /// These PCR are reset to -1 on TPM2_Startup() and reset to 0 on a _TPM_Hash_End event + /// following a _TPM_Hash_Start event. + pub const DRTM_RESET: Self = Self(0x12); // Original value: 0x00000012 + + /// A SET bit in the TPMS_PCR_SELECT indicates that the PCR is controlled by policy + /// This property is only present if the TPM supports policy control of a PCR. + pub const POLICY: Self = Self(0x13); // Original value: 0x00000013 + + /// A SET bit in the TPMS_PCR_SELECT indicates that the PCR is controlled by an + /// authorization value + /// This property is only present if the TPM supports authorization control of a PCR. + pub const AUTH: Self = Self(0x14); // Original value: 0x00000014 + + /// Top of the range of TPM_PT_PCR properties of the implementation + /// If the TPM receives a request for a PCR property with a value larger than this, the + /// TPM will return a zero length list and set the moreData parameter to NO. + /// NOTE This is an implementation-specific value. The value shown reflects the reference + /// code implementation. + pub const LAST: Self = Self(0x14); // Original value: 0x00000014 + + pub fn try_from(value: u32) -> Result { + match value { + 0 => Ok(Self::SAVE), // Original value: 0x00000000 + 1 => Ok(Self::EXTEND_L0), // Original value: 0x00000001 + 2 => Ok(Self::RESET_L0), // Original value: 0x00000002 + 3 => Ok(Self::EXTEND_L1), // Original value: 0x00000003 + 4 => Ok(Self::RESET_L1), // Original value: 0x00000004 + 5 => Ok(Self::EXTEND_L2), // Original value: 0x00000005 + 6 => Ok(Self::RESET_L2), // Original value: 0x00000006 + 7 => Ok(Self::EXTEND_L3), // Original value: 0x00000007 + 8 => Ok(Self::RESET_L3), // Original value: 0x00000008 + 9 => Ok(Self::EXTEND_L4), // Original value: 0x00000009 + 10 => Ok(Self::RESET_L4), // Original value: 0x0000000A + 17 => Ok(Self::NO_INCREMENT), // Original value: 0x00000011 + 18 => Ok(Self::DRTM_RESET), // Original value: 0x00000012 + 19 => Ok(Self::POLICY), // Original value: 0x00000013 + 20 => Ok(Self::LAST), // Original value: 0x00000014 + _ => Err(TpmError::InvalidEnumValue), + } + } +} + +impl TpmEnum for TPM_PT_PCR { + fn get_value(&self) -> u32 { + self.0.into() + } + + fn try_from_trait(value: u64) -> Result where Self: Sized { + TPM_PT_PCR::try_from(value as u32) + } + + fn new_from_trait(value: u64) -> Result where Self: Sized { + Ok(TPM_PT_PCR(value as u32)) + } +} + +impl From for u32 { + fn from(value: TPM_PT_PCR) -> Self { + value.0 as u32 + } +} + +impl From for i32 { + fn from(value: TPM_PT_PCR) -> Self { + value.0 as i32 + } +} + +impl fmt::Display for TPM_PT_PCR { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self.0 { + 0 => write!(f, "SAVE"), + 1 => write!(f, "EXTEND_L0"), + 2 => write!(f, "RESET_L0"), + 3 => write!(f, "EXTEND_L1"), + 4 => write!(f, "RESET_L1"), + 5 => write!(f, "EXTEND_L2"), + 6 => write!(f, "RESET_L2"), + 7 => write!(f, "EXTEND_L3"), + 8 => write!(f, "RESET_L3"), + 9 => write!(f, "EXTEND_L4"), + 10 => write!(f, "RESET_L4"), + 17 => write!(f, "NO_INCREMENT"), + 18 => write!(f, "DRTM_RESET"), + 19 => write!(f, "POLICY"), + 20 => write!(f, "LAST"), + _ => write!(f, "{}", enum_to_str(self.0 as u64, std::any::TypeId::of::())), + } + } +} + +/// The platform values in Table 25 are used for the TPM_PT_PS_FAMILY_INDICATOR. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)] +pub struct TPM_PS(pub u32); + +impl TPM_PS { + /// Not platform specific + pub const MAIN: Self = Self(0x0); // Original value: 0x00000000 + + /// PC Client + pub const PC: Self = Self(0x1); // Original value: 0x00000001 + + /// PDA (includes all mobile devices that are not specifically cell phones) + pub const PDA: Self = Self(0x2); // Original value: 0x00000002 + + /// Cell Phone + pub const CELL_PHONE: Self = Self(0x3); // Original value: 0x00000003 + + /// Server WG + pub const SERVER: Self = Self(0x4); // Original value: 0x00000004 + + /// Peripheral WG + pub const PERIPHERAL: Self = Self(0x5); // Original value: 0x00000005 + + /// TSS WG (deprecated) + pub const TSS: Self = Self(0x6); // Original value: 0x00000006 + + /// Storage WG + pub const STORAGE: Self = Self(0x7); // Original value: 0x00000007 + + /// Authentication WG + pub const AUTHENTICATION: Self = Self(0x8); // Original value: 0x00000008 + + /// Embedded WG + pub const EMBEDDED: Self = Self(0x9); // Original value: 0x00000009 + + /// Hardcopy WG + pub const HARDCOPY: Self = Self(0xA); // Original value: 0x0000000A + + /// Infrastructure WG (deprecated) + pub const INFRASTRUCTURE: Self = Self(0xB); // Original value: 0x0000000B + + /// Virtualization WG + pub const VIRTUALIZATION: Self = Self(0xC); // Original value: 0x0000000C + + /// Trusted Network Connect WG (deprecated) + pub const TNC: Self = Self(0xD); // Original value: 0x0000000D + + /// Multi-tenant WG (deprecated) + pub const MULTI_TENANT: Self = Self(0xE); // Original value: 0x0000000E + + /// Technical Committee (deprecated) + pub const TC: Self = Self(0xF); // Original value: 0x0000000F + + pub fn try_from(value: u32) -> Result { + match value { + 0 => Ok(Self::MAIN), // Original value: 0x00000000 + 1 => Ok(Self::PC), // Original value: 0x00000001 + 2 => Ok(Self::PDA), // Original value: 0x00000002 + 3 => Ok(Self::CELL_PHONE), // Original value: 0x00000003 + 4 => Ok(Self::SERVER), // Original value: 0x00000004 + 5 => Ok(Self::PERIPHERAL), // Original value: 0x00000005 + 6 => Ok(Self::TSS), // Original value: 0x00000006 + 7 => Ok(Self::STORAGE), // Original value: 0x00000007 + 8 => Ok(Self::AUTHENTICATION), // Original value: 0x00000008 + 9 => Ok(Self::EMBEDDED), // Original value: 0x00000009 + 10 => Ok(Self::HARDCOPY), // Original value: 0x0000000A + 11 => Ok(Self::INFRASTRUCTURE), // Original value: 0x0000000B + 12 => Ok(Self::VIRTUALIZATION), // Original value: 0x0000000C + 13 => Ok(Self::TNC), // Original value: 0x0000000D + 14 => Ok(Self::MULTI_TENANT), // Original value: 0x0000000E + 15 => Ok(Self::TC), // Original value: 0x0000000F + _ => Err(TpmError::InvalidEnumValue), + } + } +} + +impl TpmEnum for TPM_PS { + fn get_value(&self) -> u32 { + self.0.into() + } + + fn try_from_trait(value: u64) -> Result where Self: Sized { + TPM_PS::try_from(value as u32) + } + + fn new_from_trait(value: u64) -> Result where Self: Sized { + Ok(TPM_PS(value as u32)) + } +} + +impl From for u32 { + fn from(value: TPM_PS) -> Self { + value.0 as u32 + } +} + +impl From for i32 { + fn from(value: TPM_PS) -> Self { + value.0 as i32 + } +} + +impl fmt::Display for TPM_PS { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self.0 { + 0 => write!(f, "MAIN"), + 1 => write!(f, "PC"), + 2 => write!(f, "PDA"), + 3 => write!(f, "CELL_PHONE"), + 4 => write!(f, "SERVER"), + 5 => write!(f, "PERIPHERAL"), + 6 => write!(f, "TSS"), + 7 => write!(f, "STORAGE"), + 8 => write!(f, "AUTHENTICATION"), + 9 => write!(f, "EMBEDDED"), + 10 => write!(f, "HARDCOPY"), + 11 => write!(f, "INFRASTRUCTURE"), + 12 => write!(f, "VIRTUALIZATION"), + 13 => write!(f, "TNC"), + 14 => write!(f, "MULTI_TENANT"), + 15 => write!(f, "TC"), + _ => write!(f, "{}", enum_to_str(self.0 as u64, std::any::TypeId::of::())), + } + } +} + +/// The 32-bit handle space is divided into 256 regions of equal size with 224 values in +/// each. Each of these ranges represents a handle type. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)] +pub struct TPM_HT(pub u8); + +impl TPM_HT { + /// PCR consecutive numbers, starting at 0, that reference the PCR registers + /// A platform-specific specification will set the minimum number of PCR and an + /// implementation may have more. + pub const PCR: Self = Self(0x0); // Original value: 0x00 + + /// NV Index assigned by the caller + pub const NV_INDEX: Self = Self(0x1); // Original value: 0x01 + + /// HMAC Authorization Session assigned by the TPM when the session is created + pub const HMAC_SESSION: Self = Self(0x2); // Original value: 0x02 + + /// Loaded Authorization Session used only in the context of TPM2_GetCapability + /// This type references both loaded HMAC and loaded policy authorization sessions. + pub const LOADED_SESSION: Self = Self(0x2); // Original value: 0x02 + + /// Policy Authorization Session assigned by the TPM when the session is created + pub const POLICY_SESSION: Self = Self(0x3); // Original value: 0x03 + + /// Saved Authorization Session used only in the context of TPM2_GetCapability + /// This type references saved authorization session contexts for which the TPM is + /// maintaining tracking information. + pub const SAVED_SESSION: Self = Self(0x3); // Original value: 0x03 + + /// Permanent Values assigned by this specification in Table 28 + pub const PERMANENT: Self = Self(0x40); + + /// Transient Objects assigned by the TPM when an object is loaded into transient-object + /// memory or when a persistent object is converted to a transient object + pub const TRANSIENT: Self = Self(0x80); + + /// Persistent Objects assigned by the TPM when a loaded transient object is made persistent + pub const PERSISTENT: Self = Self(0x81); + + /// Attached Component handle for an Attached Component. + pub const AC: Self = Self(0x90); + + pub fn try_from(value: u8) -> Result { + match value { + 0 => Ok(Self::PCR), // Original value: 0x00 + 1 => Ok(Self::NV_INDEX), // Original value: 0x01 + 2 => Ok(Self::LOADED_SESSION), // Original value: 0x02 + 3 => Ok(Self::SAVED_SESSION), // Original value: 0x03 + 64 => Ok(Self::PERMANENT), // Original value: 0x40 + 128 => Ok(Self::TRANSIENT), // Original value: 0x80 + 129 => Ok(Self::PERSISTENT), // Original value: 0x81 + 144 => Ok(Self::AC), // Original value: 0x90 + _ => Err(TpmError::InvalidEnumValue), + } + } +} + +impl TpmEnum for TPM_HT { + fn get_value(&self) -> u8 { + self.0.into() + } + + fn try_from_trait(value: u64) -> Result where Self: Sized { + TPM_HT::try_from(value as u8) + } + + fn new_from_trait(value: u64) -> Result where Self: Sized { + Ok(TPM_HT(value as u8)) + } +} + +impl From for u8 { + fn from(value: TPM_HT) -> Self { + value.0 as u8 + } +} + +impl From for i8 { + fn from(value: TPM_HT) -> Self { + value.0 as i8 + } +} + +impl fmt::Display for TPM_HT { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self.0 { + 0 => write!(f, "PCR"), + 1 => write!(f, "NV_INDEX"), + 2 => write!(f, "LOADED_SESSION"), + 3 => write!(f, "SAVED_SESSION"), + 64 => write!(f, "PERMANENT"), + 128 => write!(f, "TRANSIENT"), + 129 => write!(f, "PERSISTENT"), + 144 => write!(f, "AC"), + _ => write!(f, "{}", enum_to_str(self.0 as u64, std::any::TypeId::of::())), + } + } +} + +/// Table 28 lists the architecturally defined handles that cannot be changed. The handles +/// include authorization handles, and special handles. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)] +pub struct TPM_RH(pub u32); + +impl TPM_RH { + pub const FIRST: Self = Self(0x40000000); + + /// Not used1 + pub const SRK: Self = Self(0x40000000); + + /// Handle references the Storage Primary Seed (SPS), the ownerAuth, and the ownerPolicy + pub const OWNER: Self = Self(0x40000001); + + /// Not used1 + pub const REVOKE: Self = Self(0x40000002); + + /// Not used1 + pub const TRANSPORT: Self = Self(0x40000003); + + /// Not used1 + pub const OPERATOR: Self = Self(0x40000004); + + /// Not used1 + pub const ADMIN: Self = Self(0x40000005); + + /// Not used1 + pub const EK: Self = Self(0x40000006); + + /// A handle associated with the null hierarchy, an EmptyAuth authValue, and an Empty + /// Policy authPolicy. + pub const NULL: Self = Self(0x40000007); + + /// Value reserved to the TPM to indicate a handle location that has not been initialized + /// or assigned + pub const UNASSIGNED: Self = Self(0x40000008); + + /// Authorization value used to indicate a password authorization session + pub const PW: Self = Self(0x40000009); + + /// References the authorization associated with the dictionary attack lockout reset + pub const LOCKOUT: Self = Self(0x4000000A); + + /// References the Endorsement Primary Seed (EPS), endorsementAuth, and endorsementPolicy + pub const ENDORSEMENT: Self = Self(0x4000000B); + + /// References the Platform Primary Seed (PPS), platformAuth, and platformPolicy + pub const PLATFORM: Self = Self(0x4000000C); + + /// For phEnableNV + pub const PLATFORM_NV: Self = Self(0x4000000D); + + /// Start of a range of authorization values that are vendor-specific. A TPM may support + /// any of the values in this range as are needed for vendor-specific purposes. + /// Disabled if ehEnable is CLEAR. + /// NOTE Any includes none. + pub const AUTH_00: Self = Self(0x40000010); + + /// End of the range of vendor-specific authorization values. + pub const AUTH_FF: Self = Self(0x4000010F); + + /// Start of the range of authenticated timers + pub const ACT_0: Self = Self(0x40000110); + + /// End of the range of authenticated timers + pub const ACT_F: Self = Self(0x4000011F); + + /// The top of the reserved handle area + /// This is set to allow TPM2_GetCapability() to know where to stop. It may vary as + /// implementations add to the permanent handle area. + pub const LAST: Self = Self(0x4000011F); + + pub fn try_from(value: u32) -> Result { + match value { + 1073741824 => Ok(Self::SRK), // Original value: 0x40000000 + 1073741825 => Ok(Self::OWNER), // Original value: 0x40000001 + 1073741826 => Ok(Self::REVOKE), // Original value: 0x40000002 + 1073741827 => Ok(Self::TRANSPORT), // Original value: 0x40000003 + 1073741828 => Ok(Self::OPERATOR), // Original value: 0x40000004 + 1073741829 => Ok(Self::ADMIN), // Original value: 0x40000005 + 1073741830 => Ok(Self::EK), // Original value: 0x40000006 + 1073741831 => Ok(Self::NULL), // Original value: 0x40000007 + 1073741832 => Ok(Self::UNASSIGNED), // Original value: 0x40000008 + 1073741833 => Ok(Self::PW), // Original value: 0x40000009 + 1073741834 => Ok(Self::LOCKOUT), // Original value: 0x4000000A + 1073741835 => Ok(Self::ENDORSEMENT), // Original value: 0x4000000B + 1073741836 => Ok(Self::PLATFORM), // Original value: 0x4000000C + 1073741837 => Ok(Self::PLATFORM_NV), // Original value: 0x4000000D + 1073741840 => Ok(Self::AUTH_00), // Original value: 0x40000010 + 1073742095 => Ok(Self::AUTH_FF), // Original value: 0x4000010F + 1073742096 => Ok(Self::ACT_0), // Original value: 0x40000110 + 1073742111 => Ok(Self::LAST), // Original value: 0x4000011F + _ => Err(TpmError::InvalidEnumValue), + } + } +} + +impl TpmEnum for TPM_RH { + fn get_value(&self) -> u32 { + self.0.into() + } + + fn try_from_trait(value: u64) -> Result where Self: Sized { + TPM_RH::try_from(value as u32) + } + + fn new_from_trait(value: u64) -> Result where Self: Sized { + Ok(TPM_RH(value as u32)) + } +} + +impl From for u32 { + fn from(value: TPM_RH) -> Self { + value.0 as u32 + } +} + +impl From for i32 { + fn from(value: TPM_RH) -> Self { + value.0 as i32 + } +} + +impl fmt::Display for TPM_RH { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self.0 { + 1073741824 => write!(f, "SRK"), + 1073741825 => write!(f, "OWNER"), + 1073741826 => write!(f, "REVOKE"), + 1073741827 => write!(f, "TRANSPORT"), + 1073741828 => write!(f, "OPERATOR"), + 1073741829 => write!(f, "ADMIN"), + 1073741830 => write!(f, "EK"), + 1073741831 => write!(f, "NULL"), + 1073741832 => write!(f, "UNASSIGNED"), + 1073741833 => write!(f, "PW"), + 1073741834 => write!(f, "LOCKOUT"), + 1073741835 => write!(f, "ENDORSEMENT"), + 1073741836 => write!(f, "PLATFORM"), + 1073741837 => write!(f, "PLATFORM_NV"), + 1073741840 => write!(f, "AUTH_00"), + 1073742095 => write!(f, "AUTH_FF"), + 1073742096 => write!(f, "ACT_0"), + 1073742111 => write!(f, "LAST"), + _ => write!(f, "{}", enum_to_str(self.0 as u64, std::any::TypeId::of::())), + } + } +} + +/// This table lists the values of the TPM_NT field of a TPMA_NV. See Table 215 for usage. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)] +pub struct TPM_NT(pub u32); + +impl TPM_NT { + /// Ordinary contains data that is opaque to the TPM that can only be modified using TPM2_NV_Write(). + pub const ORDINARY: Self = Self(0x0); + + /// Counter contains an 8-octet value that is to be used as a counter and can only be + /// modified with TPM2_NV_Increment() + pub const COUNTER: Self = Self(0x1); + + /// Bit Field contains an 8-octet value to be used as a bit field and can only be modified + /// with TPM2_NV_SetBits(). + pub const BITS: Self = Self(0x2); + + /// Extend contains a digest-sized value used like a PCR. The Index can only be modified + /// using TPM2_NV_Extend(). The extend will use the nameAlg of the Index. + pub const EXTEND: Self = Self(0x4); + + /// PIN Fail - contains pinCount that increments on a PIN authorization failure and a pinLimit + pub const PIN_FAIL: Self = Self(0x8); + + /// PIN Pass - contains pinCount that increments on a PIN authorization success and a pinLimit + pub const PIN_PASS: Self = Self(0x9); + + pub fn try_from(value: u32) -> Result { + match value { + 0 => Ok(Self::ORDINARY), // Original value: 0x0 + 1 => Ok(Self::COUNTER), // Original value: 0x1 + 2 => Ok(Self::BITS), // Original value: 0x2 + 4 => Ok(Self::EXTEND), // Original value: 0x4 + 8 => Ok(Self::PIN_FAIL), // Original value: 0x8 + 9 => Ok(Self::PIN_PASS), // Original value: 0x9 + _ => Err(TpmError::InvalidEnumValue), + } + } +} + +impl TpmEnum for TPM_NT { + fn get_value(&self) -> u32 { + self.0.into() + } + + fn try_from_trait(value: u64) -> Result where Self: Sized { + TPM_NT::try_from(value as u32) + } + + fn new_from_trait(value: u64) -> Result where Self: Sized { + Ok(TPM_NT(value as u32)) + } +} + +impl From for u32 { + fn from(value: TPM_NT) -> Self { + value.0 as u32 + } +} + +impl From for i32 { + fn from(value: TPM_NT) -> Self { + value.0 as i32 + } +} + +impl fmt::Display for TPM_NT { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self.0 { + 0 => write!(f, "ORDINARY"), + 1 => write!(f, "COUNTER"), + 2 => write!(f, "BITS"), + 4 => write!(f, "EXTEND"), + 8 => write!(f, "PIN_FAIL"), + 9 => write!(f, "PIN_PASS"), + _ => write!(f, "{}", enum_to_str(self.0 as u64, std::any::TypeId::of::())), + } + } +} + +/// These constants are used in TPM2_AC_GetCapability() to indicate the first tagged value +/// returned from an attached component. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)] +pub struct TPM_AT(pub u32); + +impl TPM_AT { + /// In a command, a non-specific request for AC information; in a response, indicates that + /// outputData is not meaningful + pub const ANY: Self = Self(0x0); // Original value: 0x00000000 + + /// Indicates a TCG defined, device-specific error + pub const ERROR: Self = Self(0x1); // Original value: 0x00000001 + + /// Indicates the most significant 32 bits of a pairing value for the AC + pub const PV1: Self = Self(0x2); // Original value: 0x00000002 + + /// Value added to a TPM_AT to indicate a vendor-specific tag value + pub const VEND: Self = Self(0x80000000); + + pub fn try_from(value: u32) -> Result { + match value { + 0 => Ok(Self::ANY), // Original value: 0x00000000 + 1 => Ok(Self::ERROR), // Original value: 0x00000001 + 2 => Ok(Self::PV1), // Original value: 0x00000002 + 2147483648 => Ok(Self::VEND), // Original value: 0x80000000 + _ => Err(TpmError::InvalidEnumValue), + } + } +} + +impl TpmEnum for TPM_AT { + fn get_value(&self) -> u32 { + self.0.into() + } + + fn try_from_trait(value: u64) -> Result where Self: Sized { + TPM_AT::try_from(value as u32) + } + + fn new_from_trait(value: u64) -> Result where Self: Sized { + Ok(TPM_AT(value as u32)) + } +} + +impl From for u32 { + fn from(value: TPM_AT) -> Self { + value.0 as u32 + } +} + +impl From for i32 { + fn from(value: TPM_AT) -> Self { + value.0 as i32 + } +} + +impl fmt::Display for TPM_AT { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self.0 { + 0 => write!(f, "ANY"), + 1 => write!(f, "ERROR"), + 2 => write!(f, "PV1"), + 2147483648 => write!(f, "VEND"), + _ => write!(f, "{}", enum_to_str(self.0 as u64, std::any::TypeId::of::())), + } + } +} + +/// These constants are the TCG-defined error values returned by an AC. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)] +pub struct TPM_AE(pub u32); + +impl TPM_AE { + /// In a command, a non-specific request for AC information; in a response, indicates that + /// outputData is not meaningful + pub const NONE: Self = Self(0x0); // Original value: 0x00000000 + + pub fn try_from(value: u32) -> Result { + match value { + 0 => Ok(Self::NONE), // Original value: 0x00000000 + _ => Err(TpmError::InvalidEnumValue), + } + } +} + +impl TpmEnum for TPM_AE { + fn get_value(&self) -> u32 { + self.0.into() + } + + fn try_from_trait(value: u64) -> Result where Self: Sized { + TPM_AE::try_from(value as u32) + } + + fn new_from_trait(value: u64) -> Result where Self: Sized { + Ok(TPM_AE(value as u32)) + } +} + +impl From for u32 { + fn from(value: TPM_AE) -> Self { + value.0 as u32 + } +} + +impl From for i32 { + fn from(value: TPM_AE) -> Self { + value.0 as i32 + } +} + +impl fmt::Display for TPM_AE { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self.0 { + 0 => write!(f, "NONE"), + _ => write!(f, "{}", enum_to_str(self.0 as u64, std::any::TypeId::of::())), + } + } +} + +/// These values are readable with TPM2_GetCapability(). They are the TPM_PT_PS_xxx values. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)] +pub struct PLATFORM(pub u32); + +impl PLATFORM { + pub const FAMILY: Self = Self(0x322E3000); // Original value: TPM_SPEC::FAMILY.into() + pub const LEVEL: Self = Self(0x0); // Original value: TPM_SPEC::LEVEL.into() + pub const VERSION: Self = Self(0xA2); // Original value: TPM_SPEC::VERSION.into() + pub const YEAR: Self = Self(0x7E3); // Original value: TPM_SPEC::YEAR.into() + pub const DAY_OF_YEAR: Self = Self(0x168); // Original value: TPM_SPEC::DAY_OF_YEAR.into() + + pub fn try_from(value: u32) -> Result { + match value { + 841887744 => Ok(Self::FAMILY), // Original value: TPM_SPEC::FAMILY.into() + 0 => Ok(Self::LEVEL), // Original value: TPM_SPEC::LEVEL.into() + 162 => Ok(Self::VERSION), // Original value: TPM_SPEC::VERSION.into() + 2019 => Ok(Self::YEAR), // Original value: TPM_SPEC::YEAR.into() + 360 => Ok(Self::DAY_OF_YEAR), // Original value: TPM_SPEC::DAY_OF_YEAR.into() + _ => Err(TpmError::InvalidEnumValue), + } + } +} + +impl TpmEnum for PLATFORM { + fn get_value(&self) -> u32 { + self.0.into() + } + + fn try_from_trait(value: u64) -> Result where Self: Sized { + PLATFORM::try_from(value as u32) + } + + fn new_from_trait(value: u64) -> Result where Self: Sized { + Ok(PLATFORM(value as u32)) + } +} + +impl From for u32 { + fn from(value: PLATFORM) -> Self { + value.0 as u32 + } +} + +impl From for i32 { + fn from(value: PLATFORM) -> Self { + value.0 as i32 + } +} + +impl fmt::Display for PLATFORM { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self.0 { + 841887744 => write!(f, "FAMILY"), + 0 => write!(f, "LEVEL"), + 162 => write!(f, "VERSION"), + 2019 => write!(f, "YEAR"), + 360 => write!(f, "DAY_OF_YEAR"), + _ => write!(f, "{}", enum_to_str(self.0 as u64, std::any::TypeId::of::())), + } + } +} + +/// This table contains a collection of values used in various parts of the reference +/// code. The values shown are illustrative. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)] +pub struct Implementation(pub u32); + +impl Implementation { + /// Temporary define + pub const FIELD_UPGRADE_IMPLEMENTED: Self = Self(0x0); // Original value: Logic::NO.into() + + /// Selection of the library that provides the basic hashing functions. + pub const HASH_LIB: Self = Self(0x1); // Original value: ImplementationConstants::Ossl.into() + + /// Selection of the library that provides the low-level symmetric cryptography. Choices + /// are determined by the vendor (See LibSupport.h for implications). + pub const SYM_LIB: Self = Self(0x1); // Original value: ImplementationConstants::Ossl.into() + + /// Selection of the library that provides the big number math including ECC. Choices are + /// determined by the vendor (See LibSupport.h for implications). + pub const MATH_LIB: Self = Self(0x1); // Original value: ImplementationConstants::Ossl.into() + + /// The number of PCR in the TPM + pub const IMPLEMENTATION_PCR: Self = Self(0x18); // Original value: 24 + pub const PCR_SELECT_MAX: Self = Self(0x3); // Original value: ((IMPLEMENTATION_PCR.into()+7)/8) + + /// The number of PCR required by the relevant platform specification + pub const PLATFORM_PCR: Self = Self(0x18); // Original value: 24 + pub const PCR_SELECT_MIN: Self = Self(0x3); // Original value: ((PLATFORM_PCR.into() + 7) / 8) + + /// The D-RTM PCR + /// NOTE This value is not defined when the TPM does not implement D-RTM + pub const DRTM_PCR: Self = Self(0x11); // Original value: 17 + + /// The PCR that will receive the H-CRTM value at TPM2_Startup. This value should not be changed. + pub const HCRTM_PCR: Self = Self(0x0); // Original value: 0 + + /// The number of localities supported by the TPM + /// This is expected to be either 5 for a PC, or 1 for just about everything else. + pub const NUM_LOCALITIES: Self = Self(0x5); // Original value: 5 + + /// The maximum number of handles in the handle area + /// This should be produced by the Part 3 parser but is here for now. + pub const MAX_HANDLE_NUM: Self = Self(0x3); // Original value: 3 + + /// The number of simultaneously active sessions that are supported by the TPM implementation + pub const MAX_ACTIVE_SESSIONS: Self = Self(0x40); // Original value: 64 + + /// The number of sessions that the TPM may have in memory + pub const MAX_LOADED_SESSIONS: Self = Self(0x3); // Original value: 3 + + /// This is the current maximum value + pub const MAX_SESSION_NUM: Self = Self(0x3); // Original value: 3 + + /// The number of simultaneously loaded objects that are supported by the TPM; this number + /// does not include the objects that may be placed in NV memory by TPM2_EvictControl(). + pub const MAX_LOADED_OBJECTS: Self = Self(0x3); // Original value: 3 + + /// The minimum number of evict objects supported by the TPM + pub const MIN_EVICT_OBJECTS: Self = Self(0x2); // Original value: 2 + + /// Number of PCR groups that have individual policies + pub const NUM_POLICY_PCR_GROUP: Self = Self(0x1); // Original value: 1 + + /// Number of PCR groups that have individual authorization values + pub const NUM_AUTHVALUE_PCR_GROUP: Self = Self(0x1); // Original value: 1 + pub const MAX_CONTEXT_SIZE: Self = Self(0x4F0); // Original value: 1264 + pub const MAX_DIGEST_BUFFER: Self = Self(0x400); // Original value: 1024 + + /// Maximum data size allowed in an NV Index + pub const MAX_NV_INDEX_SIZE: Self = Self(0x800); // Original value: 2048 + + /// Maximum data size in one NV read or write command + pub const MAX_NV_BUFFER_SIZE: Self = Self(0x400); // Original value: 1024 + + /// Maximum size of a capability buffer + pub const MAX_CAP_BUFFER: Self = Self(0x400); // Original value: 1024 + + /// Size of NV memory in octets + pub const NV_MEMORY_SIZE: Self = Self(0x4000); // Original value: 16384 + + /// The TPM will not allocate a non-counter index if it would prevent allocation of this + /// number of indices. + pub const MIN_COUNTER_INDICES: Self = Self(0x8); // Original value: 8 + pub const NUM_STATIC_PCR: Self = Self(0x10); // Original value: 16 + + /// Number of algorithms that can be in a list + pub const MAX_ALG_LIST_SIZE: Self = Self(0x40); // Original value: 64 + + /// Size of the Primary Seed in octets + pub const PRIMARY_SEED_SIZE: Self = Self(0x20); // Original value: 32 + + /// Context encryption algorithm + /// Just use the root so that the macros in GpMacros.h will work correctly. + pub const CONTEXT_ENCRYPT_ALGORITHM: Self = Self(0x6); // Original value: TPM_ALG_ID::AES.into() + + /// The update interval expressed as a power of 2 seconds + /// A value of 12 is 4,096 seconds (~68 minutes). + pub const NV_CLOCK_UPDATE_INTERVAL: Self = Self(0xC); // Original value: 12 + + /// Number of PCR groups that allow policy/auth + pub const NUM_POLICY_PCR: Self = Self(0x1); // Original value: 1 + + /// Maximum size of a command + pub const MAX_COMMAND_SIZE: Self = Self(0x1000); // Original value: 4096 + + /// Maximum size of a response + pub const MAX_RESPONSE_SIZE: Self = Self(0x1000); // Original value: 4096 + + /// Number between 1 and 32 inclusive + pub const ORDERLY_BITS: Self = Self(0x8); // Original value: 8 + + /// The maximum number of octets that may be in a sealed blob; 128 is the minimum allowed value + pub const MAX_SYM_DATA: Self = Self(0x80); // Original value: 128 + pub const MAX_RNG_ENTROPY_SIZE: Self = Self(0x40); // Original value: 64 + + /// Number of bytes used for the RAM index space. If this is not large enough, it might + /// not be possible to allocate orderly indices. + pub const RAM_INDEX_SPACE: Self = Self(0x200); // Original value: 512 + + /// 216 + 1 + pub const RSA_DEFAULT_PUBLIC_EXPONENT: Self = Self(0x10001); // Original value: 0x00010001 + + /// Indicates if the TPM_PT_PCR_NO_INCREMENT group is implemented + pub const ENABLE_PCR_NO_INCREMENT: Self = Self(0x1); // Original value: Logic::YES.into() + pub const CRT_FORMAT_RSA: Self = Self(0x1); // Original value: Logic::YES.into() + pub const VENDOR_COMMAND_COUNT: Self = Self(0x0); // Original value: 0 + + /// Maximum size of the vendor-specific buffer + pub const MAX_VENDOR_BUFFER_SIZE: Self = Self(0x400); // Original value: 1024 + + /// L value for a derivation. This is the + /// maximum number of bits allowed from an instantiation of a KDF-DRBG. This is size is OK + /// because RSA keys are never derived keys + pub const MAX_DERIVATION_BITS: Self = Self(0x2000); // Original value: 8192 + pub const RSA_MAX_PRIME: Self = Self(0x80); // Original value: (ImplementationConstants::MAX_RSA_KEY_BYTES.into()/2) + pub const RSA_PRIVATE_SIZE: Self = Self(0x280); // Original value: (RSA_MAX_PRIME.into() * 5) + pub const SIZE_OF_X509_SERIAL_NUMBER: Self = Self(0x14); // Original value: 20 + + /// This is a vendor-specific value so it is in this vendor-speific table. When this is + /// used, RSA_PRIVATE_SIZE will have been defined + pub const PRIVATE_VENDOR_SPECIFIC_BYTES: Self = Self(0x280); // Original value: RSA_PRIVATE_SIZE.into() + + pub fn try_from(value: u32) -> Result { + match value { + 0 => Ok(Self::VENDOR_COMMAND_COUNT), // Original value: 0 + 1 => Ok(Self::CRT_FORMAT_RSA), // Original value: Logic::YES.into() + 24 => Ok(Self::PLATFORM_PCR), // Original value: 24 + 3 => Ok(Self::MAX_LOADED_OBJECTS), // Original value: 3 + 17 => Ok(Self::DRTM_PCR), // Original value: 17 + 5 => Ok(Self::NUM_LOCALITIES), // Original value: 5 + 64 => Ok(Self::MAX_RNG_ENTROPY_SIZE), // Original value: 64 + 2 => Ok(Self::MIN_EVICT_OBJECTS), // Original value: 2 + 1264 => Ok(Self::MAX_CONTEXT_SIZE), // Original value: 1264 + 1024 => Ok(Self::MAX_VENDOR_BUFFER_SIZE), // Original value: 1024 + 2048 => Ok(Self::MAX_NV_INDEX_SIZE), // Original value: 2048 + 16384 => Ok(Self::NV_MEMORY_SIZE), // Original value: 16384 + 8 => Ok(Self::ORDERLY_BITS), // Original value: 8 + 16 => Ok(Self::NUM_STATIC_PCR), // Original value: 16 + 32 => Ok(Self::PRIMARY_SEED_SIZE), // Original value: 32 + 6 => Ok(Self::CONTEXT_ENCRYPT_ALGORITHM), // Original value: TPM_ALG_ID::AES.into() + 12 => Ok(Self::NV_CLOCK_UPDATE_INTERVAL), // Original value: 12 + 4096 => Ok(Self::MAX_RESPONSE_SIZE), // Original value: 4096 + 128 => Ok(Self::RSA_MAX_PRIME), // Original value: (ImplementationConstants::MAX_RSA_KEY_BYTES.into()/2) + 512 => Ok(Self::RAM_INDEX_SPACE), // Original value: 512 + 65537 => Ok(Self::RSA_DEFAULT_PUBLIC_EXPONENT), // Original value: 0x00010001 + 8192 => Ok(Self::MAX_DERIVATION_BITS), // Original value: 8192 + 640 => Ok(Self::PRIVATE_VENDOR_SPECIFIC_BYTES), // Original value: RSA_PRIVATE_SIZE.into() + 20 => Ok(Self::SIZE_OF_X509_SERIAL_NUMBER), // Original value: 20 + _ => Err(TpmError::InvalidEnumValue), + } + } +} + +impl TpmEnum for Implementation { + fn get_value(&self) -> u32 { + self.0.into() + } + + fn try_from_trait(value: u64) -> Result where Self: Sized { + Implementation::try_from(value as u32) + } + + fn new_from_trait(value: u64) -> Result where Self: Sized { + Ok(Implementation(value as u32)) + } +} + +impl From for u32 { + fn from(value: Implementation) -> Self { + value.0 as u32 + } +} + +impl From for i32 { + fn from(value: Implementation) -> Self { + value.0 as i32 + } +} + +impl fmt::Display for Implementation { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self.0 { + 0 => write!(f, "VENDOR_COMMAND_COUNT"), + 1 => write!(f, "CRT_FORMAT_RSA"), + 24 => write!(f, "PLATFORM_PCR"), + 3 => write!(f, "MAX_LOADED_OBJECTS"), + 17 => write!(f, "DRTM_PCR"), + 5 => write!(f, "NUM_LOCALITIES"), + 64 => write!(f, "MAX_RNG_ENTROPY_SIZE"), + 2 => write!(f, "MIN_EVICT_OBJECTS"), + 1264 => write!(f, "MAX_CONTEXT_SIZE"), + 1024 => write!(f, "MAX_VENDOR_BUFFER_SIZE"), + 2048 => write!(f, "MAX_NV_INDEX_SIZE"), + 16384 => write!(f, "NV_MEMORY_SIZE"), + 8 => write!(f, "ORDERLY_BITS"), + 16 => write!(f, "NUM_STATIC_PCR"), + 32 => write!(f, "PRIMARY_SEED_SIZE"), + 6 => write!(f, "CONTEXT_ENCRYPT_ALGORITHM"), + 12 => write!(f, "NV_CLOCK_UPDATE_INTERVAL"), + 4096 => write!(f, "MAX_RESPONSE_SIZE"), + 128 => write!(f, "RSA_MAX_PRIME"), + 512 => write!(f, "RAM_INDEX_SPACE"), + 65537 => write!(f, "RSA_DEFAULT_PUBLIC_EXPONENT"), + 8192 => write!(f, "MAX_DERIVATION_BITS"), + 640 => write!(f, "PRIVATE_VENDOR_SPECIFIC_BYTES"), + 20 => write!(f, "SIZE_OF_X509_SERIAL_NUMBER"), + _ => write!(f, "{}", enum_to_str(self.0 as u64, std::any::TypeId::of::())), + } + } +} + +/// The definitions in Table 29 are used to define many of the interface data types. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)] +pub struct TPM_HC(pub u32); + +impl TPM_HC { + /// To mask off the HR + pub const HR_HANDLE_MASK: Self = Self(0xFFFFFF); // Original value: 0x00FFFFFF + + /// To mask off the variable part + pub const HR_RANGE_MASK: Self = Self(0xFF000000); + pub const HR_SHIFT: Self = Self(0x18); // Original value: 24 + pub const HR_PCR: Self = Self(0x0); // Original value: (TPM_HT::PCR.into() << HR_SHIFT.into()) + pub const HR_HMAC_SESSION: Self = Self(0x2000000); // Original value: (TPM_HT::HMAC_SESSION.into() << HR_SHIFT.into()) + pub const HR_POLICY_SESSION: Self = Self(0x3000000); // Original value: (TPM_HT::POLICY_SESSION.into() << HR_SHIFT.into()) + pub const HR_TRANSIENT: Self = Self(0x80000000); // Original value: (TPM_HT::TRANSIENT.into() << HR_SHIFT.into()) + pub const HR_PERSISTENT: Self = Self(0x81000000); // Original value: (TPM_HT::PERSISTENT.into() << HR_SHIFT.into()) + pub const HR_NV_INDEX: Self = Self(0x1000000); // Original value: (TPM_HT::NV_INDEX.into() << HR_SHIFT.into()) + pub const HR_PERMANENT: Self = Self(0x40000000); // Original value: (TPM_HT::PERMANENT.into() << HR_SHIFT.into()) + + /// First PCR + pub const PCR_FIRST: Self = Self(0x0); // Original value: (HR_PCR.into() + 0) + + /// Last PCR + pub const PCR_LAST: Self = Self(0x17); // Original value: (PCR_FIRST.into() + Implementation::IMPLEMENTATION_PCR.into()-1) + + /// First HMAC session + pub const HMAC_SESSION_FIRST: Self = Self(0x2000000); // Original value: (HR_HMAC_SESSION.into() + 0) + + /// Last HMAC session + pub const HMAC_SESSION_LAST: Self = Self(0x200003F); // Original value: (HMAC_SESSION_FIRST.into()+Implementation::MAX_ACTIVE_SESSIONS.into()-1) + + /// Used in GetCapability + pub const LOADED_SESSION_FIRST: Self = Self(0x2000000); // Original value: HMAC_SESSION_FIRST.into() + + /// Used in GetCapability + pub const LOADED_SESSION_LAST: Self = Self(0x200003F); // Original value: HMAC_SESSION_LAST.into() + + /// First policy session + pub const POLICY_SESSION_FIRST: Self = Self(0x3000000); // Original value: (HR_POLICY_SESSION.into() + 0) + + /// Last policy session + pub const POLICY_SESSION_LAST: Self = Self(0x300003F); // Original value: (POLICY_SESSION_FIRST.into() + Implementation::MAX_ACTIVE_SESSIONS.into()-1) + + /// First transient object + pub const TRANSIENT_FIRST: Self = Self(0x80000000); // Original value: (HR_TRANSIENT.into() + 0) + + /// Used in GetCapability + pub const ACTIVE_SESSION_FIRST: Self = Self(0x3000000); // Original value: POLICY_SESSION_FIRST.into() + + /// Used in GetCapability + pub const ACTIVE_SESSION_LAST: Self = Self(0x300003F); // Original value: POLICY_SESSION_LAST.into() + + /// Last transient object + pub const TRANSIENT_LAST: Self = Self(0x80000002); // Original value: (TRANSIENT_FIRST.into()+Implementation::MAX_LOADED_OBJECTS.into()-1) + + /// First persistent object + pub const PERSISTENT_FIRST: Self = Self(0x81000000); // Original value: (HR_PERSISTENT.into() + 0) + + /// Last persistent object + pub const PERSISTENT_LAST: Self = Self(0x81FFFFFF); // Original value: (PERSISTENT_FIRST.into() + 0x00FFFFFF) + + /// First platform persistent object + pub const PLATFORM_PERSISTENT: Self = Self(0x81800000); // Original value: (PERSISTENT_FIRST.into() + 0x00800000) + + /// First allowed NV Index + pub const NV_INDEX_FIRST: Self = Self(0x1000000); // Original value: (HR_NV_INDEX.into() + 0) + + /// Last allowed NV Index + pub const NV_INDEX_LAST: Self = Self(0x1FFFFFF); // Original value: (NV_INDEX_FIRST.into() + 0x00FFFFFF) + pub const PERMANENT_FIRST: Self = Self(0x40000000); // Original value: TPM_RH::FIRST.into() + pub const PERMANENT_LAST: Self = Self(0x4000011F); // Original value: TPM_RH::LAST.into() + + /// AC aliased NV Index + pub const HR_NV_AC: Self = Self(0x1D00000); // Original value: ((TPM_HT::NV_INDEX.into() << HR_SHIFT.into()) + 0xD00000) + + /// First NV Index aliased to Attached Component + pub const NV_AC_FIRST: Self = Self(0x1D00000); // Original value: (HR_NV_AC.into() + 0) + + /// Last NV Index aliased to Attached Component + pub const NV_AC_LAST: Self = Self(0x1D0FFFF); // Original value: (HR_NV_AC.into() + 0x0000FFFF) + + /// AC Handle + pub const HR_AC: Self = Self(0x90000000); // Original value: (TPM_HT::AC.into() << HR_SHIFT.into()) + + /// First Attached Component + pub const AC_FIRST: Self = Self(0x90000000); // Original value: (HR_AC.into() + 0) + + /// Last Attached Component + pub const AC_LAST: Self = Self(0x9000FFFF); // Original value: (HR_AC.into() + 0x0000FFFF) + + pub fn try_from(value: u32) -> Result { + match value { + 16777215 => Ok(Self::HR_HANDLE_MASK), // Original value: 0x00FFFFFF + 4278190080 => Ok(Self::HR_RANGE_MASK), // Original value: 0xFF000000 + 24 => Ok(Self::HR_SHIFT), // Original value: 24 + 0 => Ok(Self::PCR_FIRST), // Original value: (HR_PCR.into() + 0) + 33554432 => Ok(Self::LOADED_SESSION_FIRST), // Original value: HMAC_SESSION_FIRST.into() + 50331648 => Ok(Self::ACTIVE_SESSION_FIRST), // Original value: POLICY_SESSION_FIRST.into() + 2147483648 => Ok(Self::TRANSIENT_FIRST), // Original value: (HR_TRANSIENT.into() + 0) + 2164260864 => Ok(Self::PERSISTENT_FIRST), // Original value: (HR_PERSISTENT.into() + 0) + 16777216 => Ok(Self::NV_INDEX_FIRST), // Original value: (HR_NV_INDEX.into() + 0) + 1073741824 => Ok(Self::PERMANENT_FIRST), // Original value: TPM_RH::FIRST.into() + 23 => Ok(Self::PCR_LAST), // Original value: (PCR_FIRST.into() + Implementation::IMPLEMENTATION_PCR.into()-1) + 33554495 => Ok(Self::LOADED_SESSION_LAST), // Original value: HMAC_SESSION_LAST.into() + 50331711 => Ok(Self::ACTIVE_SESSION_LAST), // Original value: POLICY_SESSION_LAST.into() + 2147483650 => Ok(Self::TRANSIENT_LAST), // Original value: (TRANSIENT_FIRST.into()+Implementation::MAX_LOADED_OBJECTS.into()-1) + 2181038079 => Ok(Self::PERSISTENT_LAST), // Original value: (PERSISTENT_FIRST.into() + 0x00FFFFFF) + 2172649472 => Ok(Self::PLATFORM_PERSISTENT), // Original value: (PERSISTENT_FIRST.into() + 0x00800000) + 33554431 => Ok(Self::NV_INDEX_LAST), // Original value: (NV_INDEX_FIRST.into() + 0x00FFFFFF) + 1073742111 => Ok(Self::PERMANENT_LAST), // Original value: TPM_RH::LAST.into() + 30408704 => Ok(Self::NV_AC_FIRST), // Original value: (HR_NV_AC.into() + 0) + 30474239 => Ok(Self::NV_AC_LAST), // Original value: (HR_NV_AC.into() + 0x0000FFFF) + 2415919104 => Ok(Self::AC_FIRST), // Original value: (HR_AC.into() + 0) + 2415984639 => Ok(Self::AC_LAST), // Original value: (HR_AC.into() + 0x0000FFFF) + _ => Err(TpmError::InvalidEnumValue), + } + } +} + +impl TpmEnum for TPM_HC { + fn get_value(&self) -> u32 { + self.0.into() + } + + fn try_from_trait(value: u64) -> Result where Self: Sized { + TPM_HC::try_from(value as u32) + } + + fn new_from_trait(value: u64) -> Result where Self: Sized { + Ok(TPM_HC(value as u32)) + } +} + +impl From for u32 { + fn from(value: TPM_HC) -> Self { + value.0 as u32 + } +} + +impl From for i32 { + fn from(value: TPM_HC) -> Self { + value.0 as i32 + } +} + +impl fmt::Display for TPM_HC { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self.0 { + 16777215 => write!(f, "HR_HANDLE_MASK"), + 4278190080 => write!(f, "HR_RANGE_MASK"), + 24 => write!(f, "HR_SHIFT"), + 0 => write!(f, "PCR_FIRST"), + 33554432 => write!(f, "LOADED_SESSION_FIRST"), + 50331648 => write!(f, "ACTIVE_SESSION_FIRST"), + 2147483648 => write!(f, "TRANSIENT_FIRST"), + 2164260864 => write!(f, "PERSISTENT_FIRST"), + 16777216 => write!(f, "NV_INDEX_FIRST"), + 1073741824 => write!(f, "PERMANENT_FIRST"), + 23 => write!(f, "PCR_LAST"), + 33554495 => write!(f, "LOADED_SESSION_LAST"), + 50331711 => write!(f, "ACTIVE_SESSION_LAST"), + 2147483650 => write!(f, "TRANSIENT_LAST"), + 2181038079 => write!(f, "PERSISTENT_LAST"), + 2172649472 => write!(f, "PLATFORM_PERSISTENT"), + 33554431 => write!(f, "NV_INDEX_LAST"), + 1073742111 => write!(f, "PERMANENT_LAST"), + 30408704 => write!(f, "NV_AC_FIRST"), + 30474239 => write!(f, "NV_AC_LAST"), + 2415919104 => write!(f, "AC_FIRST"), + 2415984639 => write!(f, "AC_LAST"), + _ => write!(f, "{}", enum_to_str(self.0 as u64, std::any::TypeId::of::())), + } + } +} + +/// This structure defines the attributes of an algorithm. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)] +pub struct TPMA_ALGORITHM(pub u32); + +impl TPMA_ALGORITHM { + /// SET (1): an asymmetric algorithm with public and private portions + /// CLEAR (0): not an asymmetric algorithm + pub const asymmetric: Self = Self(0x1); + + /// SET (1): a symmetric block cipher + /// CLEAR (0): not a symmetric block cipher + pub const symmetric: Self = Self(0x2); + + /// SET (1): a hash algorithm + /// CLEAR (0): not a hash algorithm + pub const hash: Self = Self(0x4); + + /// SET (1): an algorithm that may be used as an object type + /// CLEAR (0): an algorithm that is not used as an object type + pub const object: Self = Self(0x8); + + /// SET (1): a signing algorithm. The setting of asymmetric, symmetric, and hash will + /// indicate the type of signing algorithm. + /// CLEAR (0): not a signing algorithm + pub const signing: Self = Self(0x100); + + /// SET (1): an encryption/decryption algorithm. The setting of asymmetric, symmetric, and + /// hash will indicate the type of encryption/decryption algorithm. + /// CLEAR (0): not an encryption/decryption algorithm + pub const encrypting: Self = Self(0x200); + + /// SET (1): a method such as a key derivative function (KDF) + /// CLEAR (0): not a method + pub const method: Self = Self(0x400); + + pub fn try_from(value: u32) -> Result { + match value { + 1 => Ok(Self::asymmetric), // Original value: 0x1 + 2 => Ok(Self::symmetric), // Original value: 0x2 + 4 => Ok(Self::hash), // Original value: 0x4 + 8 => Ok(Self::object), // Original value: 0x8 + 256 => Ok(Self::signing), // Original value: 0x100 + 512 => Ok(Self::encrypting), // Original value: 0x200 + 1024 => Ok(Self::method), // Original value: 0x400 + _ => Err(TpmError::InvalidEnumValue), + } + } +} + +impl TpmEnum for TPMA_ALGORITHM { + fn get_value(&self) -> u32 { + self.0.into() + } + + fn try_from_trait(value: u64) -> Result where Self: Sized { + TPMA_ALGORITHM::try_from(value as u32) + } + + fn new_from_trait(value: u64) -> Result where Self: Sized { + Ok(TPMA_ALGORITHM(value as u32)) + } +} + +impl From for u32 { + fn from(value: TPMA_ALGORITHM) -> Self { + value.0 as u32 + } +} + +impl From for i32 { + fn from(value: TPMA_ALGORITHM) -> Self { + value.0 as i32 + } +} + +impl fmt::Display for TPMA_ALGORITHM { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self.0 { + 1 => write!(f, "asymmetric"), + 2 => write!(f, "symmetric"), + 4 => write!(f, "hash"), + 8 => write!(f, "object"), + 256 => write!(f, "signing"), + 512 => write!(f, "encrypting"), + 1024 => write!(f, "method"), + _ => write!(f, "{}", enum_to_str(self.0 as u64, std::any::TypeId::of::())), + } + } +} + +impl std::ops::BitOr for TPMA_ALGORITHM { + type Output = Self; + + fn bitor(self, rhs: Self) -> Self::Output { + Self(self.0 | rhs.0) + } + +} + +impl From for TPMA_ALGORITHM { + fn from(value: u32) -> Self { + Self(value.into()) + } +} + +/// This attribute structure indicates an objects use, its authorization types, and its +/// relationship to other objects. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)] +pub struct TPMA_OBJECT(pub u32); + +impl TPMA_OBJECT { + /// SET (1): The hierarchy of the object, as indicated by its Qualified Name, may not change. + /// CLEAR (0): The hierarchy of the object may change as a result of this object or an + /// ancestor key being duplicated for use in another hierarchy. + /// NOTE fixedTPM does not indicate that key material resides on a single TPM (see + /// sensitiveDataOrigin). + pub const fixedTPM: Self = Self(0x2); + + /// SET (1): Previously saved contexts of this object may not be loaded after Startup(CLEAR). + /// CLEAR (0): Saved contexts of this object may be used after a Shutdown(STATE) and + /// subsequent Startup(). + pub const stClear: Self = Self(0x4); + + /// SET (1): The parent of the object may not change. + /// CLEAR (0): The parent of the object may change as the result of a TPM2_Duplicate() of + /// the object. + pub const fixedParent: Self = Self(0x10); + + /// SET (1): Indicates that, when the object was created with TPM2_Create() or + /// TPM2_CreatePrimary(), the TPM generated all of the sensitive data other than the authValue. + /// CLEAR (0): A portion of the sensitive data, other than the authValue, was provided by + /// the caller. + pub const sensitiveDataOrigin: Self = Self(0x20); + + /// SET (1): Approval of USER role actions with this object may be with an HMAC session or + /// with a password using the authValue of the object or a policy session. + /// CLEAR (0): Approval of USER role actions with this object may only be done with a + /// policy session. + pub const userWithAuth: Self = Self(0x40); + + /// SET (1): Approval of ADMIN role actions with this object may only be done with a + /// policy session. + /// CLEAR (0): Approval of ADMIN role actions with this object may be with an HMAC session + /// or with a password using the authValue of the object or a policy session. + pub const adminWithPolicy: Self = Self(0x80); + + /// SET (1): The object is not subject to dictionary attack protections. + /// CLEAR (0): The object is subject to dictionary attack protections. + pub const noDA: Self = Self(0x400); + + /// SET (1): If the object is duplicated, then symmetricAlg shall not be TPM_ALG_NULL and + /// newParentHandle shall not be TPM_RH_NULL. + /// CLEAR (0): The object may be duplicated without an inner wrapper on the private + /// portion of the object and the new parent may be TPM_RH_NULL. + pub const encryptedDuplication: Self = Self(0x800); + + /// SET (1): Key usage is restricted to manipulate structures of known format; the parent + /// of this key shall have restricted SET. + /// CLEAR (0): Key usage is not restricted to use on special formats. + pub const restricted: Self = Self(0x10000); + + /// SET (1): The private portion of the key may be used to decrypt. + /// CLEAR (0): The private portion of the key may not be used to decrypt. + pub const decrypt: Self = Self(0x20000); + + /// SET (1): For a symmetric cipher object, the private portion of the key may be used to + /// encrypt. For other objects, the private portion of the key may be used to sign. + /// CLEAR (0): The private portion of the key may not be used to sign or encrypt. + pub const sign: Self = Self(0x40000); + + /// Alias to the sign value. + pub const encrypt: Self = Self(0x40000); + + /// SET (1): An asymmetric key that may not be used to sign with TPM2_Sign() + /// CLEAR (0): A key that may be used with TPM2_Sign() if sign is SET + /// NOTE: This attribute only has significance if sign is SET. + pub const x509sign: Self = Self(0x80000); + + pub fn try_from(value: u32) -> Result { + match value { + 2 => Ok(Self::fixedTPM), // Original value: 0x2 + 4 => Ok(Self::stClear), // Original value: 0x4 + 16 => Ok(Self::fixedParent), // Original value: 0x10 + 32 => Ok(Self::sensitiveDataOrigin), // Original value: 0x20 + 64 => Ok(Self::userWithAuth), // Original value: 0x40 + 128 => Ok(Self::adminWithPolicy), // Original value: 0x80 + 1024 => Ok(Self::noDA), // Original value: 0x400 + 2048 => Ok(Self::encryptedDuplication), // Original value: 0x800 + 65536 => Ok(Self::restricted), // Original value: 0x10000 + 131072 => Ok(Self::decrypt), // Original value: 0x20000 + 262144 => Ok(Self::encrypt), // Original value: 0x40000 + 524288 => Ok(Self::x509sign), // Original value: 0x80000 + _ => Err(TpmError::InvalidEnumValue), + } + } +} + +impl TpmEnum for TPMA_OBJECT { + fn get_value(&self) -> u32 { + self.0.into() + } + + fn try_from_trait(value: u64) -> Result where Self: Sized { + TPMA_OBJECT::try_from(value as u32) + } + + fn new_from_trait(value: u64) -> Result where Self: Sized { + Ok(TPMA_OBJECT(value as u32)) + } +} + +impl From for u32 { + fn from(value: TPMA_OBJECT) -> Self { + value.0 as u32 + } +} + +impl From for i32 { + fn from(value: TPMA_OBJECT) -> Self { + value.0 as i32 + } +} + +impl fmt::Display for TPMA_OBJECT { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self.0 { + 2 => write!(f, "fixedTPM"), + 4 => write!(f, "stClear"), + 16 => write!(f, "fixedParent"), + 32 => write!(f, "sensitiveDataOrigin"), + 64 => write!(f, "userWithAuth"), + 128 => write!(f, "adminWithPolicy"), + 1024 => write!(f, "noDA"), + 2048 => write!(f, "encryptedDuplication"), + 65536 => write!(f, "restricted"), + 131072 => write!(f, "decrypt"), + 262144 => write!(f, "encrypt"), + 524288 => write!(f, "x509sign"), + _ => write!(f, "{}", enum_to_str(self.0 as u64, std::any::TypeId::of::())), + } + } +} + +impl std::ops::BitOr for TPMA_OBJECT { + type Output = Self; + + fn bitor(self, rhs: Self) -> Self::Output { + Self(self.0 | rhs.0) + } + +} + +impl From for TPMA_OBJECT { + fn from(value: u32) -> Self { + Self(value.into()) + } +} + +/// This octet in each session is used to identify the session type, indicate its +/// relationship to any handles in the command, and indicate its use in parameter encryption. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)] +pub struct TPMA_SESSION(pub u8); + +impl TPMA_SESSION { + /// SET (1): In a command, this setting indicates that the session is to remain active + /// after successful completion of the command. In a response, it indicates that the + /// session is still active. If SET in the command, this attribute shall be SET in the response. + /// CLEAR (0): In a command, this setting indicates that the TPM should close the session + /// and flush any related context when the command completes successfully. In a response, + /// it indicates that the session is closed and the context is no longer active. + /// This attribute has no meaning for a password authorization and the TPM will allow any + /// setting of the attribute in the command and SET the attribute in the response. + /// This attribute will only be CLEAR in one response for a logical session. If the + /// attribute is CLEAR, the context associated with the session is no longer in use and + /// the space is available. A session created after another session is ended may have the + /// same handle but logically is not the same session. + /// This attribute has no effect if the command does not complete successfully. + pub const continueSession: Self = Self(0x1); + + /// SET (1): In a command, this setting indicates that the command should only be executed + /// if the session is exclusive at the start of the command. In a response, it indicates + /// that the session is exclusive. This setting is only allowed if the audit attribute is + /// SET (TPM_RC_ATTRIBUTES). + /// CLEAR (0): In a command, indicates that the session need not be exclusive at the start + /// of the command. In a response, indicates that the session is not exclusive. + pub const auditExclusive: Self = Self(0x2); + + /// SET (1): In a command, this setting indicates that the audit digest of the session + /// should be initialized and the exclusive status of the session SET. This setting is + /// only allowed if the audit attribute is SET (TPM_RC_ATTRIBUTES). + /// CLEAR (0): In a command, indicates that the audit digest should not be initialized. + /// This bit is always CLEAR in a response. + pub const auditReset: Self = Self(0x4); + + /// SET (1): In a command, this setting indicates that the first parameter in the command + /// is symmetrically encrypted using the parameter encryption scheme described in TPM 2.0 + /// Part 1. The TPM will decrypt the parameter after performing any HMAC computations and + /// before unmarshaling the parameter. In a response, the attribute is copied from the + /// request but has no effect on the response. + /// CLEAR (0): Session not used for encryption. + /// For a password authorization, this attribute will be CLEAR in both the command and response. + /// This attribute may be SET in a session that is not associated with a command handle. + /// Such a session is provided for purposes of encrypting a parameter and not for authorization. + /// This attribute may be SET in combination with any other session attributes. + pub const decrypt: Self = Self(0x20); + + /// SET (1): In a command, this setting indicates that the TPM should use this session to + /// encrypt the first parameter in the response. In a response, it indicates that the + /// attribute was set in the command and that the TPM used the session to encrypt the + /// first parameter in the response using the parameter encryption scheme described in TPM + /// 2.0 Part 1. + /// CLEAR (0): Session not used for encryption. + /// For a password authorization, this attribute will be CLEAR in both the command and response. + /// This attribute may be SET in a session that is not associated with a command handle. + /// Such a session is provided for purposes of encrypting a parameter and not for authorization. + pub const encrypt: Self = Self(0x40); + + /// SET (1): In a command or response, this setting indicates that the session is for + /// audit and that auditExclusive and auditReset have meaning. This session may also be + /// used for authorization, encryption, or decryption. The encrypted and encrypt fields + /// may be SET or CLEAR. + /// CLEAR (0): Session is not used for audit. + /// If SET in the command, then this attribute will be SET in the response. + pub const audit: Self = Self(0x80); + + pub fn try_from(value: u8) -> Result { + match value { + 1 => Ok(Self::continueSession), // Original value: 0x1 + 2 => Ok(Self::auditExclusive), // Original value: 0x2 + 4 => Ok(Self::auditReset), // Original value: 0x4 + 32 => Ok(Self::decrypt), // Original value: 0x20 + 64 => Ok(Self::encrypt), // Original value: 0x40 + 128 => Ok(Self::audit), // Original value: 0x80 + _ => Err(TpmError::InvalidEnumValue), + } + } +} + +impl TpmEnum for TPMA_SESSION { + fn get_value(&self) -> u8 { + self.0.into() + } + + fn try_from_trait(value: u64) -> Result where Self: Sized { + TPMA_SESSION::try_from(value as u8) + } + + fn new_from_trait(value: u64) -> Result where Self: Sized { + Ok(TPMA_SESSION(value as u8)) + } +} + +impl From for u8 { + fn from(value: TPMA_SESSION) -> Self { + value.0 as u8 + } +} + +impl From for i8 { + fn from(value: TPMA_SESSION) -> Self { + value.0 as i8 + } +} + +impl fmt::Display for TPMA_SESSION { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self.0 { + 1 => write!(f, "continueSession"), + 2 => write!(f, "auditExclusive"), + 4 => write!(f, "auditReset"), + 32 => write!(f, "decrypt"), + 64 => write!(f, "encrypt"), + 128 => write!(f, "audit"), + _ => write!(f, "{}", enum_to_str(self.0 as u64, std::any::TypeId::of::())), + } + } +} + +impl std::ops::BitOr for TPMA_SESSION { + type Output = Self; + + fn bitor(self, rhs: Self) -> Self::Output { + Self(self.0 | rhs.0) + } + +} + +impl From for TPMA_SESSION { + fn from(value: u8) -> Self { + Self(value.into()) + } +} + +/// In a TPMS_CREATION_DATA structure, this structure is used to indicate the locality of +/// the command that created the object. No more than one of the locality attributes shall +/// be set in the creation data. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)] +pub struct TPMA_LOCALITY(pub u8); + +impl TPMA_LOCALITY { + pub const LOC_ZERO: Self = Self(0x1); + pub const LOC_ONE: Self = Self(0x2); + pub const LOC_TWO: Self = Self(0x4); + pub const LOC_THREE: Self = Self(0x8); + pub const LOC_FOUR: Self = Self(0x10); + + /// If any of these bits is set, an extended locality is indicated + pub const Extended_BIT_MASK: Self = Self(0xE0); + pub const Extended_BIT_OFFSET: Self = Self(0x5); // Original value: 5 + pub const Extended_BIT_LENGTH: Self = Self(0x3); // Original value: 3 + + pub fn try_from(value: u8) -> Result { + match value { + 1 => Ok(Self::LOC_ZERO), // Original value: 0x1 + 2 => Ok(Self::LOC_ONE), // Original value: 0x2 + 4 => Ok(Self::LOC_TWO), // Original value: 0x4 + 8 => Ok(Self::LOC_THREE), // Original value: 0x8 + 16 => Ok(Self::LOC_FOUR), // Original value: 0x10 + 224 => Ok(Self::Extended_BIT_MASK), // Original value: 0xE0 + 5 => Ok(Self::Extended_BIT_OFFSET), // Original value: 5 + 3 => Ok(Self::Extended_BIT_LENGTH), // Original value: 3 + _ => Err(TpmError::InvalidEnumValue), + } + } +} + +impl TpmEnum for TPMA_LOCALITY { + fn get_value(&self) -> u8 { + self.0.into() + } + + fn try_from_trait(value: u64) -> Result where Self: Sized { + TPMA_LOCALITY::try_from(value as u8) + } + + fn new_from_trait(value: u64) -> Result where Self: Sized { + Ok(TPMA_LOCALITY(value as u8)) + } +} + +impl From for u8 { + fn from(value: TPMA_LOCALITY) -> Self { + value.0 as u8 + } +} + +impl From for i8 { + fn from(value: TPMA_LOCALITY) -> Self { + value.0 as i8 + } +} + +impl fmt::Display for TPMA_LOCALITY { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self.0 { + 1 => write!(f, "LOC_ZERO"), + 2 => write!(f, "LOC_ONE"), + 4 => write!(f, "LOC_TWO"), + 8 => write!(f, "LOC_THREE"), + 16 => write!(f, "LOC_FOUR"), + 224 => write!(f, "Extended_BIT_MASK"), + 5 => write!(f, "Extended_BIT_OFFSET"), + 3 => write!(f, "Extended_BIT_LENGTH"), + _ => write!(f, "{}", enum_to_str(self.0 as u64, std::any::TypeId::of::())), + } + } +} + +impl std::ops::BitOr for TPMA_LOCALITY { + type Output = Self; + + fn bitor(self, rhs: Self) -> Self::Output { + Self(self.0 | rhs.0) + } + +} + +impl From for TPMA_LOCALITY { + fn from(value: u8) -> Self { + Self(value.into()) + } +} + +/// The attributes in this structure are persistent and are not changed as a result of +/// _TPM_Init or any TPM2_Startup(). Some of the attributes in this structure may change +/// as the result of specific Protected Capabilities. This structure may be read using +/// TPM2_GetCapability(capability = TPM_CAP_TPM_PROPERTIES, property = TPM_PT_PERMANENT). +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)] +pub struct TPMA_PERMANENT(pub u32); + +impl TPMA_PERMANENT { + /// SET (1): TPM2_HierarchyChangeAuth() with ownerAuth has been executed since the last TPM2_Clear(). + /// CLEAR (0): ownerAuth has not been changed since TPM2_Clear(). + pub const ownerAuthSet: Self = Self(0x1); + + /// SET (1): TPM2_HierarchyChangeAuth() with endorsementAuth has been executed since the + /// last TPM2_Clear(). + /// CLEAR (0): endorsementAuth has not been changed since TPM2_Clear(). + pub const endorsementAuthSet: Self = Self(0x2); + + /// SET (1): TPM2_HierarchyChangeAuth() with lockoutAuth has been executed since the last + /// TPM2_Clear(). + /// CLEAR (0): lockoutAuth has not been changed since TPM2_Clear(). + pub const lockoutAuthSet: Self = Self(0x4); + + /// SET (1): TPM2_Clear() is disabled. + /// CLEAR (0): TPM2_Clear() is enabled. + /// NOTE See TPM2_ClearControl in TPM 2.0 Part 3 for details on changing this attribute. + pub const disableClear: Self = Self(0x100); + + /// SET (1): The TPM is in lockout, when failedTries is equal to maxTries. + pub const inLockout: Self = Self(0x200); + + /// SET (1): The EPS was created by the TPM. + /// CLEAR (0): The EPS was created outside of the TPM using a manufacturer-specific process. + pub const tpmGeneratedEPS: Self = Self(0x400); + + pub fn try_from(value: u32) -> Result { + match value { + 1 => Ok(Self::ownerAuthSet), // Original value: 0x1 + 2 => Ok(Self::endorsementAuthSet), // Original value: 0x2 + 4 => Ok(Self::lockoutAuthSet), // Original value: 0x4 + 256 => Ok(Self::disableClear), // Original value: 0x100 + 512 => Ok(Self::inLockout), // Original value: 0x200 + 1024 => Ok(Self::tpmGeneratedEPS), // Original value: 0x400 + _ => Err(TpmError::InvalidEnumValue), + } + } +} + +impl TpmEnum for TPMA_PERMANENT { + fn get_value(&self) -> u32 { + self.0.into() + } + + fn try_from_trait(value: u64) -> Result where Self: Sized { + TPMA_PERMANENT::try_from(value as u32) + } + + fn new_from_trait(value: u64) -> Result where Self: Sized { + Ok(TPMA_PERMANENT(value as u32)) + } +} + +impl From for u32 { + fn from(value: TPMA_PERMANENT) -> Self { + value.0 as u32 + } +} + +impl From for i32 { + fn from(value: TPMA_PERMANENT) -> Self { + value.0 as i32 + } +} + +impl fmt::Display for TPMA_PERMANENT { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self.0 { + 1 => write!(f, "ownerAuthSet"), + 2 => write!(f, "endorsementAuthSet"), + 4 => write!(f, "lockoutAuthSet"), + 256 => write!(f, "disableClear"), + 512 => write!(f, "inLockout"), + 1024 => write!(f, "tpmGeneratedEPS"), + _ => write!(f, "{}", enum_to_str(self.0 as u64, std::any::TypeId::of::())), + } + } +} + +impl std::ops::BitOr for TPMA_PERMANENT { + type Output = Self; + + fn bitor(self, rhs: Self) -> Self::Output { + Self(self.0 | rhs.0) + } + +} + +impl From for TPMA_PERMANENT { + fn from(value: u32) -> Self { + Self(value.into()) + } +} + +/// This structure may be read using TPM2_GetCapability(capability = +/// TPM_CAP_TPM_PROPERTIES, property = TPM_PT_STARTUP_CLEAR). +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)] +pub struct TPMA_STARTUP_CLEAR(pub u32); + +impl TPMA_STARTUP_CLEAR { + /// SET (1): The platform hierarchy is enabled and platformAuth or platformPolicy may be + /// used for authorization. + /// CLEAR (0): platformAuth and platformPolicy may not be used for authorizations, and + /// objects in the platform hierarchy, including persistent objects, cannot be used. + /// NOTE See TPM2_HierarchyControl in TPM 2.0 Part 3 for details on changing this attribute. + pub const phEnable: Self = Self(0x1); + + /// SET (1): The Storage hierarchy is enabled and ownerAuth or ownerPolicy may be used for + /// authorization. NV indices defined using owner authorization are accessible. + /// CLEAR (0): ownerAuth and ownerPolicy may not be used for authorizations, and objects + /// in the Storage hierarchy, persistent objects, and NV indices defined using owner + /// authorization cannot be used. + /// NOTE See TPM2_HierarchyControl in TPM 2.0 Part 3 for details on changing this attribute. + pub const shEnable: Self = Self(0x2); + + /// SET (1): The EPS hierarchy is enabled and Endorsement Authorization may be used to + /// authorize commands. + /// CLEAR (0): Endorsement Authorization may not be used for authorizations, and objects + /// in the endorsement hierarchy, including persistent objects, cannot be used. + /// NOTE See TPM2_HierarchyControl in TPM 2.0 Part 3 for details on changing this attribute. + pub const ehEnable: Self = Self(0x4); + + /// SET (1): NV indices that have TPMA_NV_PLATFORMCREATE SET may be read or written. The + /// platform can create define and undefine indices. + /// CLEAR (0): NV indices that have TPMA_NV_PLATFORMCREATE SET may not be read or written + /// (TPM_RC_HANDLE). The platform cannot define (TPM_RC_HIERARCHY) or undefined + /// (TPM_RC_HANDLE) indices. + /// NOTE See TPM2_HierarchyControl in TPM 2.0 Part 3 for details on changing this attribute. + /// NOTE + /// read refers to these commands: TPM2_NV_Read, TPM2_NV_ReadPublic, TPM_NV_Certify, TPM2_PolicyNV + /// write refers to these commands: TPM2_NV_Write, TPM2_NV_Increment, TPM2_NV_Extend, TPM2_NV_SetBits + /// NOTE The TPM must query the index TPMA_NV_PLATFORMCREATE attribute to determine + /// whether phEnableNV is applicable. Since the TPM will return TPM_RC_HANDLE if the index + /// does not exist, it also returns this error code if the index is disabled. Otherwise, + /// the TPM would leak the existence of an index even when disabled. + pub const phEnableNV: Self = Self(0x8); + + /// SET (1): The TPM received a TPM2_Shutdown() and a matching TPM2_Startup(). + /// CLEAR (0): TPM2_Startup(TPM_SU_CLEAR) was not preceded by a TPM2_Shutdown() of any type. + /// NOTE A shutdown is orderly if the TPM receives a TPM2_Shutdown() of any type followed + /// by a TPM2_Startup() of any type. However, the TPM will return an error if + /// TPM2_Startup(TPM_SU_STATE) was not preceded by TPM2_Shutdown(TPM_SU_STATE). + pub const orderly: Self = Self(0x80000000); + + pub fn try_from(value: u32) -> Result { + match value { + 1 => Ok(Self::phEnable), // Original value: 0x1 + 2 => Ok(Self::shEnable), // Original value: 0x2 + 4 => Ok(Self::ehEnable), // Original value: 0x4 + 8 => Ok(Self::phEnableNV), // Original value: 0x8 + 2147483648 => Ok(Self::orderly), // Original value: 0x80000000 + _ => Err(TpmError::InvalidEnumValue), + } + } +} + +impl TpmEnum for TPMA_STARTUP_CLEAR { + fn get_value(&self) -> u32 { + self.0.into() + } + + fn try_from_trait(value: u64) -> Result where Self: Sized { + TPMA_STARTUP_CLEAR::try_from(value as u32) + } + + fn new_from_trait(value: u64) -> Result where Self: Sized { + Ok(TPMA_STARTUP_CLEAR(value as u32)) + } +} + +impl From for u32 { + fn from(value: TPMA_STARTUP_CLEAR) -> Self { + value.0 as u32 + } +} + +impl From for i32 { + fn from(value: TPMA_STARTUP_CLEAR) -> Self { + value.0 as i32 + } +} + +impl fmt::Display for TPMA_STARTUP_CLEAR { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self.0 { + 1 => write!(f, "phEnable"), + 2 => write!(f, "shEnable"), + 4 => write!(f, "ehEnable"), + 8 => write!(f, "phEnableNV"), + 2147483648 => write!(f, "orderly"), + _ => write!(f, "{}", enum_to_str(self.0 as u64, std::any::TypeId::of::())), + } + } +} + +impl std::ops::BitOr for TPMA_STARTUP_CLEAR { + type Output = Self; + + fn bitor(self, rhs: Self) -> Self::Output { + Self(self.0 | rhs.0) + } + +} + +impl From for TPMA_STARTUP_CLEAR { + fn from(value: u32) -> Self { + Self(value.into()) + } +} + +/// This structure of this attribute is used to report the memory management method used +/// by the TPM for transient objects and authorization sessions. This structure may be +/// read using TPM2_GetCapability(capability = TPM_CAP_TPM_PROPERTIES, property = TPM_PT_MEMORY). +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)] +pub struct TPMA_MEMORY(pub u32); + +impl TPMA_MEMORY { + /// SET (1): indicates that the RAM memory used for authorization session contexts is + /// shared with the memory used for transient objects + /// CLEAR (0): indicates that the memory used for authorization sessions is not shared + /// with memory used for transient objects + pub const sharedRAM: Self = Self(0x1); + + /// SET (1): indicates that the NV memory used for persistent objects is shared with the + /// NV memory used for NV Index values + /// CLEAR (0): indicates that the persistent objects and NV Index values are allocated + /// from separate sections of NV + pub const sharedNV: Self = Self(0x2); + + /// SET (1): indicates that the TPM copies persistent objects to a transient-object slot + /// in RAM when the persistent object is referenced in a command. The TRM is required to + /// make sure that an object slot is available. + /// CLEAR (0): indicates that the TPM does not use transient-object slots when persistent + /// objects are referenced + pub const objectCopiedToRam: Self = Self(0x4); + + pub fn try_from(value: u32) -> Result { + match value { + 1 => Ok(Self::sharedRAM), // Original value: 0x1 + 2 => Ok(Self::sharedNV), // Original value: 0x2 + 4 => Ok(Self::objectCopiedToRam), // Original value: 0x4 + _ => Err(TpmError::InvalidEnumValue), + } + } +} + +impl TpmEnum for TPMA_MEMORY { + fn get_value(&self) -> u32 { + self.0.into() + } + + fn try_from_trait(value: u64) -> Result where Self: Sized { + TPMA_MEMORY::try_from(value as u32) + } + + fn new_from_trait(value: u64) -> Result where Self: Sized { + Ok(TPMA_MEMORY(value as u32)) + } +} + +impl From for u32 { + fn from(value: TPMA_MEMORY) -> Self { + value.0 as u32 + } +} + +impl From for i32 { + fn from(value: TPMA_MEMORY) -> Self { + value.0 as i32 + } +} + +impl fmt::Display for TPMA_MEMORY { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self.0 { + 1 => write!(f, "sharedRAM"), + 2 => write!(f, "sharedNV"), + 4 => write!(f, "objectCopiedToRam"), + _ => write!(f, "{}", enum_to_str(self.0 as u64, std::any::TypeId::of::())), + } + } +} + +impl std::ops::BitOr for TPMA_MEMORY { + type Output = Self; + + fn bitor(self, rhs: Self) -> Self::Output { + Self(self.0 | rhs.0) + } + +} + +impl From for TPMA_MEMORY { + fn from(value: u32) -> Self { + Self(value.into()) + } +} + +/// This structure defines the attributes of a command from a context management +/// perspective. The fields of the structure indicate to the TPM Resource Manager (TRM) +/// the number of resources required by a command and how the command affects the TPMs resources. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)] +pub struct TPMA_CC(pub u32); + +impl TPMA_CC { + /// Indicates the command being selected + pub const commandIndex_BIT_MASK: Self = Self(0xFFFF); + pub const commandIndex_BIT_OFFSET: Self = Self(0x0); // Original value: 0 + pub const commandIndex_BIT_LENGTH: Self = Self(0x10); // Original value: 16 + + /// SET (1): indicates that the command may write to NV + /// CLEAR (0): indicates that the command does not write to NV + pub const nv: Self = Self(0x400000); + + /// SET (1): This command could flush any number of loaded contexts. + /// CLEAR (0): no additional changes other than indicated by the flushed attribute + pub const extensive: Self = Self(0x800000); + + /// SET (1): The context associated with any transient handle in the command will be + /// flushed when this command completes. + /// CLEAR (0): No context is flushed as a side effect of this command. + pub const flushed: Self = Self(0x1000000); + + /// Indicates the number of the handles in the handle area for this command + pub const cHandles_BIT_MASK: Self = Self(0xE000000); + pub const cHandles_BIT_OFFSET: Self = Self(0x19); // Original value: 25 + pub const cHandles_BIT_LENGTH: Self = Self(0x3); // Original value: 3 + + /// SET (1): indicates the presence of the handle area in the response + pub const rHandle: Self = Self(0x10000000); + + /// SET (1): indicates that the command is vendor-specific + /// CLEAR (0): indicates that the command is defined in a version of this specification + pub const V: Self = Self(0x20000000); + + /// Allocated for software; shall be zero + pub const Res_BIT_MASK: Self = Self(0xC0000000); + pub const Res_BIT_OFFSET: Self = Self(0x1E); // Original value: 30 + pub const Res_BIT_LENGTH: Self = Self(0x2); // Original value: 2 + + pub fn try_from(value: u32) -> Result { + match value { + 65535 => Ok(Self::commandIndex_BIT_MASK), // Original value: 0xFFFF + 0 => Ok(Self::commandIndex_BIT_OFFSET), // Original value: 0 + 16 => Ok(Self::commandIndex_BIT_LENGTH), // Original value: 16 + 4194304 => Ok(Self::nv), // Original value: 0x400000 + 8388608 => Ok(Self::extensive), // Original value: 0x800000 + 16777216 => Ok(Self::flushed), // Original value: 0x1000000 + 234881024 => Ok(Self::cHandles_BIT_MASK), // Original value: 0xE000000 + 25 => Ok(Self::cHandles_BIT_OFFSET), // Original value: 25 + 3 => Ok(Self::cHandles_BIT_LENGTH), // Original value: 3 + 268435456 => Ok(Self::rHandle), // Original value: 0x10000000 + 536870912 => Ok(Self::V), // Original value: 0x20000000 + 3221225472 => Ok(Self::Res_BIT_MASK), // Original value: 0xC0000000 + 30 => Ok(Self::Res_BIT_OFFSET), // Original value: 30 + 2 => Ok(Self::Res_BIT_LENGTH), // Original value: 2 + _ => Err(TpmError::InvalidEnumValue), + } + } +} + +impl TpmEnum for TPMA_CC { + fn get_value(&self) -> u32 { + self.0.into() + } + + fn try_from_trait(value: u64) -> Result where Self: Sized { + TPMA_CC::try_from(value as u32) + } + + fn new_from_trait(value: u64) -> Result where Self: Sized { + Ok(TPMA_CC(value as u32)) + } +} + +impl From for u32 { + fn from(value: TPMA_CC) -> Self { + value.0 as u32 + } +} + +impl From for i32 { + fn from(value: TPMA_CC) -> Self { + value.0 as i32 + } +} + +impl fmt::Display for TPMA_CC { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self.0 { + 65535 => write!(f, "commandIndex_BIT_MASK"), + 0 => write!(f, "commandIndex_BIT_OFFSET"), + 16 => write!(f, "commandIndex_BIT_LENGTH"), + 4194304 => write!(f, "nv"), + 8388608 => write!(f, "extensive"), + 16777216 => write!(f, "flushed"), + 234881024 => write!(f, "cHandles_BIT_MASK"), + 25 => write!(f, "cHandles_BIT_OFFSET"), + 3 => write!(f, "cHandles_BIT_LENGTH"), + 268435456 => write!(f, "rHandle"), + 536870912 => write!(f, "V"), + 3221225472 => write!(f, "Res_BIT_MASK"), + 30 => write!(f, "Res_BIT_OFFSET"), + 2 => write!(f, "Res_BIT_LENGTH"), + _ => write!(f, "{}", enum_to_str(self.0 as u64, std::any::TypeId::of::())), + } + } +} + +impl std::ops::BitOr for TPMA_CC { + type Output = Self; + + fn bitor(self, rhs: Self) -> Self::Output { + Self(self.0 | rhs.0) + } + +} + +impl From for TPMA_CC { + fn from(value: u32) -> Self { + Self(value.into()) + } +} + +/// This structure of this attribute is used to report that the TPM is designed for these +/// modes. This structure may be read using TPM2_GetCapability(capability = +/// TPM_CAP_TPM_PROPERTIES, property = TPM_PT_MODES). +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)] +pub struct TPMA_MODES(pub u32); + +impl TPMA_MODES { + /// SET (1): indicates that the TPM is designed to comply with all of the FIPS 140-2 + /// requirements at Level 1 or higher. + pub const FIPS_140_2: Self = Self(0x1); + + pub fn try_from(value: u32) -> Result { + match value { + 1 => Ok(Self::FIPS_140_2), // Original value: 0x1 + _ => Err(TpmError::InvalidEnumValue), + } + } +} + +impl TpmEnum for TPMA_MODES { + fn get_value(&self) -> u32 { + self.0.into() + } + + fn try_from_trait(value: u64) -> Result where Self: Sized { + TPMA_MODES::try_from(value as u32) + } + + fn new_from_trait(value: u64) -> Result where Self: Sized { + Ok(TPMA_MODES(value as u32)) + } +} + +impl From for u32 { + fn from(value: TPMA_MODES) -> Self { + value.0 as u32 + } +} + +impl From for i32 { + fn from(value: TPMA_MODES) -> Self { + value.0 as i32 + } +} + +impl fmt::Display for TPMA_MODES { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self.0 { + 1 => write!(f, "FIPS_140_2"), + _ => write!(f, "{}", enum_to_str(self.0 as u64, std::any::TypeId::of::())), + } + } +} + +impl std::ops::BitOr for TPMA_MODES { + type Output = Self; + + fn bitor(self, rhs: Self) -> Self::Output { + Self(self.0 | rhs.0) + } + +} + +impl From for TPMA_MODES { + fn from(value: u32) -> Self { + Self(value.into()) + } +} + +/// These attributes are as specified in clause 4.2.1.3. of RFC 5280 Internet X.509 Public +/// Key Infrastructure Certificate and Certificate Revocation List (CRL) Profile. For +/// TPM2_CertifyX509, when a caller provides a DER encoded Key Usage in +/// partialCertificate, the TPM will validate that the key to be certified meets the +/// requirements of Key Usage. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)] +pub struct TPMA_X509_KEY_USAGE(pub u32); + +impl TPMA_X509_KEY_USAGE { + /// Attributes.Decrypt SET + pub const decipherOnly: Self = Self(0x800000); + + /// Attributes.Decrypt SET + pub const encipherOnly: Self = Self(0x1000000); + + /// Attributes.sign SET + pub const cRLSign: Self = Self(0x2000000); + + /// Attributes.sign SET + pub const keyCertSign: Self = Self(0x4000000); + + /// Attributes.Decrypt SET + pub const keyAgreement: Self = Self(0x8000000); + + /// Attributes.Decrypt SET + pub const dataEncipherment: Self = Self(0x10000000); + + /// Asymmetric key with decrypt and restricted SET key has the attributes of a parent key + pub const keyEncipherment: Self = Self(0x20000000); + + /// FixedTPM SET in Subject Key (objectHandle) + pub const nonrepudiation: Self = Self(0x40000000); + + /// Alias to the nonrepudiation value. + pub const contentCommitment: Self = Self(0x40000000); + + /// Sign SET in Subject Key (objectHandle) + pub const digitalSignature: Self = Self(0x80000000); + + pub fn try_from(value: u32) -> Result { + match value { + 8388608 => Ok(Self::decipherOnly), // Original value: 0x800000 + 16777216 => Ok(Self::encipherOnly), // Original value: 0x1000000 + 33554432 => Ok(Self::cRLSign), // Original value: 0x2000000 + 67108864 => Ok(Self::keyCertSign), // Original value: 0x4000000 + 134217728 => Ok(Self::keyAgreement), // Original value: 0x8000000 + 268435456 => Ok(Self::dataEncipherment), // Original value: 0x10000000 + 536870912 => Ok(Self::keyEncipherment), // Original value: 0x20000000 + 1073741824 => Ok(Self::contentCommitment), // Original value: 0x40000000 + 2147483648 => Ok(Self::digitalSignature), // Original value: 0x80000000 + _ => Err(TpmError::InvalidEnumValue), + } + } +} + +impl TpmEnum for TPMA_X509_KEY_USAGE { + fn get_value(&self) -> u32 { + self.0.into() + } + + fn try_from_trait(value: u64) -> Result where Self: Sized { + TPMA_X509_KEY_USAGE::try_from(value as u32) + } + + fn new_from_trait(value: u64) -> Result where Self: Sized { + Ok(TPMA_X509_KEY_USAGE(value as u32)) + } +} + +impl From for u32 { + fn from(value: TPMA_X509_KEY_USAGE) -> Self { + value.0 as u32 + } +} + +impl From for i32 { + fn from(value: TPMA_X509_KEY_USAGE) -> Self { + value.0 as i32 + } +} + +impl fmt::Display for TPMA_X509_KEY_USAGE { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self.0 { + 8388608 => write!(f, "decipherOnly"), + 16777216 => write!(f, "encipherOnly"), + 33554432 => write!(f, "cRLSign"), + 67108864 => write!(f, "keyCertSign"), + 134217728 => write!(f, "keyAgreement"), + 268435456 => write!(f, "dataEncipherment"), + 536870912 => write!(f, "keyEncipherment"), + 1073741824 => write!(f, "contentCommitment"), + 2147483648 => write!(f, "digitalSignature"), + _ => write!(f, "{}", enum_to_str(self.0 as u64, std::any::TypeId::of::())), + } + } +} + +impl std::ops::BitOr for TPMA_X509_KEY_USAGE { + type Output = Self; + + fn bitor(self, rhs: Self) -> Self::Output { + Self(self.0 | rhs.0) + } + +} + +impl From for TPMA_X509_KEY_USAGE { + fn from(value: u32) -> Self { + Self(value.into()) + } +} + +/// This attribute is used to report the ACT state. This attribute may be read using +/// TPM2_GetCapability(capability = TPM_CAP_ACT, property = TPM_RH_ACT_x where x is the +/// ACT number (0-F)). The signaled value must be preserved across TPM Resume or if the +/// TPM has not lost power. The signaled value may be preserved over a power cycle of a TPM. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)] +pub struct TPMA_ACT(pub u32); + +impl TPMA_ACT { + /// SET (1): The ACT has signaled + /// CLEAR (0): The ACT has not signaled + pub const signaled: Self = Self(0x1); + + /// Preserves the state of signaled, depending on the power cycle + pub const preserveSignaled: Self = Self(0x2); + + pub fn try_from(value: u32) -> Result { + match value { + 1 => Ok(Self::signaled), // Original value: 0x1 + 2 => Ok(Self::preserveSignaled), // Original value: 0x2 + _ => Err(TpmError::InvalidEnumValue), + } + } +} + +impl TpmEnum for TPMA_ACT { + fn get_value(&self) -> u32 { + self.0.into() + } + + fn try_from_trait(value: u64) -> Result where Self: Sized { + TPMA_ACT::try_from(value as u32) + } + + fn new_from_trait(value: u64) -> Result where Self: Sized { + Ok(TPMA_ACT(value as u32)) + } +} + +impl From for u32 { + fn from(value: TPMA_ACT) -> Self { + value.0 as u32 + } +} + +impl From for i32 { + fn from(value: TPMA_ACT) -> Self { + value.0 as i32 + } +} + +impl fmt::Display for TPMA_ACT { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self.0 { + 1 => write!(f, "signaled"), + 2 => write!(f, "preserveSignaled"), + _ => write!(f, "{}", enum_to_str(self.0 as u64, std::any::TypeId::of::())), + } + } +} + +impl std::ops::BitOr for TPMA_ACT { + type Output = Self; + + fn bitor(self, rhs: Self) -> Self::Output { + Self(self.0 | rhs.0) + } + +} + +impl From for TPMA_ACT { + fn from(value: u32) -> Self { + Self(value.into()) + } +} + +/// A TPM_NV_INDEX is used to reference a defined location in NV memory. The format of the +/// Index is changed from TPM 1.2 in order to include the Index in the reserved handle +/// space. Handles in this range use the digest of the public area of the Index as the +/// Name of the entity in authorization computations +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)] +pub struct TPM_NV_INDEX(pub u32); + +impl TPM_NV_INDEX { + /// The Index of the NV location + pub const index_BIT_MASK: Self = Self(0xFFFFFF); + pub const index_BIT_OFFSET: Self = Self(0x0); // Original value: 0 + pub const index_BIT_LENGTH: Self = Self(0x18); // Original value: 24 + + /// Constant value of TPM_HT_NV_INDEX indicating the NV Index range + pub const RhNv_BIT_MASK: Self = Self(0xFF000000); + pub const RhNv_BIT_OFFSET: Self = Self(0x18); // Original value: 24 + pub const RhNv_BIT_LENGTH: Self = Self(0x8); // Original value: 8 + + pub fn try_from(value: u32) -> Result { + match value { + 16777215 => Ok(Self::index_BIT_MASK), // Original value: 0xFFFFFF + 0 => Ok(Self::index_BIT_OFFSET), // Original value: 0 + 24 => Ok(Self::RhNv_BIT_OFFSET), // Original value: 24 + 4278190080 => Ok(Self::RhNv_BIT_MASK), // Original value: 0xFF000000 + 8 => Ok(Self::RhNv_BIT_LENGTH), // Original value: 8 + _ => Err(TpmError::InvalidEnumValue), + } + } +} + +impl TpmEnum for TPM_NV_INDEX { + fn get_value(&self) -> u32 { + self.0.into() + } + + fn try_from_trait(value: u64) -> Result where Self: Sized { + TPM_NV_INDEX::try_from(value as u32) + } + + fn new_from_trait(value: u64) -> Result where Self: Sized { + Ok(TPM_NV_INDEX(value as u32)) + } +} + +impl From for u32 { + fn from(value: TPM_NV_INDEX) -> Self { + value.0 as u32 + } +} + +impl From for i32 { + fn from(value: TPM_NV_INDEX) -> Self { + value.0 as i32 + } +} + +impl fmt::Display for TPM_NV_INDEX { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self.0 { + 16777215 => write!(f, "index_BIT_MASK"), + 0 => write!(f, "index_BIT_OFFSET"), + 24 => write!(f, "RhNv_BIT_OFFSET"), + 4278190080 => write!(f, "RhNv_BIT_MASK"), + 8 => write!(f, "RhNv_BIT_LENGTH"), + _ => write!(f, "{}", enum_to_str(self.0 as u64, std::any::TypeId::of::())), + } + } +} + +impl std::ops::BitOr for TPM_NV_INDEX { + type Output = Self; + + fn bitor(self, rhs: Self) -> Self::Output { + Self(self.0 | rhs.0) + } + +} + +impl From for TPM_NV_INDEX { + fn from(value: u32) -> Self { + Self(value.into()) + } +} + +/// This structure allows the TPM to keep track of the data and permissions to manipulate +/// an NV Index. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)] +pub struct TPMA_NV(pub u32); + +impl TPMA_NV { + /// SET (1): The Index data can be written if Platform Authorization is provided. + /// CLEAR (0): Writing of the Index data cannot be authorized with Platform Authorization. + pub const PPWRITE: Self = Self(0x1); + + /// SET (1): The Index data can be written if Owner Authorization is provided. + /// CLEAR (0): Writing of the Index data cannot be authorized with Owner Authorization. + pub const OWNERWRITE: Self = Self(0x2); + + /// SET (1): Authorizations to change the Index contents that require USER role may be + /// provided with an HMAC session or password. + /// CLEAR (0): Authorizations to change the Index contents that require USER role may not + /// be provided with an HMAC session or password. + pub const AUTHWRITE: Self = Self(0x4); + + /// SET (1): Authorizations to change the Index contents that require USER role may be + /// provided with a policy session. + /// CLEAR (0): Authorizations to change the Index contents that require USER role may not + /// be provided with a policy session. + /// NOTE TPM2_NV_ChangeAuth() always requires that authorization be provided in a policy session. + pub const POLICYWRITE: Self = Self(0x8); + + /// Ordinary contains data that is opaque to the TPM that can only be modified using TPM2_NV_Write(). + pub const ORDINARY: Self = Self(0x0); + + /// Counter contains an 8-octet value that is to be used as a counter and can only be + /// modified with TPM2_NV_Increment() + pub const COUNTER: Self = Self(0x10); + + /// Bit Field contains an 8-octet value to be used as a bit field and can only be modified + /// with TPM2_NV_SetBits(). + pub const BITS: Self = Self(0x20); + + /// Extend contains a digest-sized value used like a PCR. The Index can only be modified + /// using TPM2_NV_Extend(). The extend will use the nameAlg of the Index. + pub const EXTEND: Self = Self(0x40); + + /// PIN Fail - contains pinCount that increments on a PIN authorization failure and a pinLimit + pub const PIN_FAIL: Self = Self(0x80); + + /// PIN Pass - contains pinCount that increments on a PIN authorization success and a pinLimit + pub const PIN_PASS: Self = Self(0x90); + + /// The type of the index. + /// NOTE A TPM is not required to support all TPM_NT values + pub const TpmNt_BIT_MASK: Self = Self(0xF0); + pub const TpmNt_BIT_OFFSET: Self = Self(0x4); // Original value: 4 + pub const TpmNt_BIT_LENGTH: Self = Self(0x4); // Original value: 4 + + /// SET (1): Index may not be deleted unless the authPolicy is satisfied using + /// TPM2_NV_UndefineSpaceSpecial(). + /// CLEAR (0): Index may be deleted with proper platform or owner authorization using + /// TPM2_NV_UndefineSpace(). + /// NOTE An Index with this attribute and a policy that cannot be satisfied (e.g., an + /// Empty Policy) cannot be deleted. + pub const POLICY_DELETE: Self = Self(0x400); + + /// SET (1): Index cannot be written. + /// CLEAR (0): Index can be written. + pub const WRITELOCKED: Self = Self(0x800); + + /// SET (1): A partial write of the Index data is not allowed. The write size shall match + /// the defined space size. + /// CLEAR (0): Partial writes are allowed. This setting is required if the .dataSize of + /// the Index is larger than NV_MAX_BUFFER_SIZE for the implementation. + pub const WRITEALL: Self = Self(0x1000); + + /// SET (1): TPM2_NV_WriteLock() may be used to prevent further writes to this location. + /// CLEAR (0): TPM2_NV_WriteLock() does not block subsequent writes if + /// TPMA_NV_WRITE_STCLEAR is also CLEAR. + pub const WRITEDEFINE: Self = Self(0x2000); + + /// SET (1): TPM2_NV_WriteLock() may be used to prevent further writes to this location + /// until the next TPM Reset or TPM Restart. + /// CLEAR (0): TPM2_NV_WriteLock() does not block subsequent writes if TPMA_NV_WRITEDEFINE + /// is also CLEAR. + pub const WRITE_STCLEAR: Self = Self(0x4000); + + /// SET (1): If TPM2_NV_GlobalWriteLock() is successful, TPMA_NV_WRITELOCKED is set. + /// CLEAR (0): TPM2_NV_GlobalWriteLock() has no effect on the writing of the data at this Index. + pub const GLOBALLOCK: Self = Self(0x8000); + + /// SET (1): The Index data can be read if Platform Authorization is provided. + /// CLEAR (0): Reading of the Index data cannot be authorized with Platform Authorization. + pub const PPREAD: Self = Self(0x10000); + + /// SET (1): The Index data can be read if Owner Authorization is provided. + /// CLEAR (0): Reading of the Index data cannot be authorized with Owner Authorization. + pub const OWNERREAD: Self = Self(0x20000); + + /// SET (1): The Index data may be read if the authValue is provided. + /// CLEAR (0): Reading of the Index data cannot be authorized with the Index authValue. + pub const AUTHREAD: Self = Self(0x40000); + + /// SET (1): The Index data may be read if the authPolicy is satisfied. + /// CLEAR (0): Reading of the Index data cannot be authorized with the Index authPolicy. + pub const POLICYREAD: Self = Self(0x80000); + + /// SET (1): Authorization failures of the Index do not affect the DA logic and + /// authorization of the Index is not blocked when the TPM is in Lockout mode. + /// CLEAR (0): Authorization failures of the Index will increment the authorization + /// failure counter and authorizations of this Index are not allowed when the TPM is in + /// Lockout mode. + pub const NO_DA: Self = Self(0x2000000); + + /// SET (1): NV Index state is only required to be saved when the TPM performs an orderly + /// shutdown (TPM2_Shutdown()). + /// CLEAR (0): NV Index state is required to be persistent after the command to update the + /// Index completes successfully (that is, the NV update is synchronous with the update command). + pub const ORDERLY: Self = Self(0x4000000); + + /// SET (1): TPMA_NV_WRITTEN for the Index is CLEAR by TPM Reset or TPM Restart. + /// CLEAR (0): TPMA_NV_WRITTEN is not changed by TPM Restart. + /// NOTE This attribute may only be SET if TPM_NT is not TPM_NT_COUNTER. + pub const CLEAR_STCLEAR: Self = Self(0x8000000); + + /// SET (1): Reads of the Index are blocked until the next TPM Reset or TPM Restart. + /// CLEAR (0): Reads of the Index are allowed if proper authorization is provided. + pub const READLOCKED: Self = Self(0x10000000); + + /// SET (1): Index has been written. + /// CLEAR (0): Index has not been written. + pub const WRITTEN: Self = Self(0x20000000); + + /// SET (1): This Index may be undefined with Platform Authorization but not with Owner + /// Authorization. + /// CLEAR (0): This Index may be undefined using Owner Authorization but not with Platform + /// Authorization. + /// The TPM will validate that this attribute is SET when the Index is defined using + /// Platform Authorization and will validate that this attribute is CLEAR when the Index + /// is defined using Owner Authorization. + pub const PLATFORMCREATE: Self = Self(0x40000000); + + /// SET (1): TPM2_NV_ReadLock() may be used to SET TPMA_NV_READLOCKED for this Index. + /// CLEAR (0): TPM2_NV_ReadLock() has no effect on this Index. + pub const READ_STCLEAR: Self = Self(0x80000000); + + pub fn try_from(value: u32) -> Result { + match value { + 1 => Ok(Self::PPWRITE), // Original value: 0x1 + 2 => Ok(Self::OWNERWRITE), // Original value: 0x2 + 4 => Ok(Self::TpmNt_BIT_LENGTH), // Original value: 4 + 8 => Ok(Self::POLICYWRITE), // Original value: 0x8 + 0 => Ok(Self::ORDINARY), // Original value: 0x0 + 16 => Ok(Self::COUNTER), // Original value: 0x10 + 32 => Ok(Self::BITS), // Original value: 0x20 + 64 => Ok(Self::EXTEND), // Original value: 0x40 + 128 => Ok(Self::PIN_FAIL), // Original value: 0x80 + 144 => Ok(Self::PIN_PASS), // Original value: 0x90 + 240 => Ok(Self::TpmNt_BIT_MASK), // Original value: 0xF0 + 1024 => Ok(Self::POLICY_DELETE), // Original value: 0x400 + 2048 => Ok(Self::WRITELOCKED), // Original value: 0x800 + 4096 => Ok(Self::WRITEALL), // Original value: 0x1000 + 8192 => Ok(Self::WRITEDEFINE), // Original value: 0x2000 + 16384 => Ok(Self::WRITE_STCLEAR), // Original value: 0x4000 + 32768 => Ok(Self::GLOBALLOCK), // Original value: 0x8000 + 65536 => Ok(Self::PPREAD), // Original value: 0x10000 + 131072 => Ok(Self::OWNERREAD), // Original value: 0x20000 + 262144 => Ok(Self::AUTHREAD), // Original value: 0x40000 + 524288 => Ok(Self::POLICYREAD), // Original value: 0x80000 + 33554432 => Ok(Self::NO_DA), // Original value: 0x2000000 + 67108864 => Ok(Self::ORDERLY), // Original value: 0x4000000 + 134217728 => Ok(Self::CLEAR_STCLEAR), // Original value: 0x8000000 + 268435456 => Ok(Self::READLOCKED), // Original value: 0x10000000 + 536870912 => Ok(Self::WRITTEN), // Original value: 0x20000000 + 1073741824 => Ok(Self::PLATFORMCREATE), // Original value: 0x40000000 + 2147483648 => Ok(Self::READ_STCLEAR), // Original value: 0x80000000 + _ => Err(TpmError::InvalidEnumValue), + } + } +} + +impl TpmEnum for TPMA_NV { + fn get_value(&self) -> u32 { + self.0.into() + } + + fn try_from_trait(value: u64) -> Result where Self: Sized { + TPMA_NV::try_from(value as u32) + } + + fn new_from_trait(value: u64) -> Result where Self: Sized { + Ok(TPMA_NV(value as u32)) + } +} + +impl From for u32 { + fn from(value: TPMA_NV) -> Self { + value.0 as u32 + } +} + +impl From for i32 { + fn from(value: TPMA_NV) -> Self { + value.0 as i32 + } +} + +impl fmt::Display for TPMA_NV { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self.0 { + 1 => write!(f, "PPWRITE"), + 2 => write!(f, "OWNERWRITE"), + 4 => write!(f, "TpmNt_BIT_LENGTH"), + 8 => write!(f, "POLICYWRITE"), + 0 => write!(f, "ORDINARY"), + 16 => write!(f, "COUNTER"), + 32 => write!(f, "BITS"), + 64 => write!(f, "EXTEND"), + 128 => write!(f, "PIN_FAIL"), + 144 => write!(f, "PIN_PASS"), + 240 => write!(f, "TpmNt_BIT_MASK"), + 1024 => write!(f, "POLICY_DELETE"), + 2048 => write!(f, "WRITELOCKED"), + 4096 => write!(f, "WRITEALL"), + 8192 => write!(f, "WRITEDEFINE"), + 16384 => write!(f, "WRITE_STCLEAR"), + 32768 => write!(f, "GLOBALLOCK"), + 65536 => write!(f, "PPREAD"), + 131072 => write!(f, "OWNERREAD"), + 262144 => write!(f, "AUTHREAD"), + 524288 => write!(f, "POLICYREAD"), + 33554432 => write!(f, "NO_DA"), + 67108864 => write!(f, "ORDERLY"), + 134217728 => write!(f, "CLEAR_STCLEAR"), + 268435456 => write!(f, "READLOCKED"), + 536870912 => write!(f, "WRITTEN"), + 1073741824 => write!(f, "PLATFORMCREATE"), + 2147483648 => write!(f, "READ_STCLEAR"), + _ => write!(f, "{}", enum_to_str(self.0 as u64, std::any::TypeId::of::())), + } + } +} + +impl std::ops::BitOr for TPMA_NV { + type Output = Self; + + fn bitor(self, rhs: Self) -> Self::Output { + Self(self.0 | rhs.0) + } + +} + +impl From for TPMA_NV { + fn from(value: u32) -> Self { + Self(value.into()) + } +} + +/// Table 119 Definition of TPMU_CAPABILITIES Union [OUT] +/// One of: TPML_ALG_PROPERTY, TPML_HANDLE, TPML_CCA, TPML_CC, TPML_PCR_SELECTION, +/// TPML_TAGGED_TPM_PROPERTY, TPML_TAGGED_PCR_PROPERTY, TPML_ECC_CURVE, +/// TPML_TAGGED_POLICY, TPML_ACT_DATA. +#[derive(Clone)] +pub enum TPMU_CAPABILITIES { + algorithms(TPML_ALG_PROPERTY), + handles(TPML_HANDLE), + command(TPML_CCA), + ppCommands(TPML_CC), + auditCommands(TPML_CC), + assignedPCR(TPML_PCR_SELECTION), + tpmProperties(TPML_TAGGED_TPM_PROPERTY), + pcrProperties(TPML_TAGGED_PCR_PROPERTY), + eccCurves(TPML_ECC_CURVE), + authPolicies(TPML_TAGGED_POLICY), + actData(TPML_ACT_DATA), +} + +/// Union selector type +impl TPMU_CAPABILITIES { + pub fn GetUnionSelector(&self) -> TPM_CAP { + match self { + Self::algorithms(_) => TPML_ALG_PROPERTY::GetUnionSelector(), + Self::handles(_) => TPML_HANDLE::GetUnionSelector(), + Self::command(_) => TPML_CCA::GetUnionSelector(), + Self::ppCommands(_) => TPML_CC::GetUnionSelector(), + Self::auditCommands(_) => TPML_CC::GetUnionSelector(), + Self::assignedPCR(_) => TPML_PCR_SELECTION::GetUnionSelector(), + Self::tpmProperties(_) => TPML_TAGGED_TPM_PROPERTY::GetUnionSelector(), + Self::pcrProperties(_) => TPML_TAGGED_PCR_PROPERTY::GetUnionSelector(), + Self::eccCurves(_) => TPML_ECC_CURVE::GetUnionSelector(), + Self::authPolicies(_) => TPML_TAGGED_POLICY::GetUnionSelector(), + Self::actData(_) => TPML_ACT_DATA::GetUnionSelector(), + } + } + + pub fn create(selector: TPM_CAP) -> Result, TpmError> { + match selector { + TPM_CAP::ALGS => Ok(Some(Self::algorithms(TPML_ALG_PROPERTY::default()))), + TPM_CAP::HANDLES => Ok(Some(Self::handles(TPML_HANDLE::default()))), + TPM_CAP::COMMANDS => Ok(Some(Self::command(TPML_CCA::default()))), + TPM_CAP::PP_COMMANDS => Ok(Some(Self::ppCommands(TPML_CC::default()))), + TPM_CAP::AUDIT_COMMANDS => Ok(Some(Self::auditCommands(TPML_CC::default()))), + TPM_CAP::PCRS => Ok(Some(Self::assignedPCR(TPML_PCR_SELECTION::default()))), + TPM_CAP::TPM_PROPERTIES => Ok(Some(Self::tpmProperties(TPML_TAGGED_TPM_PROPERTY::default()))), + TPM_CAP::PCR_PROPERTIES => Ok(Some(Self::pcrProperties(TPML_TAGGED_PCR_PROPERTY::default()))), + TPM_CAP::ECC_CURVES => Ok(Some(Self::eccCurves(TPML_ECC_CURVE::default()))), + TPM_CAP::AUTH_POLICIES => Ok(Some(Self::authPolicies(TPML_TAGGED_POLICY::default()))), + TPM_CAP::ACT => Ok(Some(Self::actData(TPML_ACT_DATA::default()))), + _ => Err(TpmError::InvalidUnion), + } + } +} + +impl fmt::Debug for TPMU_CAPABILITIES { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + Self::algorithms(inner) => write!(f, "TPMU_CAPABILITIES::algorithms({:?})", inner), + Self::handles(inner) => write!(f, "TPMU_CAPABILITIES::handles({:?})", inner), + Self::command(inner) => write!(f, "TPMU_CAPABILITIES::command({:?})", inner), + Self::ppCommands(inner) => write!(f, "TPMU_CAPABILITIES::ppCommands({:?})", inner), + Self::auditCommands(inner) => write!(f, "TPMU_CAPABILITIES::auditCommands({:?})", inner), + Self::assignedPCR(inner) => write!(f, "TPMU_CAPABILITIES::assignedPCR({:?})", inner), + Self::tpmProperties(inner) => write!(f, "TPMU_CAPABILITIES::tpmProperties({:?})", inner), + Self::pcrProperties(inner) => write!(f, "TPMU_CAPABILITIES::pcrProperties({:?})", inner), + Self::eccCurves(inner) => write!(f, "TPMU_CAPABILITIES::eccCurves({:?})", inner), + Self::authPolicies(inner) => write!(f, "TPMU_CAPABILITIES::authPolicies({:?})", inner), + Self::actData(inner) => write!(f, "TPMU_CAPABILITIES::actData({:?})", inner), + } + } +} +impl TpmStructure for TPMU_CAPABILITIES { + fn serialize(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + match self { + Self::algorithms(inner) => inner.serialize(buffer), + Self::handles(inner) => inner.serialize(buffer), + Self::command(inner) => inner.serialize(buffer), + Self::ppCommands(inner) => inner.serialize(buffer), + Self::auditCommands(inner) => inner.serialize(buffer), + Self::assignedPCR(inner) => inner.serialize(buffer), + Self::tpmProperties(inner) => inner.serialize(buffer), + Self::pcrProperties(inner) => inner.serialize(buffer), + Self::eccCurves(inner) => inner.serialize(buffer), + Self::authPolicies(inner) => inner.serialize(buffer), + Self::actData(inner) => inner.serialize(buffer), + } + } + + fn deserialize(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + match self { + Self::algorithms(inner) => inner.deserialize(buffer), + Self::handles(inner) => inner.deserialize(buffer), + Self::command(inner) => inner.deserialize(buffer), + Self::ppCommands(inner) => inner.deserialize(buffer), + Self::auditCommands(inner) => inner.deserialize(buffer), + Self::assignedPCR(inner) => inner.deserialize(buffer), + Self::tpmProperties(inner) => inner.deserialize(buffer), + Self::pcrProperties(inner) => inner.deserialize(buffer), + Self::eccCurves(inner) => inner.deserialize(buffer), + Self::authPolicies(inner) => inner.deserialize(buffer), + Self::actData(inner) => inner.deserialize(buffer), + } + } + + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + match self { + Self::algorithms(inner) => inner.fromTpm(buffer), + Self::handles(inner) => inner.fromTpm(buffer), + Self::command(inner) => inner.fromTpm(buffer), + Self::ppCommands(inner) => inner.fromTpm(buffer), + Self::auditCommands(inner) => inner.fromTpm(buffer), + Self::assignedPCR(inner) => inner.fromTpm(buffer), + Self::tpmProperties(inner) => inner.fromTpm(buffer), + Self::pcrProperties(inner) => inner.fromTpm(buffer), + Self::eccCurves(inner) => inner.fromTpm(buffer), + Self::authPolicies(inner) => inner.fromTpm(buffer), + Self::actData(inner) => inner.fromTpm(buffer), + } + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + match self { + Self::algorithms(inner) => inner.fromBytes(buffer), + Self::handles(inner) => inner.fromBytes(buffer), + Self::command(inner) => inner.fromBytes(buffer), + Self::ppCommands(inner) => inner.fromBytes(buffer), + Self::auditCommands(inner) => inner.fromBytes(buffer), + Self::assignedPCR(inner) => inner.fromBytes(buffer), + Self::tpmProperties(inner) => inner.fromBytes(buffer), + Self::pcrProperties(inner) => inner.fromBytes(buffer), + Self::eccCurves(inner) => inner.fromBytes(buffer), + Self::authPolicies(inner) => inner.fromBytes(buffer), + Self::actData(inner) => inner.fromBytes(buffer), + } + } + +} + +impl TpmMarshaller for TPMU_CAPABILITIES { + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + match self { + Self::algorithms(inner) => inner.toTpm(buffer), + Self::handles(inner) => inner.toTpm(buffer), + Self::command(inner) => inner.toTpm(buffer), + Self::ppCommands(inner) => inner.toTpm(buffer), + Self::auditCommands(inner) => inner.toTpm(buffer), + Self::assignedPCR(inner) => inner.toTpm(buffer), + Self::tpmProperties(inner) => inner.toTpm(buffer), + Self::pcrProperties(inner) => inner.toTpm(buffer), + Self::eccCurves(inner) => inner.toTpm(buffer), + Self::authPolicies(inner) => inner.toTpm(buffer), + Self::actData(inner) => inner.toTpm(buffer), + } + } + + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + match self { + Self::algorithms(inner) => inner.initFromTpm(buffer), + Self::handles(inner) => inner.initFromTpm(buffer), + Self::command(inner) => inner.initFromTpm(buffer), + Self::ppCommands(inner) => inner.initFromTpm(buffer), + Self::auditCommands(inner) => inner.initFromTpm(buffer), + Self::assignedPCR(inner) => inner.initFromTpm(buffer), + Self::tpmProperties(inner) => inner.initFromTpm(buffer), + Self::pcrProperties(inner) => inner.initFromTpm(buffer), + Self::eccCurves(inner) => inner.initFromTpm(buffer), + Self::authPolicies(inner) => inner.initFromTpm(buffer), + Self::actData(inner) => inner.initFromTpm(buffer), + } + } + +} + +/// Table 132 Definition of TPMU_ATTEST Union [OUT] +/// One of: TPMS_CERTIFY_INFO, TPMS_CREATION_INFO, TPMS_QUOTE_INFO, +/// TPMS_COMMAND_AUDIT_INFO, TPMS_SESSION_AUDIT_INFO, TPMS_TIME_ATTEST_INFO, +/// TPMS_NV_CERTIFY_INFO, TPMS_NV_DIGEST_CERTIFY_INFO. +#[derive(Clone)] +pub enum TPMU_ATTEST { + certify(TPMS_CERTIFY_INFO), + creation(TPMS_CREATION_INFO), + quote(TPMS_QUOTE_INFO), + commandAudit(TPMS_COMMAND_AUDIT_INFO), + sessionAudit(TPMS_SESSION_AUDIT_INFO), + time(TPMS_TIME_ATTEST_INFO), + nv(TPMS_NV_CERTIFY_INFO), + nvDigest(TPMS_NV_DIGEST_CERTIFY_INFO), +} + +/// Union selector type +impl TPMU_ATTEST { + pub fn GetUnionSelector(&self) -> TPM_ST { + match self { + Self::certify(_) => TPMS_CERTIFY_INFO::GetUnionSelector(), + Self::creation(_) => TPMS_CREATION_INFO::GetUnionSelector(), + Self::quote(_) => TPMS_QUOTE_INFO::GetUnionSelector(), + Self::commandAudit(_) => TPMS_COMMAND_AUDIT_INFO::GetUnionSelector(), + Self::sessionAudit(_) => TPMS_SESSION_AUDIT_INFO::GetUnionSelector(), + Self::time(_) => TPMS_TIME_ATTEST_INFO::GetUnionSelector(), + Self::nv(_) => TPMS_NV_CERTIFY_INFO::GetUnionSelector(), + Self::nvDigest(_) => TPMS_NV_DIGEST_CERTIFY_INFO::GetUnionSelector(), + } + } + + pub fn create(selector: TPM_ST) -> Result, TpmError> { + match selector { + TPM_ST::ATTEST_CERTIFY => Ok(Some(Self::certify(TPMS_CERTIFY_INFO::default()))), + TPM_ST::ATTEST_CREATION => Ok(Some(Self::creation(TPMS_CREATION_INFO::default()))), + TPM_ST::ATTEST_QUOTE => Ok(Some(Self::quote(TPMS_QUOTE_INFO::default()))), + TPM_ST::ATTEST_COMMAND_AUDIT => Ok(Some(Self::commandAudit(TPMS_COMMAND_AUDIT_INFO::default()))), + TPM_ST::ATTEST_SESSION_AUDIT => Ok(Some(Self::sessionAudit(TPMS_SESSION_AUDIT_INFO::default()))), + TPM_ST::ATTEST_TIME => Ok(Some(Self::time(TPMS_TIME_ATTEST_INFO::default()))), + TPM_ST::ATTEST_NV => Ok(Some(Self::nv(TPMS_NV_CERTIFY_INFO::default()))), + TPM_ST::ATTEST_NV_DIGEST => Ok(Some(Self::nvDigest(TPMS_NV_DIGEST_CERTIFY_INFO::default()))), + _ => Err(TpmError::InvalidUnion), + } + } +} + +impl fmt::Debug for TPMU_ATTEST { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + Self::certify(inner) => write!(f, "TPMU_ATTEST::certify({:?})", inner), + Self::creation(inner) => write!(f, "TPMU_ATTEST::creation({:?})", inner), + Self::quote(inner) => write!(f, "TPMU_ATTEST::quote({:?})", inner), + Self::commandAudit(inner) => write!(f, "TPMU_ATTEST::commandAudit({:?})", inner), + Self::sessionAudit(inner) => write!(f, "TPMU_ATTEST::sessionAudit({:?})", inner), + Self::time(inner) => write!(f, "TPMU_ATTEST::time({:?})", inner), + Self::nv(inner) => write!(f, "TPMU_ATTEST::nv({:?})", inner), + Self::nvDigest(inner) => write!(f, "TPMU_ATTEST::nvDigest({:?})", inner), + } + } +} +impl TpmStructure for TPMU_ATTEST { + fn serialize(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + match self { + Self::certify(inner) => inner.serialize(buffer), + Self::creation(inner) => inner.serialize(buffer), + Self::quote(inner) => inner.serialize(buffer), + Self::commandAudit(inner) => inner.serialize(buffer), + Self::sessionAudit(inner) => inner.serialize(buffer), + Self::time(inner) => inner.serialize(buffer), + Self::nv(inner) => inner.serialize(buffer), + Self::nvDigest(inner) => inner.serialize(buffer), + } + } + + fn deserialize(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + match self { + Self::certify(inner) => inner.deserialize(buffer), + Self::creation(inner) => inner.deserialize(buffer), + Self::quote(inner) => inner.deserialize(buffer), + Self::commandAudit(inner) => inner.deserialize(buffer), + Self::sessionAudit(inner) => inner.deserialize(buffer), + Self::time(inner) => inner.deserialize(buffer), + Self::nv(inner) => inner.deserialize(buffer), + Self::nvDigest(inner) => inner.deserialize(buffer), + } + } + + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + match self { + Self::certify(inner) => inner.fromTpm(buffer), + Self::creation(inner) => inner.fromTpm(buffer), + Self::quote(inner) => inner.fromTpm(buffer), + Self::commandAudit(inner) => inner.fromTpm(buffer), + Self::sessionAudit(inner) => inner.fromTpm(buffer), + Self::time(inner) => inner.fromTpm(buffer), + Self::nv(inner) => inner.fromTpm(buffer), + Self::nvDigest(inner) => inner.fromTpm(buffer), + } + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + match self { + Self::certify(inner) => inner.fromBytes(buffer), + Self::creation(inner) => inner.fromBytes(buffer), + Self::quote(inner) => inner.fromBytes(buffer), + Self::commandAudit(inner) => inner.fromBytes(buffer), + Self::sessionAudit(inner) => inner.fromBytes(buffer), + Self::time(inner) => inner.fromBytes(buffer), + Self::nv(inner) => inner.fromBytes(buffer), + Self::nvDigest(inner) => inner.fromBytes(buffer), + } + } + +} + +impl TpmMarshaller for TPMU_ATTEST { + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + match self { + Self::certify(inner) => inner.toTpm(buffer), + Self::creation(inner) => inner.toTpm(buffer), + Self::quote(inner) => inner.toTpm(buffer), + Self::commandAudit(inner) => inner.toTpm(buffer), + Self::sessionAudit(inner) => inner.toTpm(buffer), + Self::time(inner) => inner.toTpm(buffer), + Self::nv(inner) => inner.toTpm(buffer), + Self::nvDigest(inner) => inner.toTpm(buffer), + } + } + + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + match self { + Self::certify(inner) => inner.initFromTpm(buffer), + Self::creation(inner) => inner.initFromTpm(buffer), + Self::quote(inner) => inner.initFromTpm(buffer), + Self::commandAudit(inner) => inner.initFromTpm(buffer), + Self::sessionAudit(inner) => inner.initFromTpm(buffer), + Self::time(inner) => inner.initFromTpm(buffer), + Self::nv(inner) => inner.initFromTpm(buffer), + Self::nvDigest(inner) => inner.initFromTpm(buffer), + } + } + +} + +/// This union allows additional parameters to be added for a symmetric cipher. Currently, +/// no additional parameters are required for any of the symmetric algorithms. +/// One of: TPMS_TDES_SYM_DETAILS, TPMS_AES_SYM_DETAILS, TPMS_SM4_SYM_DETAILS, +/// TPMS_CAMELLIA_SYM_DETAILS, TPMS_ANY_SYM_DETAILS, TPMS_XOR_SYM_DETAILS, TPMS_NULL_SYM_DETAILS. +#[derive(Clone)] +pub enum TPMU_SYM_DETAILS { + tdes(TPMS_TDES_SYM_DETAILS), + aes(TPMS_AES_SYM_DETAILS), + sm4(TPMS_SM4_SYM_DETAILS), + camellia(TPMS_CAMELLIA_SYM_DETAILS), + sym(TPMS_ANY_SYM_DETAILS), + xor(TPMS_XOR_SYM_DETAILS), + null(TPMS_NULL_SYM_DETAILS), +} + +/// Union selector type +impl TPMU_SYM_DETAILS { + pub fn GetUnionSelector(&self) -> TPM_ALG_ID { + match self { + Self::tdes(_) => TPMS_TDES_SYM_DETAILS::GetUnionSelector(), + Self::aes(_) => TPMS_AES_SYM_DETAILS::GetUnionSelector(), + Self::sm4(_) => TPMS_SM4_SYM_DETAILS::GetUnionSelector(), + Self::camellia(_) => TPMS_CAMELLIA_SYM_DETAILS::GetUnionSelector(), + Self::sym(_) => TPMS_ANY_SYM_DETAILS::GetUnionSelector(), + Self::xor(_) => TPMS_XOR_SYM_DETAILS::GetUnionSelector(), + Self::null(_) => TPMS_NULL_SYM_DETAILS::GetUnionSelector(), + } + } + + pub fn create(selector: TPM_ALG_ID) -> Result, TpmError> { + match selector { + TPM_ALG_ID::TDES => Ok(Some(Self::tdes(TPMS_TDES_SYM_DETAILS::default()))), + TPM_ALG_ID::AES => Ok(Some(Self::aes(TPMS_AES_SYM_DETAILS::default()))), + TPM_ALG_ID::SM4 => Ok(Some(Self::sm4(TPMS_SM4_SYM_DETAILS::default()))), + TPM_ALG_ID::CAMELLIA => Ok(Some(Self::camellia(TPMS_CAMELLIA_SYM_DETAILS::default()))), + TPM_ALG_ID::ANY => Ok(Some(Self::sym(TPMS_ANY_SYM_DETAILS::default()))), + TPM_ALG_ID::XOR => Ok(Some(Self::xor(TPMS_XOR_SYM_DETAILS::default()))), + TPM_ALG_ID::NULL => Ok(Some(Self::null(TPMS_NULL_SYM_DETAILS::default()))), + _ => Err(TpmError::InvalidUnion), + } + } +} + +impl fmt::Debug for TPMU_SYM_DETAILS { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + Self::tdes(inner) => write!(f, "TPMU_SYM_DETAILS::tdes({:?})", inner), + Self::aes(inner) => write!(f, "TPMU_SYM_DETAILS::aes({:?})", inner), + Self::sm4(inner) => write!(f, "TPMU_SYM_DETAILS::sm4({:?})", inner), + Self::camellia(inner) => write!(f, "TPMU_SYM_DETAILS::camellia({:?})", inner), + Self::sym(inner) => write!(f, "TPMU_SYM_DETAILS::sym({:?})", inner), + Self::xor(inner) => write!(f, "TPMU_SYM_DETAILS::xor({:?})", inner), + Self::null(inner) => write!(f, "TPMU_SYM_DETAILS::null({:?})", inner), + } + } +} +impl TpmStructure for TPMU_SYM_DETAILS { + fn serialize(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + match self { + Self::tdes(inner) => inner.serialize(buffer), + Self::aes(inner) => inner.serialize(buffer), + Self::sm4(inner) => inner.serialize(buffer), + Self::camellia(inner) => inner.serialize(buffer), + Self::sym(inner) => inner.serialize(buffer), + Self::xor(inner) => inner.serialize(buffer), + Self::null(inner) => inner.serialize(buffer), + } + } + + fn deserialize(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + match self { + Self::tdes(inner) => inner.deserialize(buffer), + Self::aes(inner) => inner.deserialize(buffer), + Self::sm4(inner) => inner.deserialize(buffer), + Self::camellia(inner) => inner.deserialize(buffer), + Self::sym(inner) => inner.deserialize(buffer), + Self::xor(inner) => inner.deserialize(buffer), + Self::null(inner) => inner.deserialize(buffer), + } + } + + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + match self { + Self::tdes(inner) => inner.fromTpm(buffer), + Self::aes(inner) => inner.fromTpm(buffer), + Self::sm4(inner) => inner.fromTpm(buffer), + Self::camellia(inner) => inner.fromTpm(buffer), + Self::sym(inner) => inner.fromTpm(buffer), + Self::xor(inner) => inner.fromTpm(buffer), + Self::null(inner) => inner.fromTpm(buffer), + } + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + match self { + Self::tdes(inner) => inner.fromBytes(buffer), + Self::aes(inner) => inner.fromBytes(buffer), + Self::sm4(inner) => inner.fromBytes(buffer), + Self::camellia(inner) => inner.fromBytes(buffer), + Self::sym(inner) => inner.fromBytes(buffer), + Self::xor(inner) => inner.fromBytes(buffer), + Self::null(inner) => inner.fromBytes(buffer), + } + } + +} + +impl TpmMarshaller for TPMU_SYM_DETAILS { + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + match self { + Self::tdes(inner) => inner.toTpm(buffer), + Self::aes(inner) => inner.toTpm(buffer), + Self::sm4(inner) => inner.toTpm(buffer), + Self::camellia(inner) => inner.toTpm(buffer), + Self::sym(inner) => inner.toTpm(buffer), + Self::xor(inner) => inner.toTpm(buffer), + Self::null(inner) => inner.toTpm(buffer), + } + } + + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + match self { + Self::tdes(inner) => inner.initFromTpm(buffer), + Self::aes(inner) => inner.initFromTpm(buffer), + Self::sm4(inner) => inner.initFromTpm(buffer), + Self::camellia(inner) => inner.initFromTpm(buffer), + Self::sym(inner) => inner.initFromTpm(buffer), + Self::xor(inner) => inner.initFromTpm(buffer), + Self::null(inner) => inner.initFromTpm(buffer), + } + } + +} + +/// This structure allows a TPM2B_SENSITIVE_CREATE structure to carry either a +/// TPM2B_SENSITVE_DATA or a TPM2B_DERIVE structure. The contents of the union are +/// determined by context. When an object is being derived, the derivation values are present. +/// One of: u8, TPMS_DERIVE. +#[derive(Clone)] +pub enum TPMU_SENSITIVE_CREATE { + create, + derive(TPMS_DERIVE), +} + +/// Union selector type +impl TPMU_SENSITIVE_CREATE { + pub fn GetUnionSelector(&self) -> TPM_ALG_ID { + match self { + Self::create => TPM_ALG_ID::ANY, + Self::derive(_) => TPMS_DERIVE::GetUnionSelector(), + } + } + + pub fn create(selector: TPM_ALG_ID) -> Result, TpmError> { + match selector { + TPM_ALG_ID::ANY => Ok(None), + TPM_ALG_ID::ANY2 => Ok(Some(Self::derive(TPMS_DERIVE::default()))), + _ => Err(TpmError::InvalidUnion), + } + } +} + +impl fmt::Debug for TPMU_SENSITIVE_CREATE { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + Self::create => write!(f, "TPMU_SENSITIVE_CREATE::create"), + Self::derive(inner) => write!(f, "TPMU_SENSITIVE_CREATE::derive({:?})", inner), + } + } +} +impl TpmStructure for TPMU_SENSITIVE_CREATE { + fn serialize(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + match self { + Self::create => Ok(()), + Self::derive(inner) => inner.serialize(buffer), + } + } + + fn deserialize(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + match self { + Self::create => Ok(()), + Self::derive(inner) => inner.deserialize(buffer), + } + } + + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + match self { + Self::create => Ok(()), + Self::derive(inner) => inner.fromTpm(buffer), + } + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + match self { + Self::create => Ok(()), + Self::derive(inner) => inner.fromBytes(buffer), + } + } + +} + +impl TpmMarshaller for TPMU_SENSITIVE_CREATE { + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + match self { + Self::create => Ok(()), + Self::derive(inner) => inner.toTpm(buffer), + } + } + + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + match self { + Self::create => Ok(()), + Self::derive(inner) => inner.initFromTpm(buffer), + } + } + +} + +/// Table 157 Definition of TPMU_SCHEME_KEYEDHASH Union [IN/OUT] +/// One of: TPMS_SCHEME_HMAC, TPMS_SCHEME_XOR, TPMS_NULL_SCHEME_KEYEDHASH. +#[derive(Clone)] +pub enum TPMU_SCHEME_KEYEDHASH { + hmac(TPMS_SCHEME_HMAC), + xor(TPMS_SCHEME_XOR), + null(TPMS_NULL_SCHEME_KEYEDHASH), +} + +/// Union selector type +impl TPMU_SCHEME_KEYEDHASH { + pub fn GetUnionSelector(&self) -> TPM_ALG_ID { + match self { + Self::hmac(_) => TPMS_SCHEME_HMAC::GetUnionSelector(), + Self::xor(_) => TPMS_SCHEME_XOR::GetUnionSelector(), + Self::null(_) => TPMS_NULL_SCHEME_KEYEDHASH::GetUnionSelector(), + } + } + + pub fn create(selector: TPM_ALG_ID) -> Result, TpmError> { + match selector { + TPM_ALG_ID::HMAC => Ok(Some(Self::hmac(TPMS_SCHEME_HMAC::default()))), + TPM_ALG_ID::XOR => Ok(Some(Self::xor(TPMS_SCHEME_XOR::default()))), + TPM_ALG_ID::NULL => Ok(Some(Self::null(TPMS_NULL_SCHEME_KEYEDHASH::default()))), + _ => Err(TpmError::InvalidUnion), + } + } +} + +impl fmt::Debug for TPMU_SCHEME_KEYEDHASH { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + Self::hmac(inner) => write!(f, "TPMU_SCHEME_KEYEDHASH::hmac({:?})", inner), + Self::xor(inner) => write!(f, "TPMU_SCHEME_KEYEDHASH::xor({:?})", inner), + Self::null(inner) => write!(f, "TPMU_SCHEME_KEYEDHASH::null({:?})", inner), + } + } +} +impl TpmStructure for TPMU_SCHEME_KEYEDHASH { + fn serialize(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + match self { + Self::hmac(inner) => inner.serialize(buffer), + Self::xor(inner) => inner.serialize(buffer), + Self::null(inner) => inner.serialize(buffer), + } + } + + fn deserialize(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + match self { + Self::hmac(inner) => inner.deserialize(buffer), + Self::xor(inner) => inner.deserialize(buffer), + Self::null(inner) => inner.deserialize(buffer), + } + } + + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + match self { + Self::hmac(inner) => inner.fromTpm(buffer), + Self::xor(inner) => inner.fromTpm(buffer), + Self::null(inner) => inner.fromTpm(buffer), + } + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + match self { + Self::hmac(inner) => inner.fromBytes(buffer), + Self::xor(inner) => inner.fromBytes(buffer), + Self::null(inner) => inner.fromBytes(buffer), + } + } + +} + +impl TpmMarshaller for TPMU_SCHEME_KEYEDHASH { + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + match self { + Self::hmac(inner) => inner.toTpm(buffer), + Self::xor(inner) => inner.toTpm(buffer), + Self::null(inner) => inner.toTpm(buffer), + } + } + + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + match self { + Self::hmac(inner) => inner.initFromTpm(buffer), + Self::xor(inner) => inner.initFromTpm(buffer), + Self::null(inner) => inner.initFromTpm(buffer), + } + } + +} + +/// This is the union of all of the signature schemes. +/// One of: TPMS_SIG_SCHEME_RSASSA, TPMS_SIG_SCHEME_RSAPSS, TPMS_SIG_SCHEME_ECDSA, +/// TPMS_SIG_SCHEME_ECDAA, TPMS_SIG_SCHEME_SM2, TPMS_SIG_SCHEME_ECSCHNORR, +/// TPMS_SCHEME_HMAC, TPMS_SCHEME_HASH, TPMS_NULL_SIG_SCHEME. +#[derive(Clone)] +pub enum TPMU_SIG_SCHEME { + rsassa(TPMS_SIG_SCHEME_RSASSA), + rsapss(TPMS_SIG_SCHEME_RSAPSS), + ecdsa(TPMS_SIG_SCHEME_ECDSA), + ecdaa(TPMS_SIG_SCHEME_ECDAA), + sm2(TPMS_SIG_SCHEME_SM2), + ecschnorr(TPMS_SIG_SCHEME_ECSCHNORR), + hmac(TPMS_SCHEME_HMAC), + any(TPMS_SCHEME_HASH), + null(TPMS_NULL_SIG_SCHEME), +} + +/// Union selector type +impl TPMU_SIG_SCHEME { + pub fn GetUnionSelector(&self) -> TPM_ALG_ID { + match self { + Self::rsassa(_) => TPMS_SIG_SCHEME_RSASSA::GetUnionSelector(), + Self::rsapss(_) => TPMS_SIG_SCHEME_RSAPSS::GetUnionSelector(), + Self::ecdsa(_) => TPMS_SIG_SCHEME_ECDSA::GetUnionSelector(), + Self::ecdaa(_) => TPMS_SIG_SCHEME_ECDAA::GetUnionSelector(), + Self::sm2(_) => TPMS_SIG_SCHEME_SM2::GetUnionSelector(), + Self::ecschnorr(_) => TPMS_SIG_SCHEME_ECSCHNORR::GetUnionSelector(), + Self::hmac(_) => TPMS_SCHEME_HMAC::GetUnionSelector(), + Self::any(_) => TPMS_SCHEME_HASH::GetUnionSelector(), + Self::null(_) => TPMS_NULL_SIG_SCHEME::GetUnionSelector(), + } + } + + pub fn create(selector: TPM_ALG_ID) -> Result, TpmError> { + match selector { + TPM_ALG_ID::RSASSA => Ok(Some(Self::rsassa(TPMS_SIG_SCHEME_RSASSA::default()))), + TPM_ALG_ID::RSAPSS => Ok(Some(Self::rsapss(TPMS_SIG_SCHEME_RSAPSS::default()))), + TPM_ALG_ID::ECDSA => Ok(Some(Self::ecdsa(TPMS_SIG_SCHEME_ECDSA::default()))), + TPM_ALG_ID::ECDAA => Ok(Some(Self::ecdaa(TPMS_SIG_SCHEME_ECDAA::default()))), + TPM_ALG_ID::SM2 => Ok(Some(Self::sm2(TPMS_SIG_SCHEME_SM2::default()))), + TPM_ALG_ID::ECSCHNORR => Ok(Some(Self::ecschnorr(TPMS_SIG_SCHEME_ECSCHNORR::default()))), + TPM_ALG_ID::HMAC => Ok(Some(Self::hmac(TPMS_SCHEME_HMAC::default()))), + TPM_ALG_ID::ANY => Ok(Some(Self::any(TPMS_SCHEME_HASH::default()))), + TPM_ALG_ID::NULL => Ok(Some(Self::null(TPMS_NULL_SIG_SCHEME::default()))), + _ => Err(TpmError::InvalidUnion), + } + } +} + +impl fmt::Debug for TPMU_SIG_SCHEME { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + Self::rsassa(inner) => write!(f, "TPMU_SIG_SCHEME::rsassa({:?})", inner), + Self::rsapss(inner) => write!(f, "TPMU_SIG_SCHEME::rsapss({:?})", inner), + Self::ecdsa(inner) => write!(f, "TPMU_SIG_SCHEME::ecdsa({:?})", inner), + Self::ecdaa(inner) => write!(f, "TPMU_SIG_SCHEME::ecdaa({:?})", inner), + Self::sm2(inner) => write!(f, "TPMU_SIG_SCHEME::sm2({:?})", inner), + Self::ecschnorr(inner) => write!(f, "TPMU_SIG_SCHEME::ecschnorr({:?})", inner), + Self::hmac(inner) => write!(f, "TPMU_SIG_SCHEME::hmac({:?})", inner), + Self::any(inner) => write!(f, "TPMU_SIG_SCHEME::any({:?})", inner), + Self::null(inner) => write!(f, "TPMU_SIG_SCHEME::null({:?})", inner), + } + } +} +impl TpmStructure for TPMU_SIG_SCHEME { + fn serialize(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + match self { + Self::rsassa(inner) => inner.serialize(buffer), + Self::rsapss(inner) => inner.serialize(buffer), + Self::ecdsa(inner) => inner.serialize(buffer), + Self::ecdaa(inner) => inner.serialize(buffer), + Self::sm2(inner) => inner.serialize(buffer), + Self::ecschnorr(inner) => inner.serialize(buffer), + Self::hmac(inner) => inner.serialize(buffer), + Self::any(inner) => inner.serialize(buffer), + Self::null(inner) => inner.serialize(buffer), + } + } + + fn deserialize(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + match self { + Self::rsassa(inner) => inner.deserialize(buffer), + Self::rsapss(inner) => inner.deserialize(buffer), + Self::ecdsa(inner) => inner.deserialize(buffer), + Self::ecdaa(inner) => inner.deserialize(buffer), + Self::sm2(inner) => inner.deserialize(buffer), + Self::ecschnorr(inner) => inner.deserialize(buffer), + Self::hmac(inner) => inner.deserialize(buffer), + Self::any(inner) => inner.deserialize(buffer), + Self::null(inner) => inner.deserialize(buffer), + } + } + + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + match self { + Self::rsassa(inner) => inner.fromTpm(buffer), + Self::rsapss(inner) => inner.fromTpm(buffer), + Self::ecdsa(inner) => inner.fromTpm(buffer), + Self::ecdaa(inner) => inner.fromTpm(buffer), + Self::sm2(inner) => inner.fromTpm(buffer), + Self::ecschnorr(inner) => inner.fromTpm(buffer), + Self::hmac(inner) => inner.fromTpm(buffer), + Self::any(inner) => inner.fromTpm(buffer), + Self::null(inner) => inner.fromTpm(buffer), + } + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + match self { + Self::rsassa(inner) => inner.fromBytes(buffer), + Self::rsapss(inner) => inner.fromBytes(buffer), + Self::ecdsa(inner) => inner.fromBytes(buffer), + Self::ecdaa(inner) => inner.fromBytes(buffer), + Self::sm2(inner) => inner.fromBytes(buffer), + Self::ecschnorr(inner) => inner.fromBytes(buffer), + Self::hmac(inner) => inner.fromBytes(buffer), + Self::any(inner) => inner.fromBytes(buffer), + Self::null(inner) => inner.fromBytes(buffer), + } + } + +} + +impl TpmMarshaller for TPMU_SIG_SCHEME { + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + match self { + Self::rsassa(inner) => inner.toTpm(buffer), + Self::rsapss(inner) => inner.toTpm(buffer), + Self::ecdsa(inner) => inner.toTpm(buffer), + Self::ecdaa(inner) => inner.toTpm(buffer), + Self::sm2(inner) => inner.toTpm(buffer), + Self::ecschnorr(inner) => inner.toTpm(buffer), + Self::hmac(inner) => inner.toTpm(buffer), + Self::any(inner) => inner.toTpm(buffer), + Self::null(inner) => inner.toTpm(buffer), + } + } + + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + match self { + Self::rsassa(inner) => inner.initFromTpm(buffer), + Self::rsapss(inner) => inner.initFromTpm(buffer), + Self::ecdsa(inner) => inner.initFromTpm(buffer), + Self::ecdaa(inner) => inner.initFromTpm(buffer), + Self::sm2(inner) => inner.initFromTpm(buffer), + Self::ecschnorr(inner) => inner.initFromTpm(buffer), + Self::hmac(inner) => inner.initFromTpm(buffer), + Self::any(inner) => inner.initFromTpm(buffer), + Self::null(inner) => inner.initFromTpm(buffer), + } + } + +} + +/// Table 166 Definition of TPMU_KDF_SCHEME Union [IN/OUT] +/// One of: TPMS_KDF_SCHEME_MGF1, TPMS_KDF_SCHEME_KDF1_SP800_56A, TPMS_KDF_SCHEME_KDF2, +/// TPMS_KDF_SCHEME_KDF1_SP800_108, TPMS_SCHEME_HASH, TPMS_NULL_KDF_SCHEME. +#[derive(Clone)] +pub enum TPMU_KDF_SCHEME { + mgf1(TPMS_KDF_SCHEME_MGF1), + kdf1_sp800_56a(TPMS_KDF_SCHEME_KDF1_SP800_56A), + kdf2(TPMS_KDF_SCHEME_KDF2), + kdf1_sp800_108(TPMS_KDF_SCHEME_KDF1_SP800_108), + anyKdf(TPMS_SCHEME_HASH), + null(TPMS_NULL_KDF_SCHEME), +} + +/// Union selector type +impl TPMU_KDF_SCHEME { + pub fn GetUnionSelector(&self) -> TPM_ALG_ID { + match self { + Self::mgf1(_) => TPMS_KDF_SCHEME_MGF1::GetUnionSelector(), + Self::kdf1_sp800_56a(_) => TPMS_KDF_SCHEME_KDF1_SP800_56A::GetUnionSelector(), + Self::kdf2(_) => TPMS_KDF_SCHEME_KDF2::GetUnionSelector(), + Self::kdf1_sp800_108(_) => TPMS_KDF_SCHEME_KDF1_SP800_108::GetUnionSelector(), + Self::anyKdf(_) => TPMS_SCHEME_HASH::GetUnionSelector(), + Self::null(_) => TPMS_NULL_KDF_SCHEME::GetUnionSelector(), + } + } + + pub fn create(selector: TPM_ALG_ID) -> Result, TpmError> { + match selector { + TPM_ALG_ID::MGF1 => Ok(Some(Self::mgf1(TPMS_KDF_SCHEME_MGF1::default()))), + TPM_ALG_ID::KDF1_SP800_56A => Ok(Some(Self::kdf1_sp800_56a(TPMS_KDF_SCHEME_KDF1_SP800_56A::default()))), + TPM_ALG_ID::KDF2 => Ok(Some(Self::kdf2(TPMS_KDF_SCHEME_KDF2::default()))), + TPM_ALG_ID::KDF1_SP800_108 => Ok(Some(Self::kdf1_sp800_108(TPMS_KDF_SCHEME_KDF1_SP800_108::default()))), + TPM_ALG_ID::ANY => Ok(Some(Self::anyKdf(TPMS_SCHEME_HASH::default()))), + TPM_ALG_ID::NULL => Ok(Some(Self::null(TPMS_NULL_KDF_SCHEME::default()))), + _ => Err(TpmError::InvalidUnion), + } + } +} + +impl fmt::Debug for TPMU_KDF_SCHEME { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + Self::mgf1(inner) => write!(f, "TPMU_KDF_SCHEME::mgf1({:?})", inner), + Self::kdf1_sp800_56a(inner) => write!(f, "TPMU_KDF_SCHEME::kdf1_sp800_56a({:?})", inner), + Self::kdf2(inner) => write!(f, "TPMU_KDF_SCHEME::kdf2({:?})", inner), + Self::kdf1_sp800_108(inner) => write!(f, "TPMU_KDF_SCHEME::kdf1_sp800_108({:?})", inner), + Self::anyKdf(inner) => write!(f, "TPMU_KDF_SCHEME::anyKdf({:?})", inner), + Self::null(inner) => write!(f, "TPMU_KDF_SCHEME::null({:?})", inner), + } + } +} +impl TpmStructure for TPMU_KDF_SCHEME { + fn serialize(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + match self { + Self::mgf1(inner) => inner.serialize(buffer), + Self::kdf1_sp800_56a(inner) => inner.serialize(buffer), + Self::kdf2(inner) => inner.serialize(buffer), + Self::kdf1_sp800_108(inner) => inner.serialize(buffer), + Self::anyKdf(inner) => inner.serialize(buffer), + Self::null(inner) => inner.serialize(buffer), + } + } + + fn deserialize(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + match self { + Self::mgf1(inner) => inner.deserialize(buffer), + Self::kdf1_sp800_56a(inner) => inner.deserialize(buffer), + Self::kdf2(inner) => inner.deserialize(buffer), + Self::kdf1_sp800_108(inner) => inner.deserialize(buffer), + Self::anyKdf(inner) => inner.deserialize(buffer), + Self::null(inner) => inner.deserialize(buffer), + } + } + + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + match self { + Self::mgf1(inner) => inner.fromTpm(buffer), + Self::kdf1_sp800_56a(inner) => inner.fromTpm(buffer), + Self::kdf2(inner) => inner.fromTpm(buffer), + Self::kdf1_sp800_108(inner) => inner.fromTpm(buffer), + Self::anyKdf(inner) => inner.fromTpm(buffer), + Self::null(inner) => inner.fromTpm(buffer), + } + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + match self { + Self::mgf1(inner) => inner.fromBytes(buffer), + Self::kdf1_sp800_56a(inner) => inner.fromBytes(buffer), + Self::kdf2(inner) => inner.fromBytes(buffer), + Self::kdf1_sp800_108(inner) => inner.fromBytes(buffer), + Self::anyKdf(inner) => inner.fromBytes(buffer), + Self::null(inner) => inner.fromBytes(buffer), + } + } + +} + +impl TpmMarshaller for TPMU_KDF_SCHEME { + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + match self { + Self::mgf1(inner) => inner.toTpm(buffer), + Self::kdf1_sp800_56a(inner) => inner.toTpm(buffer), + Self::kdf2(inner) => inner.toTpm(buffer), + Self::kdf1_sp800_108(inner) => inner.toTpm(buffer), + Self::anyKdf(inner) => inner.toTpm(buffer), + Self::null(inner) => inner.toTpm(buffer), + } + } + + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + match self { + Self::mgf1(inner) => inner.initFromTpm(buffer), + Self::kdf1_sp800_56a(inner) => inner.initFromTpm(buffer), + Self::kdf2(inner) => inner.initFromTpm(buffer), + Self::kdf1_sp800_108(inner) => inner.initFromTpm(buffer), + Self::anyKdf(inner) => inner.initFromTpm(buffer), + Self::null(inner) => inner.initFromTpm(buffer), + } + } + +} + +/// This union of all asymmetric schemes is used in each of the asymmetric scheme +/// structures. The actual scheme structure is defined by the interface type used for the +/// selector (TPMI_ALG_ASYM_SCHEME). +/// One of: TPMS_KEY_SCHEME_ECDH, TPMS_KEY_SCHEME_ECMQV, TPMS_SIG_SCHEME_RSASSA, +/// TPMS_SIG_SCHEME_RSAPSS, TPMS_SIG_SCHEME_ECDSA, TPMS_SIG_SCHEME_ECDAA, +/// TPMS_SIG_SCHEME_SM2, TPMS_SIG_SCHEME_ECSCHNORR, TPMS_ENC_SCHEME_RSAES, +/// TPMS_ENC_SCHEME_OAEP, TPMS_SCHEME_HASH, TPMS_NULL_ASYM_SCHEME. +#[derive(Clone)] +pub enum TPMU_ASYM_SCHEME { + ecdh(TPMS_KEY_SCHEME_ECDH), + ecmqv(TPMS_KEY_SCHEME_ECMQV), + rsassa(TPMS_SIG_SCHEME_RSASSA), + rsapss(TPMS_SIG_SCHEME_RSAPSS), + ecdsa(TPMS_SIG_SCHEME_ECDSA), + ecdaa(TPMS_SIG_SCHEME_ECDAA), + sm2(TPMS_SIG_SCHEME_SM2), + ecschnorr(TPMS_SIG_SCHEME_ECSCHNORR), + rsaes(TPMS_ENC_SCHEME_RSAES), + oaep(TPMS_ENC_SCHEME_OAEP), + anySig(TPMS_SCHEME_HASH), + null(TPMS_NULL_ASYM_SCHEME), +} + +/// Union selector type +impl TPMU_ASYM_SCHEME { + pub fn GetUnionSelector(&self) -> TPM_ALG_ID { + match self { + Self::ecdh(_) => TPMS_KEY_SCHEME_ECDH::GetUnionSelector(), + Self::ecmqv(_) => TPMS_KEY_SCHEME_ECMQV::GetUnionSelector(), + Self::rsassa(_) => TPMS_SIG_SCHEME_RSASSA::GetUnionSelector(), + Self::rsapss(_) => TPMS_SIG_SCHEME_RSAPSS::GetUnionSelector(), + Self::ecdsa(_) => TPMS_SIG_SCHEME_ECDSA::GetUnionSelector(), + Self::ecdaa(_) => TPMS_SIG_SCHEME_ECDAA::GetUnionSelector(), + Self::sm2(_) => TPMS_SIG_SCHEME_SM2::GetUnionSelector(), + Self::ecschnorr(_) => TPMS_SIG_SCHEME_ECSCHNORR::GetUnionSelector(), + Self::rsaes(_) => TPMS_ENC_SCHEME_RSAES::GetUnionSelector(), + Self::oaep(_) => TPMS_ENC_SCHEME_OAEP::GetUnionSelector(), + Self::anySig(_) => TPMS_SCHEME_HASH::GetUnionSelector(), + Self::null(_) => TPMS_NULL_ASYM_SCHEME::GetUnionSelector(), + } + } + + pub fn create(selector: TPM_ALG_ID) -> Result, TpmError> { + match selector { + TPM_ALG_ID::ECDH => Ok(Some(Self::ecdh(TPMS_KEY_SCHEME_ECDH::default()))), + TPM_ALG_ID::ECMQV => Ok(Some(Self::ecmqv(TPMS_KEY_SCHEME_ECMQV::default()))), + TPM_ALG_ID::RSASSA => Ok(Some(Self::rsassa(TPMS_SIG_SCHEME_RSASSA::default()))), + TPM_ALG_ID::RSAPSS => Ok(Some(Self::rsapss(TPMS_SIG_SCHEME_RSAPSS::default()))), + TPM_ALG_ID::ECDSA => Ok(Some(Self::ecdsa(TPMS_SIG_SCHEME_ECDSA::default()))), + TPM_ALG_ID::ECDAA => Ok(Some(Self::ecdaa(TPMS_SIG_SCHEME_ECDAA::default()))), + TPM_ALG_ID::SM2 => Ok(Some(Self::sm2(TPMS_SIG_SCHEME_SM2::default()))), + TPM_ALG_ID::ECSCHNORR => Ok(Some(Self::ecschnorr(TPMS_SIG_SCHEME_ECSCHNORR::default()))), + TPM_ALG_ID::RSAES => Ok(Some(Self::rsaes(TPMS_ENC_SCHEME_RSAES::default()))), + TPM_ALG_ID::OAEP => Ok(Some(Self::oaep(TPMS_ENC_SCHEME_OAEP::default()))), + TPM_ALG_ID::ANY => Ok(Some(Self::anySig(TPMS_SCHEME_HASH::default()))), + TPM_ALG_ID::NULL => Ok(Some(Self::null(TPMS_NULL_ASYM_SCHEME::default()))), + _ => Err(TpmError::InvalidUnion), + } + } +} + +impl fmt::Debug for TPMU_ASYM_SCHEME { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + Self::ecdh(inner) => write!(f, "TPMU_ASYM_SCHEME::ecdh({:?})", inner), + Self::ecmqv(inner) => write!(f, "TPMU_ASYM_SCHEME::ecmqv({:?})", inner), + Self::rsassa(inner) => write!(f, "TPMU_ASYM_SCHEME::rsassa({:?})", inner), + Self::rsapss(inner) => write!(f, "TPMU_ASYM_SCHEME::rsapss({:?})", inner), + Self::ecdsa(inner) => write!(f, "TPMU_ASYM_SCHEME::ecdsa({:?})", inner), + Self::ecdaa(inner) => write!(f, "TPMU_ASYM_SCHEME::ecdaa({:?})", inner), + Self::sm2(inner) => write!(f, "TPMU_ASYM_SCHEME::sm2({:?})", inner), + Self::ecschnorr(inner) => write!(f, "TPMU_ASYM_SCHEME::ecschnorr({:?})", inner), + Self::rsaes(inner) => write!(f, "TPMU_ASYM_SCHEME::rsaes({:?})", inner), + Self::oaep(inner) => write!(f, "TPMU_ASYM_SCHEME::oaep({:?})", inner), + Self::anySig(inner) => write!(f, "TPMU_ASYM_SCHEME::anySig({:?})", inner), + Self::null(inner) => write!(f, "TPMU_ASYM_SCHEME::null({:?})", inner), + } + } +} +impl TpmStructure for TPMU_ASYM_SCHEME { + fn serialize(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + match self { + Self::ecdh(inner) => inner.serialize(buffer), + Self::ecmqv(inner) => inner.serialize(buffer), + Self::rsassa(inner) => inner.serialize(buffer), + Self::rsapss(inner) => inner.serialize(buffer), + Self::ecdsa(inner) => inner.serialize(buffer), + Self::ecdaa(inner) => inner.serialize(buffer), + Self::sm2(inner) => inner.serialize(buffer), + Self::ecschnorr(inner) => inner.serialize(buffer), + Self::rsaes(inner) => inner.serialize(buffer), + Self::oaep(inner) => inner.serialize(buffer), + Self::anySig(inner) => inner.serialize(buffer), + Self::null(inner) => inner.serialize(buffer), + } + } + + fn deserialize(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + match self { + Self::ecdh(inner) => inner.deserialize(buffer), + Self::ecmqv(inner) => inner.deserialize(buffer), + Self::rsassa(inner) => inner.deserialize(buffer), + Self::rsapss(inner) => inner.deserialize(buffer), + Self::ecdsa(inner) => inner.deserialize(buffer), + Self::ecdaa(inner) => inner.deserialize(buffer), + Self::sm2(inner) => inner.deserialize(buffer), + Self::ecschnorr(inner) => inner.deserialize(buffer), + Self::rsaes(inner) => inner.deserialize(buffer), + Self::oaep(inner) => inner.deserialize(buffer), + Self::anySig(inner) => inner.deserialize(buffer), + Self::null(inner) => inner.deserialize(buffer), + } + } + + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + match self { + Self::ecdh(inner) => inner.fromTpm(buffer), + Self::ecmqv(inner) => inner.fromTpm(buffer), + Self::rsassa(inner) => inner.fromTpm(buffer), + Self::rsapss(inner) => inner.fromTpm(buffer), + Self::ecdsa(inner) => inner.fromTpm(buffer), + Self::ecdaa(inner) => inner.fromTpm(buffer), + Self::sm2(inner) => inner.fromTpm(buffer), + Self::ecschnorr(inner) => inner.fromTpm(buffer), + Self::rsaes(inner) => inner.fromTpm(buffer), + Self::oaep(inner) => inner.fromTpm(buffer), + Self::anySig(inner) => inner.fromTpm(buffer), + Self::null(inner) => inner.fromTpm(buffer), + } + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + match self { + Self::ecdh(inner) => inner.fromBytes(buffer), + Self::ecmqv(inner) => inner.fromBytes(buffer), + Self::rsassa(inner) => inner.fromBytes(buffer), + Self::rsapss(inner) => inner.fromBytes(buffer), + Self::ecdsa(inner) => inner.fromBytes(buffer), + Self::ecdaa(inner) => inner.fromBytes(buffer), + Self::sm2(inner) => inner.fromBytes(buffer), + Self::ecschnorr(inner) => inner.fromBytes(buffer), + Self::rsaes(inner) => inner.fromBytes(buffer), + Self::oaep(inner) => inner.fromBytes(buffer), + Self::anySig(inner) => inner.fromBytes(buffer), + Self::null(inner) => inner.fromBytes(buffer), + } + } + +} + +impl TpmMarshaller for TPMU_ASYM_SCHEME { + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + match self { + Self::ecdh(inner) => inner.toTpm(buffer), + Self::ecmqv(inner) => inner.toTpm(buffer), + Self::rsassa(inner) => inner.toTpm(buffer), + Self::rsapss(inner) => inner.toTpm(buffer), + Self::ecdsa(inner) => inner.toTpm(buffer), + Self::ecdaa(inner) => inner.toTpm(buffer), + Self::sm2(inner) => inner.toTpm(buffer), + Self::ecschnorr(inner) => inner.toTpm(buffer), + Self::rsaes(inner) => inner.toTpm(buffer), + Self::oaep(inner) => inner.toTpm(buffer), + Self::anySig(inner) => inner.toTpm(buffer), + Self::null(inner) => inner.toTpm(buffer), + } + } + + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + match self { + Self::ecdh(inner) => inner.initFromTpm(buffer), + Self::ecmqv(inner) => inner.initFromTpm(buffer), + Self::rsassa(inner) => inner.initFromTpm(buffer), + Self::rsapss(inner) => inner.initFromTpm(buffer), + Self::ecdsa(inner) => inner.initFromTpm(buffer), + Self::ecdaa(inner) => inner.initFromTpm(buffer), + Self::sm2(inner) => inner.initFromTpm(buffer), + Self::ecschnorr(inner) => inner.initFromTpm(buffer), + Self::rsaes(inner) => inner.initFromTpm(buffer), + Self::oaep(inner) => inner.initFromTpm(buffer), + Self::anySig(inner) => inner.initFromTpm(buffer), + Self::null(inner) => inner.initFromTpm(buffer), + } + } + +} + +/// A TPMU_SIGNATURE_COMPOSITE is a union of the various signatures that are supported by +/// a particular TPM implementation. The union allows substitution of any signature +/// algorithm wherever a signature is required in a structure. +/// One of: TPMS_SIGNATURE_RSASSA, TPMS_SIGNATURE_RSAPSS, TPMS_SIGNATURE_ECDSA, +/// TPMS_SIGNATURE_ECDAA, TPMS_SIGNATURE_SM2, TPMS_SIGNATURE_ECSCHNORR, TPMT_HA, +/// TPMS_SCHEME_HASH, TPMS_NULL_SIGNATURE. +#[derive(Clone)] +pub enum TPMU_SIGNATURE { + rsassa(TPMS_SIGNATURE_RSASSA), + rsapss(TPMS_SIGNATURE_RSAPSS), + ecdsa(TPMS_SIGNATURE_ECDSA), + ecdaa(TPMS_SIGNATURE_ECDAA), + sm2(TPMS_SIGNATURE_SM2), + ecschnorr(TPMS_SIGNATURE_ECSCHNORR), + hmac(TPMT_HA), + any(TPMS_SCHEME_HASH), + null(TPMS_NULL_SIGNATURE), +} + +/// Union selector type +impl TPMU_SIGNATURE { + pub fn GetUnionSelector(&self) -> TPM_ALG_ID { + match self { + Self::rsassa(_) => TPMS_SIGNATURE_RSASSA::GetUnionSelector(), + Self::rsapss(_) => TPMS_SIGNATURE_RSAPSS::GetUnionSelector(), + Self::ecdsa(_) => TPMS_SIGNATURE_ECDSA::GetUnionSelector(), + Self::ecdaa(_) => TPMS_SIGNATURE_ECDAA::GetUnionSelector(), + Self::sm2(_) => TPMS_SIGNATURE_SM2::GetUnionSelector(), + Self::ecschnorr(_) => TPMS_SIGNATURE_ECSCHNORR::GetUnionSelector(), + Self::hmac(_) => TPMT_HA::GetUnionSelector(), + Self::any(_) => TPMS_SCHEME_HASH::GetUnionSelector(), + Self::null(_) => TPMS_NULL_SIGNATURE::GetUnionSelector(), + } + } + + pub fn create(selector: TPM_ALG_ID) -> Result, TpmError> { + match selector { + TPM_ALG_ID::RSASSA => Ok(Some(Self::rsassa(TPMS_SIGNATURE_RSASSA::default()))), + TPM_ALG_ID::RSAPSS => Ok(Some(Self::rsapss(TPMS_SIGNATURE_RSAPSS::default()))), + TPM_ALG_ID::ECDSA => Ok(Some(Self::ecdsa(TPMS_SIGNATURE_ECDSA::default()))), + TPM_ALG_ID::ECDAA => Ok(Some(Self::ecdaa(TPMS_SIGNATURE_ECDAA::default()))), + TPM_ALG_ID::SM2 => Ok(Some(Self::sm2(TPMS_SIGNATURE_SM2::default()))), + TPM_ALG_ID::ECSCHNORR => Ok(Some(Self::ecschnorr(TPMS_SIGNATURE_ECSCHNORR::default()))), + TPM_ALG_ID::HMAC => Ok(Some(Self::hmac(TPMT_HA::default()))), + TPM_ALG_ID::ANY => Ok(Some(Self::any(TPMS_SCHEME_HASH::default()))), + TPM_ALG_ID::NULL => Ok(Some(Self::null(TPMS_NULL_SIGNATURE::default()))), + _ => Err(TpmError::InvalidUnion), + } + } +} + +impl fmt::Debug for TPMU_SIGNATURE { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + Self::rsassa(inner) => write!(f, "TPMU_SIGNATURE::rsassa({:?})", inner), + Self::rsapss(inner) => write!(f, "TPMU_SIGNATURE::rsapss({:?})", inner), + Self::ecdsa(inner) => write!(f, "TPMU_SIGNATURE::ecdsa({:?})", inner), + Self::ecdaa(inner) => write!(f, "TPMU_SIGNATURE::ecdaa({:?})", inner), + Self::sm2(inner) => write!(f, "TPMU_SIGNATURE::sm2({:?})", inner), + Self::ecschnorr(inner) => write!(f, "TPMU_SIGNATURE::ecschnorr({:?})", inner), + Self::hmac(inner) => write!(f, "TPMU_SIGNATURE::hmac({:?})", inner), + Self::any(inner) => write!(f, "TPMU_SIGNATURE::any({:?})", inner), + Self::null(inner) => write!(f, "TPMU_SIGNATURE::null({:?})", inner), + } + } +} +impl TpmStructure for TPMU_SIGNATURE { + fn serialize(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + match self { + Self::rsassa(inner) => inner.serialize(buffer), + Self::rsapss(inner) => inner.serialize(buffer), + Self::ecdsa(inner) => inner.serialize(buffer), + Self::ecdaa(inner) => inner.serialize(buffer), + Self::sm2(inner) => inner.serialize(buffer), + Self::ecschnorr(inner) => inner.serialize(buffer), + Self::hmac(inner) => inner.serialize(buffer), + Self::any(inner) => inner.serialize(buffer), + Self::null(inner) => inner.serialize(buffer), + } + } + + fn deserialize(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + match self { + Self::rsassa(inner) => inner.deserialize(buffer), + Self::rsapss(inner) => inner.deserialize(buffer), + Self::ecdsa(inner) => inner.deserialize(buffer), + Self::ecdaa(inner) => inner.deserialize(buffer), + Self::sm2(inner) => inner.deserialize(buffer), + Self::ecschnorr(inner) => inner.deserialize(buffer), + Self::hmac(inner) => inner.deserialize(buffer), + Self::any(inner) => inner.deserialize(buffer), + Self::null(inner) => inner.deserialize(buffer), + } + } + + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + match self { + Self::rsassa(inner) => inner.fromTpm(buffer), + Self::rsapss(inner) => inner.fromTpm(buffer), + Self::ecdsa(inner) => inner.fromTpm(buffer), + Self::ecdaa(inner) => inner.fromTpm(buffer), + Self::sm2(inner) => inner.fromTpm(buffer), + Self::ecschnorr(inner) => inner.fromTpm(buffer), + Self::hmac(inner) => inner.fromTpm(buffer), + Self::any(inner) => inner.fromTpm(buffer), + Self::null(inner) => inner.fromTpm(buffer), + } + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + match self { + Self::rsassa(inner) => inner.fromBytes(buffer), + Self::rsapss(inner) => inner.fromBytes(buffer), + Self::ecdsa(inner) => inner.fromBytes(buffer), + Self::ecdaa(inner) => inner.fromBytes(buffer), + Self::sm2(inner) => inner.fromBytes(buffer), + Self::ecschnorr(inner) => inner.fromBytes(buffer), + Self::hmac(inner) => inner.fromBytes(buffer), + Self::any(inner) => inner.fromBytes(buffer), + Self::null(inner) => inner.fromBytes(buffer), + } + } + +} + +impl TpmMarshaller for TPMU_SIGNATURE { + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + match self { + Self::rsassa(inner) => inner.toTpm(buffer), + Self::rsapss(inner) => inner.toTpm(buffer), + Self::ecdsa(inner) => inner.toTpm(buffer), + Self::ecdaa(inner) => inner.toTpm(buffer), + Self::sm2(inner) => inner.toTpm(buffer), + Self::ecschnorr(inner) => inner.toTpm(buffer), + Self::hmac(inner) => inner.toTpm(buffer), + Self::any(inner) => inner.toTpm(buffer), + Self::null(inner) => inner.toTpm(buffer), + } + } + + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + match self { + Self::rsassa(inner) => inner.initFromTpm(buffer), + Self::rsapss(inner) => inner.initFromTpm(buffer), + Self::ecdsa(inner) => inner.initFromTpm(buffer), + Self::ecdaa(inner) => inner.initFromTpm(buffer), + Self::sm2(inner) => inner.initFromTpm(buffer), + Self::ecschnorr(inner) => inner.initFromTpm(buffer), + Self::hmac(inner) => inner.initFromTpm(buffer), + Self::any(inner) => inner.initFromTpm(buffer), + Self::null(inner) => inner.initFromTpm(buffer), + } + } + +} + +/// This is the union of all values allowed in in the unique field of a TPMT_PUBLIC. +/// One of: TPM2B_DIGEST_KEYEDHASH, TPM2B_DIGEST_SYMCIPHER, TPM2B_PUBLIC_KEY_RSA, +/// TPMS_ECC_POINT, TPMS_DERIVE. +#[derive(Clone)] +pub enum TPMU_PUBLIC_ID { + keyedHash(TPM2B_DIGEST_KEYEDHASH), + sym(TPM2B_DIGEST_SYMCIPHER), + rsa(TPM2B_PUBLIC_KEY_RSA), + ecc(TPMS_ECC_POINT), + derive(TPMS_DERIVE), +} + +/// Union selector type +impl TPMU_PUBLIC_ID { + pub fn GetUnionSelector(&self) -> TPM_ALG_ID { + match self { + Self::keyedHash(_) => TPM2B_DIGEST_KEYEDHASH::GetUnionSelector(), + Self::sym(_) => TPM2B_DIGEST_SYMCIPHER::GetUnionSelector(), + Self::rsa(_) => TPM2B_PUBLIC_KEY_RSA::GetUnionSelector(), + Self::ecc(_) => TPMS_ECC_POINT::GetUnionSelector(), + Self::derive(_) => TPMS_DERIVE::GetUnionSelector(), + } + } + + pub fn create(selector: TPM_ALG_ID) -> Result, TpmError> { + match selector { + TPM_ALG_ID::KEYEDHASH => Ok(Some(Self::keyedHash(TPM2B_DIGEST_KEYEDHASH::default()))), + TPM_ALG_ID::SYMCIPHER => Ok(Some(Self::sym(TPM2B_DIGEST_SYMCIPHER::default()))), + TPM_ALG_ID::RSA => Ok(Some(Self::rsa(TPM2B_PUBLIC_KEY_RSA::default()))), + TPM_ALG_ID::ECC => Ok(Some(Self::ecc(TPMS_ECC_POINT::default()))), + TPM_ALG_ID::ANY => Ok(Some(Self::derive(TPMS_DERIVE::default()))), + _ => Err(TpmError::InvalidUnion), + } + } +} + +impl fmt::Debug for TPMU_PUBLIC_ID { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + Self::keyedHash(inner) => write!(f, "TPMU_PUBLIC_ID::keyedHash({:?})", inner), + Self::sym(inner) => write!(f, "TPMU_PUBLIC_ID::sym({:?})", inner), + Self::rsa(inner) => write!(f, "TPMU_PUBLIC_ID::rsa({:?})", inner), + Self::ecc(inner) => write!(f, "TPMU_PUBLIC_ID::ecc({:?})", inner), + Self::derive(inner) => write!(f, "TPMU_PUBLIC_ID::derive({:?})", inner), + } + } +} +impl TpmStructure for TPMU_PUBLIC_ID { + fn serialize(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + match self { + Self::keyedHash(inner) => inner.serialize(buffer), + Self::sym(inner) => inner.serialize(buffer), + Self::rsa(inner) => inner.serialize(buffer), + Self::ecc(inner) => inner.serialize(buffer), + Self::derive(inner) => inner.serialize(buffer), + } + } + + fn deserialize(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + match self { + Self::keyedHash(inner) => inner.deserialize(buffer), + Self::sym(inner) => inner.deserialize(buffer), + Self::rsa(inner) => inner.deserialize(buffer), + Self::ecc(inner) => inner.deserialize(buffer), + Self::derive(inner) => inner.deserialize(buffer), + } + } + + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + match self { + Self::keyedHash(inner) => inner.fromTpm(buffer), + Self::sym(inner) => inner.fromTpm(buffer), + Self::rsa(inner) => inner.fromTpm(buffer), + Self::ecc(inner) => inner.fromTpm(buffer), + Self::derive(inner) => inner.fromTpm(buffer), + } + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + match self { + Self::keyedHash(inner) => inner.fromBytes(buffer), + Self::sym(inner) => inner.fromBytes(buffer), + Self::rsa(inner) => inner.fromBytes(buffer), + Self::ecc(inner) => inner.fromBytes(buffer), + Self::derive(inner) => inner.fromBytes(buffer), + } + } + +} + +impl TpmMarshaller for TPMU_PUBLIC_ID { + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + match self { + Self::keyedHash(inner) => inner.toTpm(buffer), + Self::sym(inner) => inner.toTpm(buffer), + Self::rsa(inner) => inner.toTpm(buffer), + Self::ecc(inner) => inner.toTpm(buffer), + Self::derive(inner) => inner.toTpm(buffer), + } + } + + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + match self { + Self::keyedHash(inner) => inner.initFromTpm(buffer), + Self::sym(inner) => inner.initFromTpm(buffer), + Self::rsa(inner) => inner.initFromTpm(buffer), + Self::ecc(inner) => inner.initFromTpm(buffer), + Self::derive(inner) => inner.initFromTpm(buffer), + } + } + +} + +/// Table 199 defines the possible parameter definition structures that may be contained +/// in the public portion of a key. If the Object can be a parent, the first field must be +/// a TPMT_SYM_DEF_OBJECT. See 11.1.7. +/// One of: TPMS_KEYEDHASH_PARMS, TPMS_SYMCIPHER_PARMS, TPMS_RSA_PARMS, TPMS_ECC_PARMS, +/// TPMS_ASYM_PARMS. +#[derive(Clone)] +pub enum TPMU_PUBLIC_PARMS { + keyedHashDetail(TPMS_KEYEDHASH_PARMS), + symDetail(TPMS_SYMCIPHER_PARMS), + rsaDetail(TPMS_RSA_PARMS), + eccDetail(TPMS_ECC_PARMS), + asymDetail(TPMS_ASYM_PARMS), +} + +/// Union selector type +impl TPMU_PUBLIC_PARMS { + pub fn GetUnionSelector(&self) -> TPM_ALG_ID { + match self { + Self::keyedHashDetail(_) => TPMS_KEYEDHASH_PARMS::GetUnionSelector(), + Self::symDetail(_) => TPMS_SYMCIPHER_PARMS::GetUnionSelector(), + Self::rsaDetail(_) => TPMS_RSA_PARMS::GetUnionSelector(), + Self::eccDetail(_) => TPMS_ECC_PARMS::GetUnionSelector(), + Self::asymDetail(_) => TPMS_ASYM_PARMS::GetUnionSelector(), + } + } + + pub fn create(selector: TPM_ALG_ID) -> Result, TpmError> { + match selector { + TPM_ALG_ID::KEYEDHASH => Ok(Some(Self::keyedHashDetail(TPMS_KEYEDHASH_PARMS::default()))), + TPM_ALG_ID::SYMCIPHER => Ok(Some(Self::symDetail(TPMS_SYMCIPHER_PARMS::default()))), + TPM_ALG_ID::RSA => Ok(Some(Self::rsaDetail(TPMS_RSA_PARMS::default()))), + TPM_ALG_ID::ECC => Ok(Some(Self::eccDetail(TPMS_ECC_PARMS::default()))), + TPM_ALG_ID::ANY => Ok(Some(Self::asymDetail(TPMS_ASYM_PARMS::default()))), + _ => Err(TpmError::InvalidUnion), + } + } +} + +impl fmt::Debug for TPMU_PUBLIC_PARMS { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + Self::keyedHashDetail(inner) => write!(f, "TPMU_PUBLIC_PARMS::keyedHashDetail({:?})", inner), + Self::symDetail(inner) => write!(f, "TPMU_PUBLIC_PARMS::symDetail({:?})", inner), + Self::rsaDetail(inner) => write!(f, "TPMU_PUBLIC_PARMS::rsaDetail({:?})", inner), + Self::eccDetail(inner) => write!(f, "TPMU_PUBLIC_PARMS::eccDetail({:?})", inner), + Self::asymDetail(inner) => write!(f, "TPMU_PUBLIC_PARMS::asymDetail({:?})", inner), + } + } +} +impl TpmStructure for TPMU_PUBLIC_PARMS { + fn serialize(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + match self { + Self::keyedHashDetail(inner) => inner.serialize(buffer), + Self::symDetail(inner) => inner.serialize(buffer), + Self::rsaDetail(inner) => inner.serialize(buffer), + Self::eccDetail(inner) => inner.serialize(buffer), + Self::asymDetail(inner) => inner.serialize(buffer), + } + } + + fn deserialize(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + match self { + Self::keyedHashDetail(inner) => inner.deserialize(buffer), + Self::symDetail(inner) => inner.deserialize(buffer), + Self::rsaDetail(inner) => inner.deserialize(buffer), + Self::eccDetail(inner) => inner.deserialize(buffer), + Self::asymDetail(inner) => inner.deserialize(buffer), + } + } + + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + match self { + Self::keyedHashDetail(inner) => inner.fromTpm(buffer), + Self::symDetail(inner) => inner.fromTpm(buffer), + Self::rsaDetail(inner) => inner.fromTpm(buffer), + Self::eccDetail(inner) => inner.fromTpm(buffer), + Self::asymDetail(inner) => inner.fromTpm(buffer), + } + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + match self { + Self::keyedHashDetail(inner) => inner.fromBytes(buffer), + Self::symDetail(inner) => inner.fromBytes(buffer), + Self::rsaDetail(inner) => inner.fromBytes(buffer), + Self::eccDetail(inner) => inner.fromBytes(buffer), + Self::asymDetail(inner) => inner.fromBytes(buffer), + } + } + +} + +impl TpmMarshaller for TPMU_PUBLIC_PARMS { + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + match self { + Self::keyedHashDetail(inner) => inner.toTpm(buffer), + Self::symDetail(inner) => inner.toTpm(buffer), + Self::rsaDetail(inner) => inner.toTpm(buffer), + Self::eccDetail(inner) => inner.toTpm(buffer), + Self::asymDetail(inner) => inner.toTpm(buffer), + } + } + + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + match self { + Self::keyedHashDetail(inner) => inner.initFromTpm(buffer), + Self::symDetail(inner) => inner.initFromTpm(buffer), + Self::rsaDetail(inner) => inner.initFromTpm(buffer), + Self::eccDetail(inner) => inner.initFromTpm(buffer), + Self::asymDetail(inner) => inner.initFromTpm(buffer), + } + } + +} + +/// Table 205 Definition of TPMU_SENSITIVE_COMPOSITE Union [IN/OUT] +/// One of: TPM2B_PRIVATE_KEY_RSA, TPM2B_ECC_PARAMETER, TPM2B_SENSITIVE_DATA, +/// TPM2B_SYM_KEY, TPM2B_PRIVATE_VENDOR_SPECIFIC. +#[derive(Clone)] +pub enum TPMU_SENSITIVE_COMPOSITE { + rsa(TPM2B_PRIVATE_KEY_RSA), + ecc(TPM2B_ECC_PARAMETER), + bits(TPM2B_SENSITIVE_DATA), + sym(TPM2B_SYM_KEY), + any(TPM2B_PRIVATE_VENDOR_SPECIFIC), +} + +/// Union selector type +impl TPMU_SENSITIVE_COMPOSITE { + pub fn GetUnionSelector(&self) -> TPM_ALG_ID { + match self { + Self::rsa(_) => TPM2B_PRIVATE_KEY_RSA::GetUnionSelector(), + Self::ecc(_) => TPM2B_ECC_PARAMETER::GetUnionSelector(), + Self::bits(_) => TPM2B_SENSITIVE_DATA::GetUnionSelector(), + Self::sym(_) => TPM2B_SYM_KEY::GetUnionSelector(), + Self::any(_) => TPM2B_PRIVATE_VENDOR_SPECIFIC::GetUnionSelector(), + } + } + + pub fn create(selector: TPM_ALG_ID) -> Result, TpmError> { + match selector { + TPM_ALG_ID::RSA => Ok(Some(Self::rsa(TPM2B_PRIVATE_KEY_RSA::default()))), + TPM_ALG_ID::ECC => Ok(Some(Self::ecc(TPM2B_ECC_PARAMETER::default()))), + TPM_ALG_ID::KEYEDHASH => Ok(Some(Self::bits(TPM2B_SENSITIVE_DATA::default()))), + TPM_ALG_ID::SYMCIPHER => Ok(Some(Self::sym(TPM2B_SYM_KEY::default()))), + TPM_ALG_ID::ANY => Ok(Some(Self::any(TPM2B_PRIVATE_VENDOR_SPECIFIC::default()))), + _ => Err(TpmError::InvalidUnion), + } + } +} + +impl fmt::Debug for TPMU_SENSITIVE_COMPOSITE { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + Self::rsa(inner) => write!(f, "TPMU_SENSITIVE_COMPOSITE::rsa({:?})", inner), + Self::ecc(inner) => write!(f, "TPMU_SENSITIVE_COMPOSITE::ecc({:?})", inner), + Self::bits(inner) => write!(f, "TPMU_SENSITIVE_COMPOSITE::bits({:?})", inner), + Self::sym(inner) => write!(f, "TPMU_SENSITIVE_COMPOSITE::sym({:?})", inner), + Self::any(inner) => write!(f, "TPMU_SENSITIVE_COMPOSITE::any({:?})", inner), + } + } +} +impl TpmStructure for TPMU_SENSITIVE_COMPOSITE { + fn serialize(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + match self { + Self::rsa(inner) => inner.serialize(buffer), + Self::ecc(inner) => inner.serialize(buffer), + Self::bits(inner) => inner.serialize(buffer), + Self::sym(inner) => inner.serialize(buffer), + Self::any(inner) => inner.serialize(buffer), + } + } + + fn deserialize(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + match self { + Self::rsa(inner) => inner.deserialize(buffer), + Self::ecc(inner) => inner.deserialize(buffer), + Self::bits(inner) => inner.deserialize(buffer), + Self::sym(inner) => inner.deserialize(buffer), + Self::any(inner) => inner.deserialize(buffer), + } + } + + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + match self { + Self::rsa(inner) => inner.fromTpm(buffer), + Self::ecc(inner) => inner.fromTpm(buffer), + Self::bits(inner) => inner.fromTpm(buffer), + Self::sym(inner) => inner.fromTpm(buffer), + Self::any(inner) => inner.fromTpm(buffer), + } + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + match self { + Self::rsa(inner) => inner.fromBytes(buffer), + Self::ecc(inner) => inner.fromBytes(buffer), + Self::bits(inner) => inner.fromBytes(buffer), + Self::sym(inner) => inner.fromBytes(buffer), + Self::any(inner) => inner.fromBytes(buffer), + } + } + +} + +impl TpmMarshaller for TPMU_SENSITIVE_COMPOSITE { + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + match self { + Self::rsa(inner) => inner.toTpm(buffer), + Self::ecc(inner) => inner.toTpm(buffer), + Self::bits(inner) => inner.toTpm(buffer), + Self::sym(inner) => inner.toTpm(buffer), + Self::any(inner) => inner.toTpm(buffer), + } + } + + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + match self { + Self::rsa(inner) => inner.initFromTpm(buffer), + Self::ecc(inner) => inner.initFromTpm(buffer), + Self::bits(inner) => inner.initFromTpm(buffer), + Self::sym(inner) => inner.initFromTpm(buffer), + Self::any(inner) => inner.initFromTpm(buffer), + } + } + +} + +/// Handle of a loaded TPM key or other object [TSS] +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM_HANDLE { + /// Handle value + #[derivative(Default(value="TPM_RH::NULL.into()"))] + pub handle: u32, + + /// The authorization value associated with this handle + pub auth_value: Vec, + + /// The name associated with this handle + pub name: Vec, +} + +impl TPM_HANDLE { + /// Creates a new instance with the specified values + pub fn new( + handle: u32, + ) -> Self { + Self { + handle: handle.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM_HANDLE { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeInt(self.handle as u32); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.handle = buf.readInt() as u32; + Ok(()) + } + +} + +impl TpmMarshaller for TPM_HANDLE { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// Base class for empty union elements. +/// An empty union element does not contain any data to marshal. +/// This data structure can be used in place of any other union +/// initialized with its own empty element. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPMS_NULL_UNION { +} + +impl TPMS_NULL_UNION { + fn GetUnionSelector() -> TPM_ALG_ID { + TPM_ALG_ID::NULL + } +} + +impl TpmStructure for TPMS_NULL_UNION { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + Ok(()) + } + +} + +impl TpmMarshaller for TPMS_NULL_UNION { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// This structure is used as a placeholder. In some cases, a union will have a selector +/// value with no data to unmarshal when that type is selected. Rather than leave the +/// entry empty, TPMS_EMPTY may be selected. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPMS_EMPTY { +} + +impl TPMS_EMPTY { + fn GetUnionSelector() -> TPM_ALG_ID { + TPM_ALG_ID::RSAES + } +} + +impl TpmStructure for TPMS_EMPTY { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + Ok(()) + } + +} + +impl TpmMarshaller for TPMS_EMPTY { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// This structure is a return value for a TPM2_GetCapability() that reads the installed algorithms. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPMS_ALGORITHM_DESCRIPTION { + /// An algorithm + #[derivative(Default(value="TPM_ALG_ID::NULL"))] + pub alg: TPM_ALG_ID, + + /// The attributes of the algorithm + pub attributes: TPMA_ALGORITHM, +} + +impl TPMS_ALGORITHM_DESCRIPTION { + /// Creates a new instance with the specified values + pub fn new( + alg: TPM_ALG_ID, + attributes: TPMA_ALGORITHM, + ) -> Self { + Self { + alg: alg.clone(), + attributes: attributes.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPMS_ALGORITHM_DESCRIPTION { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeShort(self.alg.into()); + buf.writeInt(self.attributes.into()); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.alg = TPM_ALG_ID(buf.readShort() as u16); + self.attributes = TPMA_ALGORITHM(buf.readInt() as u32); + Ok(()) + } + +} + +impl TpmMarshaller for TPMS_ALGORITHM_DESCRIPTION { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// Table 80 shows the basic hash-agile structure used in this specification. To handle +/// hash agility, this structure uses the hashAlg parameter to indicate the algorithm used +/// to compute the digest and, by implication, the size of the digest. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPMT_HA { + /// Selector of the hash contained in the digest that implies the size of the digest + /// NOTE The leading + on the type indicates that this structure should pass an indication + /// to the unmarshaling function for TPMI_ALG_HASH so that TPM_ALG_NULL will be allowed if + /// a use of a TPMT_HA allows TPM_ALG_NULL. + #[derivative(Default(value="TPM_ALG_ID::NULL"))] + pub hashAlg: TPM_ALG_ID, + + /// Hash value + pub digest: Vec, +} + +impl TPMT_HA { + /// Creates a new instance with the specified values + pub fn new( + hashAlg: TPM_ALG_ID, + digest: &Vec, + ) -> Self { + Self { + hashAlg: hashAlg.clone(), + digest: digest.clone(), + ..Default::default() + } + } + + fn GetUnionSelector() -> TPM_ALG_ID { + TPM_ALG_ID::HMAC + } +} + +impl TpmStructure for TPMT_HA { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeShort(self.hashAlg.into()); + buf.writeByteBuf(&self.digest); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.hashAlg = TPM_ALG_ID(buf.readShort() as u16); + self.digest = buf.readByteBuf(Crypto::digestSize(self.hashAlg)); + Ok(()) + } + +} + +impl TpmMarshaller for TPMT_HA { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// This structure is used for a sized buffer that cannot be larger than the largest +/// digest produced by any hash algorithm implemented on the TPM. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2B_DIGEST { + /// The buffer area that can be no larger than a digest + pub buffer: Vec, +} + +impl TPM2B_DIGEST { + /// Creates a new instance with the specified values + pub fn new( + buffer: &Vec, + ) -> Self { + Self { + buffer: buffer.clone(), + ..Default::default() + } + } + + fn GetUnionSelector() -> TPM_ALG_ID { + TPM_ALG_ID::KEYEDHASH + } +} + +impl TpmStructure for TPM2B_DIGEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.buffer, 2); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.buffer = buf.readSizedByteBuf(2); + Ok(()) + } + +} + +impl TpmMarshaller for TPM2B_DIGEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// This structure is used for a data buffer that is required to be no larger than the +/// size of the Name of an object. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2B_DATA { + pub buffer: Vec, +} + +impl TPM2B_DATA { + /// Creates a new instance with the specified values + pub fn new( + buffer: &Vec, + ) -> Self { + Self { + buffer: buffer.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2B_DATA { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.buffer, 2); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.buffer = buf.readSizedByteBuf(2); + Ok(()) + } + +} + +impl TpmMarshaller for TPM2B_DATA { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// Table 83 Definition of Types for TPM2B_NONCE +pub type TPM2B_NONCE = TPM2B_DIGEST; + +/// This structure is used for an authorization value and limits an authValue to being no +/// larger than the largest digest produced by a TPM. In order to ensure consistency +/// within an object, the authValue may be no larger than the size of the digest produced +/// by the objects nameAlg. This ensures that any TPM that can load the object will be +/// able to handle the authValue of the object. +pub type TPM2B_AUTH = TPM2B_DIGEST; + +/// This type is a sized buffer that can hold an operand for a comparison with an NV Index +/// location. The maximum size of the operand is implementation dependent but a TPM is +/// required to support an operand size that is at least as big as the digest produced by +/// any of the hash algorithms implemented on the TPM. +pub type TPM2B_OPERAND = TPM2B_DIGEST; + +/// This type is a sized buffer that can hold event data. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2B_EVENT { + /// The operand + pub buffer: Vec, +} + +impl TPM2B_EVENT { + /// Creates a new instance with the specified values + pub fn new( + buffer: &Vec, + ) -> Self { + Self { + buffer: buffer.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2B_EVENT { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.buffer, 2); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.buffer = buf.readSizedByteBuf(2); + Ok(()) + } + +} + +impl TpmMarshaller for TPM2B_EVENT { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// This type is a sized buffer that can hold a maximally sized buffer for commands that +/// use a large data buffer such as TPM2_Hash(), TPM2_SequenceUpdate(), or TPM2_FieldUpgradeData(). +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2B_MAX_BUFFER { + /// The operand + pub buffer: Vec, +} + +impl TPM2B_MAX_BUFFER { + /// Creates a new instance with the specified values + pub fn new( + buffer: &Vec, + ) -> Self { + Self { + buffer: buffer.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2B_MAX_BUFFER { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.buffer, 2); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.buffer = buf.readSizedByteBuf(2); + Ok(()) + } + +} + +impl TpmMarshaller for TPM2B_MAX_BUFFER { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// This type is a sized buffer that can hold a maximally sized buffer for NV data +/// commands such as TPM2_NV_Read(), TPM2_NV_Write(), and TPM2_NV_Certify(). +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2B_MAX_NV_BUFFER { + /// The operand + /// NOTE MAX_NV_BUFFER_SIZE is TPM-dependent + pub buffer: Vec, +} + +impl TPM2B_MAX_NV_BUFFER { + /// Creates a new instance with the specified values + pub fn new( + buffer: &Vec, + ) -> Self { + Self { + buffer: buffer.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2B_MAX_NV_BUFFER { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.buffer, 2); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.buffer = buf.readSizedByteBuf(2); + Ok(()) + } + +} + +impl TpmMarshaller for TPM2B_MAX_NV_BUFFER { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// This TPM-dependent structure is used to provide the timeout value for an +/// authorization. The size shall be 8 or less. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2B_TIMEOUT { + /// The timeout value + pub buffer: Vec, +} + +impl TPM2B_TIMEOUT { + /// Creates a new instance with the specified values + pub fn new( + buffer: &Vec, + ) -> Self { + Self { + buffer: buffer.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2B_TIMEOUT { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.buffer, 2); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.buffer = buf.readSizedByteBuf(2); + Ok(()) + } + +} + +impl TpmMarshaller for TPM2B_TIMEOUT { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// This structure is used for passing an initial value for a symmetric block cipher to or +/// from the TPM. The size is set to be the largest block size of any implemented +/// symmetric cipher implemented on the TPM. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2B_IV { + /// The IV value + pub buffer: Vec, +} + +impl TPM2B_IV { + /// Creates a new instance with the specified values + pub fn new( + buffer: &Vec, + ) -> Self { + Self { + buffer: buffer.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2B_IV { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.buffer, 2); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.buffer = buf.readSizedByteBuf(2); + Ok(()) + } + +} + +impl TpmMarshaller for TPM2B_IV { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// This buffer holds a Name for any entity type. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2B_NAME { + /// The Name structure + pub name: Vec, +} + +impl TPM2B_NAME { + /// Creates a new instance with the specified values + pub fn new( + name: &Vec, + ) -> Self { + Self { + name: name.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2B_NAME { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.name, 2); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.name = buf.readSizedByteBuf(2); + Ok(()) + } + +} + +impl TpmMarshaller for TPM2B_NAME { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// This structure provides a standard method of specifying a list of PCR. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPMS_PCR_SELECT { + /// The bit map of selected PCR + pub pcrSelect: Vec, +} + +impl TPMS_PCR_SELECT { + /// Creates a new instance with the specified values + pub fn new( + pcrSelect: &Vec, + ) -> Self { + Self { + pcrSelect: pcrSelect.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPMS_PCR_SELECT { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.pcrSelect, 1); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.pcrSelect = buf.readSizedByteBuf(1); + Ok(()) + } + +} + +impl TpmMarshaller for TPMS_PCR_SELECT { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// Table 94 Definition of TPMS_PCR_SELECTION Structure +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPMS_PCR_SELECTION { + /// The hash algorithm associated with the selection + #[derivative(Default(value="TPM_ALG_ID::NULL"))] + pub hash: TPM_ALG_ID, + + /// The bit map of selected PCR + pub pcrSelect: Vec, +} + +impl TPMS_PCR_SELECTION { + /// Creates a new instance with the specified values + pub fn new( + hash: TPM_ALG_ID, + pcrSelect: &Vec, + ) -> Self { + Self { + hash: hash.clone(), + pcrSelect: pcrSelect.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPMS_PCR_SELECTION { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeShort(self.hash.into()); + buf.writeSizedByteBuf(&self.pcrSelect, 1); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.hash = TPM_ALG_ID(buf.readShort() as u16); + self.pcrSelect = buf.readSizedByteBuf(1); + Ok(()) + } + +} + +impl TpmMarshaller for TPMS_PCR_SELECTION { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// This ticket is produced by TPM2_Create() or TPM2_CreatePrimary(). It is used to bind +/// the creation data to the object to which it applies. The ticket is computed by +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPMT_TK_CREATION { + /// The hierarchy containing name + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub hierarchy: TPM_HANDLE, + + /// This shall be the HMAC produced using a proof value of hierarchy. + pub digest: Vec, +} + +impl TPMT_TK_CREATION { + /// Creates a new instance with the specified values + pub fn new( + hierarchy: &TPM_HANDLE, + digest: &Vec, + ) -> Self { + Self { + hierarchy: hierarchy.clone(), + digest: digest.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPMT_TK_CREATION { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeShort(TPM_ST::CREATION.into()); + self.hierarchy.toTpm(buf)?; + buf.writeSizedByteBuf(&self.digest, 2); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + buf.readShort(); + self.hierarchy.initFromTpm(buf)?; + self.digest = buf.readSizedByteBuf(2); + Ok(()) + } + +} + +impl TpmMarshaller for TPMT_TK_CREATION { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// This ticket is produced by TPM2_VerifySignature(). This formulation is used for +/// multiple ticket uses. The ticket provides evidence that the TPM has validated that a +/// digest was signed by a key with the Name of keyName. The ticket is computed by +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPMT_TK_VERIFIED { + /// The hierarchy containing keyName + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub hierarchy: TPM_HANDLE, + + /// This shall be the HMAC produced using a proof value of hierarchy. + pub digest: Vec, +} + +impl TPMT_TK_VERIFIED { + /// Creates a new instance with the specified values + pub fn new( + hierarchy: &TPM_HANDLE, + digest: &Vec, + ) -> Self { + Self { + hierarchy: hierarchy.clone(), + digest: digest.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPMT_TK_VERIFIED { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeShort(TPM_ST::VERIFIED.into()); + self.hierarchy.toTpm(buf)?; + buf.writeSizedByteBuf(&self.digest, 2); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + buf.readShort(); + self.hierarchy.initFromTpm(buf)?; + self.digest = buf.readSizedByteBuf(2); + Ok(()) + } + +} + +impl TpmMarshaller for TPMT_TK_VERIFIED { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// This ticket is produced by TPM2_PolicySigned() and TPM2_PolicySecret() when the +/// authorization has an expiration time. If nonceTPM was provided in the policy command, +/// the ticket is computed by +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPMT_TK_AUTH { + /// Ticket structure tag + pub tag: TPM_ST, + + /// The hierarchy of the object used to produce the ticket + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub hierarchy: TPM_HANDLE, + + /// This shall be the HMAC produced using a proof value of hierarchy. + pub digest: Vec, +} + +impl TPMT_TK_AUTH { + /// Creates a new instance with the specified values + pub fn new( + tag: TPM_ST, + hierarchy: &TPM_HANDLE, + digest: &Vec, + ) -> Self { + Self { + tag: tag.clone(), + hierarchy: hierarchy.clone(), + digest: digest.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPMT_TK_AUTH { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeShort(self.tag.into()); + self.hierarchy.toTpm(buf)?; + buf.writeSizedByteBuf(&self.digest, 2); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.tag = TPM_ST(buf.readShort() as u16); + self.hierarchy.initFromTpm(buf)?; + self.digest = buf.readSizedByteBuf(2); + Ok(()) + } + +} + +impl TpmMarshaller for TPMT_TK_AUTH { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// This ticket is produced by TPM2_SequenceComplete() or TPM2_Hash() when the message +/// that was digested did not start with TPM_GENERATED_VALUE. The ticket is computed by +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPMT_TK_HASHCHECK { + /// The hierarchy + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub hierarchy: TPM_HANDLE, + + /// This shall be the HMAC produced using a proof value of hierarchy. + pub digest: Vec, +} + +impl TPMT_TK_HASHCHECK { + /// Creates a new instance with the specified values + pub fn new( + hierarchy: &TPM_HANDLE, + digest: &Vec, + ) -> Self { + Self { + hierarchy: hierarchy.clone(), + digest: digest.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPMT_TK_HASHCHECK { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeShort(TPM_ST::HASHCHECK.into()); + self.hierarchy.toTpm(buf)?; + buf.writeSizedByteBuf(&self.digest, 2); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + buf.readShort(); + self.hierarchy.initFromTpm(buf)?; + self.digest = buf.readSizedByteBuf(2); + Ok(()) + } + +} + +impl TpmMarshaller for TPMT_TK_HASHCHECK { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// This structure is used to report the properties of an algorithm identifier. It is +/// returned in response to a TPM2_GetCapability() with capability = TPM_CAP_ALG. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPMS_ALG_PROPERTY { + /// An algorithm identifier + #[derivative(Default(value="TPM_ALG_ID::NULL"))] + pub alg: TPM_ALG_ID, + + /// The attributes of the algorithm + pub algProperties: TPMA_ALGORITHM, +} + +impl TPMS_ALG_PROPERTY { + /// Creates a new instance with the specified values + pub fn new( + alg: TPM_ALG_ID, + algProperties: TPMA_ALGORITHM, + ) -> Self { + Self { + alg: alg.clone(), + algProperties: algProperties.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPMS_ALG_PROPERTY { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeShort(self.alg.into()); + buf.writeInt(self.algProperties.into()); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.alg = TPM_ALG_ID(buf.readShort() as u16); + self.algProperties = TPMA_ALGORITHM(buf.readInt() as u32); + Ok(()) + } + +} + +impl TpmMarshaller for TPMS_ALG_PROPERTY { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// This structure is used to report the properties that are UINT32 values. It is returned +/// in response to a TPM2_GetCapability(). +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPMS_TAGGED_PROPERTY { + /// A property identifier + pub property: TPM_PT, + + /// The value of the property + pub value: u32, +} + +impl TPMS_TAGGED_PROPERTY { + /// Creates a new instance with the specified values + pub fn new( + property: TPM_PT, + value: u32, + ) -> Self { + Self { + property: property.clone(), + value: value.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPMS_TAGGED_PROPERTY { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeInt(self.property.into()); + buf.writeInt(self.value as u32); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.property = TPM_PT(buf.readInt() as u32); + self.value = buf.readInt() as u32; + Ok(()) + } + +} + +impl TpmMarshaller for TPMS_TAGGED_PROPERTY { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// This structure is used in TPM2_GetCapability() to return the attributes of the PCR. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPMS_TAGGED_PCR_SELECT { + /// The property identifier + pub tag: TPM_PT_PCR, + + /// The bit map of PCR with the identified property + pub pcrSelect: Vec, +} + +impl TPMS_TAGGED_PCR_SELECT { + /// Creates a new instance with the specified values + pub fn new( + tag: TPM_PT_PCR, + pcrSelect: &Vec, + ) -> Self { + Self { + tag: tag.clone(), + pcrSelect: pcrSelect.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPMS_TAGGED_PCR_SELECT { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeInt(self.tag.into()); + buf.writeSizedByteBuf(&self.pcrSelect, 1); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.tag = TPM_PT_PCR(buf.readInt() as u32); + self.pcrSelect = buf.readSizedByteBuf(1); + Ok(()) + } + +} + +impl TpmMarshaller for TPMS_TAGGED_PCR_SELECT { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// This structure is used in TPM2_GetCapability() to return the policy associated with a +/// permanent handle. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPMS_TAGGED_POLICY { + /// A permanent handle + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub handle: TPM_HANDLE, + + /// The policy algorithm and hash + pub policyHash: TPMT_HA, +} + +impl TPMS_TAGGED_POLICY { + /// Creates a new instance with the specified values + pub fn new( + handle: &TPM_HANDLE, + policyHash: &TPMT_HA, + ) -> Self { + Self { + handle: handle.clone(), + policyHash: policyHash.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPMS_TAGGED_POLICY { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + self.handle.toTpm(buf)?; + self.policyHash.toTpm(buf)?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.handle.initFromTpm(buf)?; + self.policyHash.initFromTpm(buf)?; + Ok(()) + } + +} + +impl TpmMarshaller for TPMS_TAGGED_POLICY { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// This structure is used in TPM2_GetCapability() to return the ACT data. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPMS_ACT_DATA { + /// A permanent handle + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub handle: TPM_HANDLE, + + /// The current timeout of the ACT + pub timeout: u32, + + /// The state of the ACT + pub attributes: TPMA_ACT, +} + +impl TPMS_ACT_DATA { + /// Creates a new instance with the specified values + pub fn new( + handle: &TPM_HANDLE, + timeout: u32, + attributes: TPMA_ACT, + ) -> Self { + Self { + handle: handle.clone(), + timeout: timeout.clone(), + attributes: attributes.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPMS_ACT_DATA { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + self.handle.toTpm(buf)?; + buf.writeInt(self.timeout as u32); + buf.writeInt(self.attributes.into()); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.handle.initFromTpm(buf)?; + self.timeout = buf.readInt() as u32; + self.attributes = TPMA_ACT(buf.readInt() as u32); + Ok(()) + } + +} + +impl TpmMarshaller for TPMS_ACT_DATA { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// A list of command codes may be input to the TPM or returned by the TPM depending on +/// the command. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPML_CC { + /// A list of command codes + /// The maximum only applies to a command code list in a command. The response size is + /// limited only by the size of the parameter buffer. + pub commandCodes: Vec, +} + +impl TPML_CC { + /// Creates a new instance with the specified values + pub fn new( + commandCodes: &Vec, + ) -> Self { + Self { + commandCodes: commandCodes.clone(), + ..Default::default() + } + } + + fn GetUnionSelector() -> TPM_CAP { + TPM_CAP::PP_COMMANDS + } +} + +impl TpmStructure for TPML_CC { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeValArr(self.commandCodes.as_ref(), 4); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + buf.readValArr(self.commandCodes.as_mut(), 4)?; + Ok(()) + } + +} + +impl TpmMarshaller for TPML_CC { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// This list is only used in TPM2_GetCapability(capability = TPM_CAP_COMMANDS). +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPML_CCA { + /// A list of command codes attributes + pub commandAttributes: Vec, +} + +impl TPML_CCA { + /// Creates a new instance with the specified values + pub fn new( + commandAttributes: &Vec, + ) -> Self { + Self { + commandAttributes: commandAttributes.clone(), + ..Default::default() + } + } + + fn GetUnionSelector() -> TPM_CAP { + TPM_CAP::COMMANDS + } +} + +impl TpmStructure for TPML_CCA { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeValArr(self.commandAttributes.as_ref(), 4); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + buf.readValArr(self.commandAttributes.as_mut(), 4)?; + Ok(()) + } + +} + +impl TpmMarshaller for TPML_CCA { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// This list is returned by TPM2_IncrementalSelfTest(). +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPML_ALG { + /// A list of algorithm IDs + /// The maximum only applies to an algorithm list in a command. The response size is + /// limited only by the size of the parameter buffer. + pub algorithms: Vec, +} + +impl TPML_ALG { + /// Creates a new instance with the specified values + pub fn new( + algorithms: &Vec, + ) -> Self { + Self { + algorithms: algorithms.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPML_ALG { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeValArr(self.algorithms.as_ref(), 2); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + buf.readValArr(self.algorithms.as_mut(), 2)?; + Ok(()) + } + +} + +impl TpmMarshaller for TPML_ALG { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// This structure is used when the TPM returns a list of loaded handles when the +/// capability in TPM2_GetCapability() is TPM_CAP_HANDLE. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPML_HANDLE { + /// An array of handles + pub handle: Vec, +} + +impl TPML_HANDLE { + /// Creates a new instance with the specified values + pub fn new( + handle: &Vec, + ) -> Self { + Self { + handle: handle.clone(), + ..Default::default() + } + } + + fn GetUnionSelector() -> TPM_CAP { + TPM_CAP::HANDLES + } +} + +impl TpmStructure for TPML_HANDLE { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeObjArr(self.handle.as_ref())?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + buf.readObjArr(self.handle.as_mut())?; + Ok(()) + } + +} + +impl TpmMarshaller for TPML_HANDLE { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// This list is used to convey a list of digest values. This type is used in +/// TPM2_PolicyOR() and in TPM2_PCR_Read(). +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPML_DIGEST { + /// A list of digests + /// For TPM2_PolicyOR(), all digests will have been computed using the digest of the + /// policy session. For TPM2_PCR_Read(), each digest will be the size of the digest for + /// the bank containing the PCR. + pub digests: Vec, +} + +impl TPML_DIGEST { + /// Creates a new instance with the specified values + pub fn new( + digests: &Vec, + ) -> Self { + Self { + digests: digests.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPML_DIGEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeObjArr(self.digests.as_ref())?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + buf.readObjArr(self.digests.as_mut())?; + Ok(()) + } + +} + +impl TpmMarshaller for TPML_DIGEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// This list is used to convey a list of digest values. This type is returned by +/// TPM2_PCR_Event() and TPM2_EventSequenceComplete() and is an input for TPM2_PCR_Extend(). +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPML_DIGEST_VALUES { + /// A list of tagged digests + pub digests: Vec, +} + +impl TPML_DIGEST_VALUES { + /// Creates a new instance with the specified values + pub fn new( + digests: &Vec, + ) -> Self { + Self { + digests: digests.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPML_DIGEST_VALUES { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeObjArr(self.digests.as_ref())?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + buf.readObjArr(self.digests.as_mut())?; + Ok(()) + } + +} + +impl TpmMarshaller for TPML_DIGEST_VALUES { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// This list is used to indicate the PCR that are included in a selection when more than +/// one PCR value may be selected. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPML_PCR_SELECTION { + /// List of selections + pub pcrSelections: Vec, +} + +impl TPML_PCR_SELECTION { + /// Creates a new instance with the specified values + pub fn new( + pcrSelections: &Vec, + ) -> Self { + Self { + pcrSelections: pcrSelections.clone(), + ..Default::default() + } + } + + fn GetUnionSelector() -> TPM_CAP { + TPM_CAP::PCRS + } +} + +impl TpmStructure for TPML_PCR_SELECTION { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeObjArr(self.pcrSelections.as_ref())?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + buf.readObjArr(self.pcrSelections.as_mut())?; + Ok(()) + } + +} + +impl TpmMarshaller for TPML_PCR_SELECTION { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// This list is used to report on a list of algorithm attributes. It is returned in a +/// TPM2_GetCapability(). +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPML_ALG_PROPERTY { + /// List of properties + pub algProperties: Vec, +} + +impl TPML_ALG_PROPERTY { + /// Creates a new instance with the specified values + pub fn new( + algProperties: &Vec, + ) -> Self { + Self { + algProperties: algProperties.clone(), + ..Default::default() + } + } + + fn GetUnionSelector() -> TPM_CAP { + TPM_CAP::ALGS + } +} + +impl TpmStructure for TPML_ALG_PROPERTY { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeObjArr(self.algProperties.as_ref())?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + buf.readObjArr(self.algProperties.as_mut())?; + Ok(()) + } + +} + +impl TpmMarshaller for TPML_ALG_PROPERTY { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// This list is used to report on a list of properties that are TPMS_TAGGED_PROPERTY +/// values. It is returned by a TPM2_GetCapability(). +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPML_TAGGED_TPM_PROPERTY { + /// An array of tagged properties + pub tpmProperty: Vec, +} + +impl TPML_TAGGED_TPM_PROPERTY { + /// Creates a new instance with the specified values + pub fn new( + tpmProperty: &Vec, + ) -> Self { + Self { + tpmProperty: tpmProperty.clone(), + ..Default::default() + } + } + + fn GetUnionSelector() -> TPM_CAP { + TPM_CAP::TPM_PROPERTIES + } +} + +impl TpmStructure for TPML_TAGGED_TPM_PROPERTY { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeObjArr(self.tpmProperty.as_ref())?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + buf.readObjArr(self.tpmProperty.as_mut())?; + Ok(()) + } + +} + +impl TpmMarshaller for TPML_TAGGED_TPM_PROPERTY { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// This list is used to report on a list of properties that are TPMS_PCR_SELECT values. +/// It is returned by a TPM2_GetCapability(). +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPML_TAGGED_PCR_PROPERTY { + /// A tagged PCR selection + pub pcrProperty: Vec, +} + +impl TPML_TAGGED_PCR_PROPERTY { + /// Creates a new instance with the specified values + pub fn new( + pcrProperty: &Vec, + ) -> Self { + Self { + pcrProperty: pcrProperty.clone(), + ..Default::default() + } + } + + fn GetUnionSelector() -> TPM_CAP { + TPM_CAP::PCR_PROPERTIES + } +} + +impl TpmStructure for TPML_TAGGED_PCR_PROPERTY { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeObjArr(self.pcrProperty.as_ref())?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + buf.readObjArr(self.pcrProperty.as_mut())?; + Ok(()) + } + +} + +impl TpmMarshaller for TPML_TAGGED_PCR_PROPERTY { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// This list is used to report the ECC curve ID values supported by the TPM. It is +/// returned by a TPM2_GetCapability(). +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPML_ECC_CURVE { + /// Array of ECC curve identifiers + pub eccCurves: Vec, +} + +impl TPML_ECC_CURVE { + /// Creates a new instance with the specified values + pub fn new( + eccCurves: &Vec, + ) -> Self { + Self { + eccCurves: eccCurves.clone(), + ..Default::default() + } + } + + fn GetUnionSelector() -> TPM_CAP { + TPM_CAP::ECC_CURVES + } +} + +impl TpmStructure for TPML_ECC_CURVE { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeValArr(self.eccCurves.as_ref(), 2); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + buf.readValArr(self.eccCurves.as_mut(), 2)?; + Ok(()) + } + +} + +impl TpmMarshaller for TPML_ECC_CURVE { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// This list is used to report the authorization policy values for permanent handles. +/// This is list may be generated by TPM2_GetCapabiltiy(). A permanent handle that cannot +/// have a policy is not included in the list. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPML_TAGGED_POLICY { + /// Array of tagged policies + pub policies: Vec, +} + +impl TPML_TAGGED_POLICY { + /// Creates a new instance with the specified values + pub fn new( + policies: &Vec, + ) -> Self { + Self { + policies: policies.clone(), + ..Default::default() + } + } + + fn GetUnionSelector() -> TPM_CAP { + TPM_CAP::AUTH_POLICIES + } +} + +impl TpmStructure for TPML_TAGGED_POLICY { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeObjArr(self.policies.as_ref())?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + buf.readObjArr(self.policies.as_mut())?; + Ok(()) + } + +} + +impl TpmMarshaller for TPML_TAGGED_POLICY { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// This list is used to report the timeout and state for the ACT. This list may be +/// generated by TPM2_GetCapabilty(). Only implemented ACT are present in the list +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPML_ACT_DATA { + /// Array of ACT data + pub actData: Vec, +} + +impl TPML_ACT_DATA { + /// Creates a new instance with the specified values + pub fn new( + actData: &Vec, + ) -> Self { + Self { + actData: actData.clone(), + ..Default::default() + } + } + + fn GetUnionSelector() -> TPM_CAP { + TPM_CAP::ACT + } +} + +impl TpmStructure for TPML_ACT_DATA { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeObjArr(self.actData.as_ref())?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + buf.readObjArr(self.actData.as_mut())?; + Ok(()) + } + +} + +impl TpmMarshaller for TPML_ACT_DATA { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// This data area is returned in response to a TPM2_GetCapability(). +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPMS_CAPABILITY_DATA { + /// The capability + + /// The capability data + /// One of: TPML_ALG_PROPERTY, TPML_HANDLE, TPML_CCA, TPML_CC, TPML_PCR_SELECTION, + /// TPML_TAGGED_TPM_PROPERTY, TPML_TAGGED_PCR_PROPERTY, TPML_ECC_CURVE, + /// TPML_TAGGED_POLICY, TPML_ACT_DATA. + pub data: Option, +} + +impl TPMS_CAPABILITY_DATA { + /// Creates a new instance with the specified values + pub fn new( + data: &Option, + ) -> Self { + Self { + data: data.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPMS_CAPABILITY_DATA { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + if (self.data.is_none()) { return Ok(()) }; + buf.writeInt(self.data.as_ref().unwrap().GetUnionSelector().into()); + self.data.as_ref().unwrap().toTpm(buf)?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + let r#capability: TPM_CAP = TPM_CAP(buf.readInt() as u32); + self.data = TPMU_CAPABILITIES::create(r#capability)?; + self.data.as_mut().unwrap().initFromTpm(buf)?; + Ok(()) + } + +} + +impl TpmMarshaller for TPMS_CAPABILITY_DATA { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// This structure is used in each of the attestation commands. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPMS_CLOCK_INFO { + /// Time value in milliseconds that advances while the TPM is powered + /// NOTE The interpretation of the time-origin (clock=0) is out of the scope of this + /// specification, although Coordinated Universal Time (UTC) is expected to be a common + /// convention. This structure element is used to report on the TPM's Clock value. + /// This value is reset to zero when the Storage Primary Seed is changed (TPM2_Clear()). + /// This value may be advanced by TPM2_ClockSet(). + pub clock: u64, + + /// Number of occurrences of TPM Reset since the last TPM2_Clear() + pub resetCount: u32, + + /// Number of times that TPM2_Shutdown() or _TPM_Hash_Start have occurred since the last + /// TPM Reset or TPM2_Clear(). + pub restartCount: u32, + + /// No value of Clock greater than the current value of Clock has been previously reported + /// by the TPM. Set to YES on TPM2_Clear(). + pub safe: u8, +} + +impl TPMS_CLOCK_INFO { + /// Creates a new instance with the specified values + pub fn new( + clock: u64, + resetCount: u32, + restartCount: u32, + safe: u8, + ) -> Self { + Self { + clock: clock.clone(), + resetCount: resetCount.clone(), + restartCount: restartCount.clone(), + safe: safe.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPMS_CLOCK_INFO { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeInt64(self.clock as u64); + buf.writeInt(self.resetCount as u32); + buf.writeInt(self.restartCount as u32); + buf.writeByte(self.safe as u8); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.clock = buf.readInt64() as u64; + self.resetCount = buf.readInt() as u32; + self.restartCount = buf.readInt() as u32; + self.safe = buf.readByte() as u8; + Ok(()) + } + +} + +impl TpmMarshaller for TPMS_CLOCK_INFO { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// This structure is used in, e.g., the TPM2_GetTime() attestation and TPM2_ReadClock(). +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPMS_TIME_INFO { + /// Time in milliseconds since the TIme circuit was last reset + /// This structure element is used to report on the TPM's Time value. + pub time: u64, + + /// A structure containing the clock information + pub clockInfo: TPMS_CLOCK_INFO, +} + +impl TPMS_TIME_INFO { + /// Creates a new instance with the specified values + pub fn new( + time: u64, + clockInfo: &TPMS_CLOCK_INFO, + ) -> Self { + Self { + time: time.clone(), + clockInfo: clockInfo.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPMS_TIME_INFO { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeInt64(self.time as u64); + self.clockInfo.toTpm(buf)?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.time = buf.readInt64() as u64; + self.clockInfo.initFromTpm(buf)?; + Ok(()) + } + +} + +impl TpmMarshaller for TPMS_TIME_INFO { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// This structure is used when the TPM performs TPM2_GetTime. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPMS_TIME_ATTEST_INFO { + /// The Time, Clock, resetCount, restartCount, and Safe indicator + pub time: TPMS_TIME_INFO, + + /// A TPM vendor-specific value indicating the version number of the firmware + pub firmwareVersion: u64, +} + +impl TPMS_TIME_ATTEST_INFO { + /// Creates a new instance with the specified values + pub fn new( + time: &TPMS_TIME_INFO, + firmwareVersion: u64, + ) -> Self { + Self { + time: time.clone(), + firmwareVersion: firmwareVersion.clone(), + ..Default::default() + } + } + + fn GetUnionSelector() -> TPM_ST { + TPM_ST::ATTEST_TIME + } +} + +impl TpmStructure for TPMS_TIME_ATTEST_INFO { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + self.time.toTpm(buf)?; + buf.writeInt64(self.firmwareVersion as u64); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.time.initFromTpm(buf)?; + self.firmwareVersion = buf.readInt64() as u64; + Ok(()) + } + +} + +impl TpmMarshaller for TPMS_TIME_ATTEST_INFO { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// This is the attested data for TPM2_Certify(). +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPMS_CERTIFY_INFO { + /// Name of the certified object + pub name: Vec, + + /// Qualified Name of the certified object + pub qualifiedName: Vec, +} + +impl TPMS_CERTIFY_INFO { + /// Creates a new instance with the specified values + pub fn new( + name: &Vec, + qualifiedName: &Vec, + ) -> Self { + Self { + name: name.clone(), + qualifiedName: qualifiedName.clone(), + ..Default::default() + } + } + + fn GetUnionSelector() -> TPM_ST { + TPM_ST::ATTEST_CERTIFY + } +} + +impl TpmStructure for TPMS_CERTIFY_INFO { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.name, 2); + buf.writeSizedByteBuf(&self.qualifiedName, 2); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.name = buf.readSizedByteBuf(2); + self.qualifiedName = buf.readSizedByteBuf(2); + Ok(()) + } + +} + +impl TpmMarshaller for TPMS_CERTIFY_INFO { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// This is the attested data for TPM2_Quote(). +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPMS_QUOTE_INFO { + /// Information on algID, PCR selected and digest + pub pcrSelect: Vec, + + /// Digest of the selected PCR using the hash of the signing key + pub pcrDigest: Vec, +} + +impl TPMS_QUOTE_INFO { + /// Creates a new instance with the specified values + pub fn new( + pcrSelect: &Vec, + pcrDigest: &Vec, + ) -> Self { + Self { + pcrSelect: pcrSelect.clone(), + pcrDigest: pcrDigest.clone(), + ..Default::default() + } + } + + fn GetUnionSelector() -> TPM_ST { + TPM_ST::ATTEST_QUOTE + } +} + +impl TpmStructure for TPMS_QUOTE_INFO { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeObjArr(self.pcrSelect.as_ref())?; + buf.writeSizedByteBuf(&self.pcrDigest, 2); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + buf.readObjArr(self.pcrSelect.as_mut())?; + self.pcrDigest = buf.readSizedByteBuf(2); + Ok(()) + } + +} + +impl TpmMarshaller for TPMS_QUOTE_INFO { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// This is the attested data for TPM2_GetCommandAuditDigest(). +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPMS_COMMAND_AUDIT_INFO { + /// The monotonic audit counter + pub auditCounter: u64, + + /// Hash algorithm used for the command audit + #[derivative(Default(value="TPM_ALG_ID::NULL"))] + pub digestAlg: TPM_ALG_ID, + + /// The current value of the audit digest + pub auditDigest: Vec, + + /// Digest of the command codes being audited using digestAlg + pub commandDigest: Vec, +} + +impl TPMS_COMMAND_AUDIT_INFO { + /// Creates a new instance with the specified values + pub fn new( + auditCounter: u64, + digestAlg: TPM_ALG_ID, + auditDigest: &Vec, + commandDigest: &Vec, + ) -> Self { + Self { + auditCounter: auditCounter.clone(), + digestAlg: digestAlg.clone(), + auditDigest: auditDigest.clone(), + commandDigest: commandDigest.clone(), + ..Default::default() + } + } + + fn GetUnionSelector() -> TPM_ST { + TPM_ST::ATTEST_COMMAND_AUDIT + } +} + +impl TpmStructure for TPMS_COMMAND_AUDIT_INFO { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeInt64(self.auditCounter as u64); + buf.writeShort(self.digestAlg.into()); + buf.writeSizedByteBuf(&self.auditDigest, 2); + buf.writeSizedByteBuf(&self.commandDigest, 2); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.auditCounter = buf.readInt64() as u64; + self.digestAlg = TPM_ALG_ID(buf.readShort() as u16); + self.auditDigest = buf.readSizedByteBuf(2); + self.commandDigest = buf.readSizedByteBuf(2); + Ok(()) + } + +} + +impl TpmMarshaller for TPMS_COMMAND_AUDIT_INFO { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// This is the attested data for TPM2_GetSessionAuditDigest(). +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPMS_SESSION_AUDIT_INFO { + /// Current exclusive status of the session + /// TRUE if all of the commands recorded in the sessionDigest were executed without any + /// intervening TPM command that did not use this audit session + pub exclusiveSession: u8, + + /// The current value of the session audit digest + pub sessionDigest: Vec, +} + +impl TPMS_SESSION_AUDIT_INFO { + /// Creates a new instance with the specified values + pub fn new( + exclusiveSession: u8, + sessionDigest: &Vec, + ) -> Self { + Self { + exclusiveSession: exclusiveSession.clone(), + sessionDigest: sessionDigest.clone(), + ..Default::default() + } + } + + fn GetUnionSelector() -> TPM_ST { + TPM_ST::ATTEST_SESSION_AUDIT + } +} + +impl TpmStructure for TPMS_SESSION_AUDIT_INFO { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeByte(self.exclusiveSession as u8); + buf.writeSizedByteBuf(&self.sessionDigest, 2); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.exclusiveSession = buf.readByte() as u8; + self.sessionDigest = buf.readSizedByteBuf(2); + Ok(()) + } + +} + +impl TpmMarshaller for TPMS_SESSION_AUDIT_INFO { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// This is the attested data for TPM2_CertifyCreation(). +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPMS_CREATION_INFO { + /// Name of the object + pub objectName: Vec, + + /// CreationHash + pub creationHash: Vec, +} + +impl TPMS_CREATION_INFO { + /// Creates a new instance with the specified values + pub fn new( + objectName: &Vec, + creationHash: &Vec, + ) -> Self { + Self { + objectName: objectName.clone(), + creationHash: creationHash.clone(), + ..Default::default() + } + } + + fn GetUnionSelector() -> TPM_ST { + TPM_ST::ATTEST_CREATION + } +} + +impl TpmStructure for TPMS_CREATION_INFO { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.objectName, 2); + buf.writeSizedByteBuf(&self.creationHash, 2); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.objectName = buf.readSizedByteBuf(2); + self.creationHash = buf.readSizedByteBuf(2); + Ok(()) + } + +} + +impl TpmMarshaller for TPMS_CREATION_INFO { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// This structure contains the Name and contents of the selected NV Index that is +/// certified by TPM2_NV_Certify(). +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPMS_NV_CERTIFY_INFO { + /// Name of the NV Index + pub indexName: Vec, + + /// The offset parameter of TPM2_NV_Certify() + pub offset: u16, + + /// Contents of the NV Index + pub nvContents: Vec, +} + +impl TPMS_NV_CERTIFY_INFO { + /// Creates a new instance with the specified values + pub fn new( + indexName: &Vec, + offset: u16, + nvContents: &Vec, + ) -> Self { + Self { + indexName: indexName.clone(), + offset: offset.clone(), + nvContents: nvContents.clone(), + ..Default::default() + } + } + + fn GetUnionSelector() -> TPM_ST { + TPM_ST::ATTEST_NV + } +} + +impl TpmStructure for TPMS_NV_CERTIFY_INFO { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.indexName, 2); + buf.writeShort(self.offset as u16); + buf.writeSizedByteBuf(&self.nvContents, 2); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.indexName = buf.readSizedByteBuf(2); + self.offset = buf.readShort() as u16; + self.nvContents = buf.readSizedByteBuf(2); + Ok(()) + } + +} + +impl TpmMarshaller for TPMS_NV_CERTIFY_INFO { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// This structure contains the Name and hash of the contents of the selected NV Index +/// that is certified by TPM2_NV_Certify(). The data is hashed using hash of the signing scheme. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPMS_NV_DIGEST_CERTIFY_INFO { + /// Name of the NV Index + pub indexName: Vec, + + /// Hash of the contents of the index + pub nvDigest: Vec, +} + +impl TPMS_NV_DIGEST_CERTIFY_INFO { + /// Creates a new instance with the specified values + pub fn new( + indexName: &Vec, + nvDigest: &Vec, + ) -> Self { + Self { + indexName: indexName.clone(), + nvDigest: nvDigest.clone(), + ..Default::default() + } + } + + fn GetUnionSelector() -> TPM_ST { + TPM_ST::ATTEST_NV_DIGEST + } +} + +impl TpmStructure for TPMS_NV_DIGEST_CERTIFY_INFO { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.indexName, 2); + buf.writeSizedByteBuf(&self.nvDigest, 2); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.indexName = buf.readSizedByteBuf(2); + self.nvDigest = buf.readSizedByteBuf(2); + Ok(()) + } + +} + +impl TpmMarshaller for TPMS_NV_DIGEST_CERTIFY_INFO { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// This structure is used on each TPM-generated signed structure. The signature is over +/// this structure. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPMS_ATTEST { + /// The indication that this structure was created by a TPM (always TPM_GENERATED_VALUE) + pub magic: TPM_GENERATED, + + /// Type of the attestation structure + + /// Qualified Name of the signing key + pub qualifiedSigner: Vec, + + /// External information supplied by caller + /// NOTE A TPM2B_DATA structure provides room for a digest and a method indicator to + /// indicate the components of the digest. The definition of this method indicator is + /// outside the scope of this specification. + pub extraData: Vec, + + /// Clock, resetCount, restartCount, and Safe + pub clockInfo: TPMS_CLOCK_INFO, + + /// TPM-vendor-specific value identifying the version number of the firmware + pub firmwareVersion: u64, + + /// The type-specific attestation information + /// One of: TPMS_CERTIFY_INFO, TPMS_CREATION_INFO, TPMS_QUOTE_INFO, + /// TPMS_COMMAND_AUDIT_INFO, TPMS_SESSION_AUDIT_INFO, TPMS_TIME_ATTEST_INFO, + /// TPMS_NV_CERTIFY_INFO, TPMS_NV_DIGEST_CERTIFY_INFO. + pub attested: Option, +} + +impl TPMS_ATTEST { + /// Creates a new instance with the specified values + pub fn new( + magic: TPM_GENERATED, + qualifiedSigner: &Vec, + extraData: &Vec, + clockInfo: &TPMS_CLOCK_INFO, + firmwareVersion: u64, + attested: &Option, + ) -> Self { + Self { + magic: magic.clone(), + qualifiedSigner: qualifiedSigner.clone(), + extraData: extraData.clone(), + clockInfo: clockInfo.clone(), + firmwareVersion: firmwareVersion.clone(), + attested: attested.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPMS_ATTEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeInt(self.magic.into()); + buf.writeShort(self.attested.as_ref().unwrap().GetUnionSelector().into()); + buf.writeSizedByteBuf(&self.qualifiedSigner, 2); + buf.writeSizedByteBuf(&self.extraData, 2); + self.clockInfo.toTpm(buf)?; + buf.writeInt64(self.firmwareVersion as u64); + self.attested.as_ref().unwrap().toTpm(buf)?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.magic = TPM_GENERATED(buf.readInt() as u32); + let r#type: TPM_ST = TPM_ST(buf.readShort() as u16); + self.qualifiedSigner = buf.readSizedByteBuf(2); + self.extraData = buf.readSizedByteBuf(2); + self.clockInfo.initFromTpm(buf)?; + self.firmwareVersion = buf.readInt64() as u64; + self.attested = TPMU_ATTEST::create(r#type)?; + self.attested.as_mut().unwrap().initFromTpm(buf)?; + Ok(()) + } + +} + +impl TpmMarshaller for TPMS_ATTEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// This sized buffer to contain the signed structure. The attestationData is the signed +/// portion of the structure. The size parameter is not signed. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2B_ATTEST { + /// The signed structure + pub attestationData: TPMS_ATTEST, +} + +impl TPM2B_ATTEST { + /// Creates a new instance with the specified values + pub fn new( + attestationData: &TPMS_ATTEST, + ) -> Self { + Self { + attestationData: attestationData.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2B_ATTEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedObj(&self.attestationData)?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + buf.readSizedObj(&mut self.attestationData)?; + Ok(()) + } + +} + +impl TpmMarshaller for TPM2B_ATTEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// This is the format used for each of the authorizations in the session area of a command. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPMS_AUTH_COMMAND { + /// The session handle + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub sessionHandle: TPM_HANDLE, + + /// The session nonce, may be the Empty Buffer + pub nonce: Vec, + + /// The session attributes + pub sessionAttributes: TPMA_SESSION, + + /// Either an HMAC, a password, or an EmptyAuth + pub hmac: Vec, +} + +impl TPMS_AUTH_COMMAND { + /// Creates a new instance with the specified values + pub fn new( + sessionHandle: &TPM_HANDLE, + nonce: &Vec, + sessionAttributes: TPMA_SESSION, + hmac: &Vec, + ) -> Self { + Self { + sessionHandle: sessionHandle.clone(), + nonce: nonce.clone(), + sessionAttributes: sessionAttributes.clone(), + hmac: hmac.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPMS_AUTH_COMMAND { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + self.sessionHandle.toTpm(buf)?; + buf.writeSizedByteBuf(&self.nonce, 2); + buf.writeByte(self.sessionAttributes.into()); + buf.writeSizedByteBuf(&self.hmac, 2); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.sessionHandle.initFromTpm(buf)?; + self.nonce = buf.readSizedByteBuf(2); + self.sessionAttributes = TPMA_SESSION(buf.readByte() as u8); + self.hmac = buf.readSizedByteBuf(2); + Ok(()) + } + +} + +impl TpmMarshaller for TPMS_AUTH_COMMAND { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// This is the format for each of the authorizations in the session area of the response. +/// If the TPM returns TPM_RC_SUCCESS, then the session area of the response contains the +/// same number of authorizations as the command and the authorizations are in the same order. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPMS_AUTH_RESPONSE { + /// The session nonce, may be the Empty Buffer + pub nonce: Vec, + + /// The session attributes + pub sessionAttributes: TPMA_SESSION, + + /// Either an HMAC or an EmptyAuth + pub hmac: Vec, +} + +impl TPMS_AUTH_RESPONSE { + /// Creates a new instance with the specified values + pub fn new( + nonce: &Vec, + sessionAttributes: TPMA_SESSION, + hmac: &Vec, + ) -> Self { + Self { + nonce: nonce.clone(), + sessionAttributes: sessionAttributes.clone(), + hmac: hmac.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPMS_AUTH_RESPONSE { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.nonce, 2); + buf.writeByte(self.sessionAttributes.into()); + buf.writeSizedByteBuf(&self.hmac, 2); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.nonce = buf.readSizedByteBuf(2); + self.sessionAttributes = TPMA_SESSION(buf.readByte() as u8); + self.hmac = buf.readSizedByteBuf(2); + Ok(()) + } + +} + +impl TpmMarshaller for TPMS_AUTH_RESPONSE { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// Custom data structure representing an empty element (i.e. the one with +/// no data to marshal) for selector algorithm TPM_ALG_TDES for the union TPMU_SYM_DETAILS +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPMS_TDES_SYM_DETAILS { +} + +impl TPMS_TDES_SYM_DETAILS { + fn GetUnionSelector() -> TPM_ALG_ID { + TPM_ALG_ID::TDES + } +} + +impl TpmStructure for TPMS_TDES_SYM_DETAILS { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + Ok(()) + } + +} + +impl TpmMarshaller for TPMS_TDES_SYM_DETAILS { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// Custom data structure representing an empty element (i.e. the one with +/// no data to marshal) for selector algorithm TPM_ALG_AES for the union TPMU_SYM_DETAILS +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPMS_AES_SYM_DETAILS { +} + +impl TPMS_AES_SYM_DETAILS { + fn GetUnionSelector() -> TPM_ALG_ID { + TPM_ALG_ID::AES + } +} + +impl TpmStructure for TPMS_AES_SYM_DETAILS { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + Ok(()) + } + +} + +impl TpmMarshaller for TPMS_AES_SYM_DETAILS { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// Custom data structure representing an empty element (i.e. the one with +/// no data to marshal) for selector algorithm TPM_ALG_SM4 for the union TPMU_SYM_DETAILS +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPMS_SM4_SYM_DETAILS { +} + +impl TPMS_SM4_SYM_DETAILS { + fn GetUnionSelector() -> TPM_ALG_ID { + TPM_ALG_ID::SM4 + } +} + +impl TpmStructure for TPMS_SM4_SYM_DETAILS { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + Ok(()) + } + +} + +impl TpmMarshaller for TPMS_SM4_SYM_DETAILS { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// Custom data structure representing an empty element (i.e. the one with +/// no data to marshal) for selector algorithm TPM_ALG_CAMELLIA for the union TPMU_SYM_DETAILS +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPMS_CAMELLIA_SYM_DETAILS { +} + +impl TPMS_CAMELLIA_SYM_DETAILS { + fn GetUnionSelector() -> TPM_ALG_ID { + TPM_ALG_ID::CAMELLIA + } +} + +impl TpmStructure for TPMS_CAMELLIA_SYM_DETAILS { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + Ok(()) + } + +} + +impl TpmMarshaller for TPMS_CAMELLIA_SYM_DETAILS { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// Custom data structure representing an empty element (i.e. the one with +/// no data to marshal) for selector algorithm TPM_ALG_ANY for the union TPMU_SYM_DETAILS +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPMS_ANY_SYM_DETAILS { +} + +impl TPMS_ANY_SYM_DETAILS { + fn GetUnionSelector() -> TPM_ALG_ID { + TPM_ALG_ID::ANY + } +} + +impl TpmStructure for TPMS_ANY_SYM_DETAILS { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + Ok(()) + } + +} + +impl TpmMarshaller for TPMS_ANY_SYM_DETAILS { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// Custom data structure representing an empty element (i.e. the one with +/// no data to marshal) for selector algorithm TPM_ALG_XOR for the union TPMU_SYM_DETAILS +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPMS_XOR_SYM_DETAILS { +} + +impl TPMS_XOR_SYM_DETAILS { + fn GetUnionSelector() -> TPM_ALG_ID { + TPM_ALG_ID::XOR + } +} + +impl TpmStructure for TPMS_XOR_SYM_DETAILS { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + Ok(()) + } + +} + +impl TpmMarshaller for TPMS_XOR_SYM_DETAILS { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// Custom data structure representing an empty element (i.e. the one with +/// no data to marshal) for selector algorithm TPM_ALG_NULL for the union TPMU_SYM_DETAILS +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPMS_NULL_SYM_DETAILS { +} + +impl TPMS_NULL_SYM_DETAILS { + fn GetUnionSelector() -> TPM_ALG_ID { + TPM_ALG_ID::NULL + } +} + +impl TpmStructure for TPMS_NULL_SYM_DETAILS { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + Ok(()) + } + +} + +impl TpmMarshaller for TPMS_NULL_SYM_DETAILS { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// The TPMT_SYM_DEF structure is used to select an algorithm to be used for parameter +/// encryption in those cases when different symmetric algorithms may be selected. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPMT_SYM_DEF { + /// Indicates a symmetric algorithm + #[derivative(Default(value="TPM_ALG_ID::NULL"))] + pub algorithm: TPM_ALG_ID, + + /// A supported key size + pub keyBits: u16, + + /// The mode for the key + #[derivative(Default(value="TPM_ALG_ID::NULL"))] + pub mode: TPM_ALG_ID, +} + +impl TPMT_SYM_DEF { + /// Creates a new instance with the specified values + pub fn new( + algorithm: TPM_ALG_ID, + keyBits: u16, + mode: TPM_ALG_ID, + ) -> Self { + Self { + algorithm: algorithm.clone(), + keyBits: keyBits.clone(), + mode: mode.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPMT_SYM_DEF { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeShort(self.algorithm.into()); + if (self.algorithm == TPM_ALG_ID::NULL) { return Ok(()) }; + buf.writeShort(self.keyBits as u16); + buf.writeShort(self.mode.into()); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.algorithm = TPM_ALG_ID(buf.readShort() as u16); + if (self.algorithm == TPM_ALG_ID::NULL) { return Ok(()) }; + self.keyBits = buf.readShort() as u16; + self.mode = TPM_ALG_ID(buf.readShort() as u16); + Ok(()) + } + +} + +impl TpmMarshaller for TPMT_SYM_DEF { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// This structure is used when different symmetric block cipher (not XOR) algorithms may +/// be selected. If the Object can be an ordinary parent (not a derivation parent), this +/// must be the first field in the Object's parameter (see 12.2.3.7) field. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPMT_SYM_DEF_OBJECT { + /// Selects a symmetric block cipher + /// When used in the parameter area of a parent object, this shall be a supported block + /// cipher and not TPM_ALG_NULL + #[derivative(Default(value="TPM_ALG_ID::NULL"))] + pub algorithm: TPM_ALG_ID, + + /// The key size + pub keyBits: u16, + + /// Default mode + /// When used in the parameter area of a parent object, this shall be TPM_ALG_CFB. + #[derivative(Default(value="TPM_ALG_ID::NULL"))] + pub mode: TPM_ALG_ID, +} + +impl TPMT_SYM_DEF_OBJECT { + /// Creates a new instance with the specified values + pub fn new( + algorithm: TPM_ALG_ID, + keyBits: u16, + mode: TPM_ALG_ID, + ) -> Self { + Self { + algorithm: algorithm.clone(), + keyBits: keyBits.clone(), + mode: mode.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPMT_SYM_DEF_OBJECT { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeShort(self.algorithm.into()); + if (self.algorithm == TPM_ALG_ID::NULL) { return Ok(()) }; + buf.writeShort(self.keyBits as u16); + buf.writeShort(self.mode.into()); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.algorithm = TPM_ALG_ID(buf.readShort() as u16); + if (self.algorithm == TPM_ALG_ID::NULL) { return Ok(()) }; + self.keyBits = buf.readShort() as u16; + self.mode = TPM_ALG_ID(buf.readShort() as u16); + Ok(()) + } + +} + +impl TpmMarshaller for TPMT_SYM_DEF_OBJECT { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// This structure is used to hold a symmetric key in the sensitive area of an asymmetric object. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2B_SYM_KEY { + /// The key + pub buffer: Vec, +} + +impl TPM2B_SYM_KEY { + /// Creates a new instance with the specified values + pub fn new( + buffer: &Vec, + ) -> Self { + Self { + buffer: buffer.clone(), + ..Default::default() + } + } + + fn GetUnionSelector() -> TPM_ALG_ID { + TPM_ALG_ID::SYMCIPHER + } +} + +impl TpmStructure for TPM2B_SYM_KEY { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.buffer, 2); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.buffer = buf.readSizedByteBuf(2); + Ok(()) + } + +} + +impl TpmMarshaller for TPM2B_SYM_KEY { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// This structure contains the parameters for a symmetric block cipher object. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPMS_SYMCIPHER_PARMS { + /// A symmetric block cipher + pub sym: TPMT_SYM_DEF_OBJECT, +} + +impl TPMS_SYMCIPHER_PARMS { + /// Creates a new instance with the specified values + pub fn new( + sym: &TPMT_SYM_DEF_OBJECT, + ) -> Self { + Self { + sym: sym.clone(), + ..Default::default() + } + } + + fn GetUnionSelector() -> TPM_ALG_ID { + TPM_ALG_ID::SYMCIPHER + } +} + +impl TpmStructure for TPMS_SYMCIPHER_PARMS { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + self.sym.toTpm(buf)?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.sym.initFromTpm(buf)?; + Ok(()) + } + +} + +impl TpmMarshaller for TPMS_SYMCIPHER_PARMS { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// This buffer holds a label or context value. For interoperability and backwards +/// compatibility, LABEL_MAX_BUFFER is the minimum of the largest digest on the device and +/// the largest ECC parameter (MAX_ECC_KEY_BYTES) but no more than 32 bytes. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2B_LABEL { + /// Symmetric data for a created object or the label and context for a derived object + pub buffer: Vec, +} + +impl TPM2B_LABEL { + /// Creates a new instance with the specified values + pub fn new( + buffer: &Vec, + ) -> Self { + Self { + buffer: buffer.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2B_LABEL { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.buffer, 2); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.buffer = buf.readSizedByteBuf(2); + Ok(()) + } + +} + +impl TpmMarshaller for TPM2B_LABEL { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// This structure contains the label and context fields for a derived object. These +/// values are used in the derivation KDF. The values in the unique field of inPublic area +/// template take precedence over the values in the inSensitive parameter. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPMS_DERIVE { + pub label: Vec, + pub context: Vec, +} + +impl TPMS_DERIVE { + /// Creates a new instance with the specified values + pub fn new( + label: &Vec, + context: &Vec, + ) -> Self { + Self { + label: label.clone(), + context: context.clone(), + ..Default::default() + } + } + + fn GetUnionSelector() -> TPM_ALG_ID { + TPM_ALG_ID::ANY2 + } +} + +impl TpmStructure for TPMS_DERIVE { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.label, 2); + buf.writeSizedByteBuf(&self.context, 2); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.label = buf.readSizedByteBuf(2); + self.context = buf.readSizedByteBuf(2); + Ok(()) + } + +} + +impl TpmMarshaller for TPMS_DERIVE { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// Table 147 Definition of TPM2B_DERIVE Structure +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2B_DERIVE { + /// Symmetric data for a created object or the label and context for a derived object + pub buffer: TPMS_DERIVE, +} + +impl TPM2B_DERIVE { + /// Creates a new instance with the specified values + pub fn new( + buffer: &TPMS_DERIVE, + ) -> Self { + Self { + buffer: buffer.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2B_DERIVE { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedObj(&self.buffer)?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + buf.readSizedObj(&mut self.buffer)?; + Ok(()) + } + +} + +impl TpmMarshaller for TPM2B_DERIVE { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// This buffer wraps the TPMU_SENSITIVE_CREATE structure. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2B_SENSITIVE_DATA { + /// Symmetric data for a created object or the label and context for a derived object + pub buffer: Vec, +} + +impl TPM2B_SENSITIVE_DATA { + /// Creates a new instance with the specified values + pub fn new( + buffer: &Vec, + ) -> Self { + Self { + buffer: buffer.clone(), + ..Default::default() + } + } + + fn GetUnionSelector() -> TPM_ALG_ID { + TPM_ALG_ID::KEYEDHASH + } +} + +impl TpmStructure for TPM2B_SENSITIVE_DATA { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.buffer, 2); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.buffer = buf.readSizedByteBuf(2); + Ok(()) + } + +} + +impl TpmMarshaller for TPM2B_SENSITIVE_DATA { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// This structure defines the values to be placed in the sensitive area of a created +/// object. This structure is only used within a TPM2B_SENSITIVE_CREATE structure. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPMS_SENSITIVE_CREATE { + /// The USER auth secret value + pub userAuth: Vec, + + /// Data to be sealed, a key, or derivation values + pub data: Vec, +} + +impl TPMS_SENSITIVE_CREATE { + /// Creates a new instance with the specified values + pub fn new( + userAuth: &Vec, + data: &Vec, + ) -> Self { + Self { + userAuth: userAuth.clone(), + data: data.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPMS_SENSITIVE_CREATE { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.userAuth, 2); + buf.writeSizedByteBuf(&self.data, 2); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.userAuth = buf.readSizedByteBuf(2); + self.data = buf.readSizedByteBuf(2); + Ok(()) + } + +} + +impl TpmMarshaller for TPMS_SENSITIVE_CREATE { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// This structure contains the sensitive creation data in a sized buffer. This structure +/// is defined so that both the userAuth and data values of the TPMS_SENSITIVE_CREATE may +/// be passed as a single parameter for parameter encryption purposes. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2B_SENSITIVE_CREATE { + /// Data to be sealed or a symmetric key value. + pub sensitive: TPMS_SENSITIVE_CREATE, +} + +impl TPM2B_SENSITIVE_CREATE { + /// Creates a new instance with the specified values + pub fn new( + sensitive: &TPMS_SENSITIVE_CREATE, + ) -> Self { + Self { + sensitive: sensitive.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2B_SENSITIVE_CREATE { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedObj(&self.sensitive)?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + buf.readSizedObj(&mut self.sensitive)?; + Ok(()) + } + +} + +impl TpmMarshaller for TPM2B_SENSITIVE_CREATE { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// This structure is the scheme data for schemes that only require a hash to complete +/// their definition. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPMS_SCHEME_HASH { + /// The hash algorithm used to digest the message + #[derivative(Default(value="TPM_ALG_ID::NULL"))] + pub hashAlg: TPM_ALG_ID, +} + +impl TPMS_SCHEME_HASH { + /// Creates a new instance with the specified values + pub fn new( + hashAlg: TPM_ALG_ID, + ) -> Self { + Self { + hashAlg: hashAlg.clone(), + ..Default::default() + } + } + + fn GetUnionSelector() -> TPM_ALG_ID { + TPM_ALG_ID::HMAC + } +} + +impl TpmStructure for TPMS_SCHEME_HASH { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeShort(self.hashAlg.into()); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.hashAlg = TPM_ALG_ID(buf.readShort() as u16); + Ok(()) + } + +} + +impl TpmMarshaller for TPMS_SCHEME_HASH { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// This definition is for split signing schemes that require a commit count. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPMS_SCHEME_ECDAA { + /// The hash algorithm used to digest the message + #[derivative(Default(value="TPM_ALG_ID::NULL"))] + pub hashAlg: TPM_ALG_ID, + + /// The counter value that is used between TPM2_Commit() and the sign operation + pub count: u16, +} + +impl TPMS_SCHEME_ECDAA { + /// Creates a new instance with the specified values + pub fn new( + hashAlg: TPM_ALG_ID, + count: u16, + ) -> Self { + Self { + hashAlg: hashAlg.clone(), + count: count.clone(), + ..Default::default() + } + } + + fn GetUnionSelector() -> TPM_ALG_ID { + TPM_ALG_ID::ECDAA + } +} + +impl TpmStructure for TPMS_SCHEME_ECDAA { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeShort(self.hashAlg.into()); + buf.writeShort(self.count as u16); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.hashAlg = TPM_ALG_ID(buf.readShort() as u16); + self.count = buf.readShort() as u16; + Ok(()) + } + +} + +impl TpmMarshaller for TPMS_SCHEME_ECDAA { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// Table 155 Definition of Types for HMAC_SIG_SCHEME +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPMS_SCHEME_HMAC { + /// The hash algorithm used to digest the message + #[derivative(Default(value="TPM_ALG_ID::NULL"))] + pub hashAlg: TPM_ALG_ID, +} + +impl TPMS_SCHEME_HMAC { + fn GetUnionSelector() -> TPM_ALG_ID { + TPM_ALG_ID::HMAC + } +} + +impl TpmStructure for TPMS_SCHEME_HMAC { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeShort(self.hashAlg.into()); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.hashAlg = TPM_ALG_ID(buf.readShort() as u16); + Ok(()) + } + +} + +impl TpmMarshaller for TPMS_SCHEME_HMAC { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// This structure is for the XOR encryption scheme. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPMS_SCHEME_XOR { + /// The hash algorithm used to digest the message + #[derivative(Default(value="TPM_ALG_ID::NULL"))] + pub hashAlg: TPM_ALG_ID, + + /// The key derivation function + #[derivative(Default(value="TPM_ALG_ID::NULL"))] + pub kdf: TPM_ALG_ID, +} + +impl TPMS_SCHEME_XOR { + /// Creates a new instance with the specified values + pub fn new( + hashAlg: TPM_ALG_ID, + kdf: TPM_ALG_ID, + ) -> Self { + Self { + hashAlg: hashAlg.clone(), + kdf: kdf.clone(), + ..Default::default() + } + } + + fn GetUnionSelector() -> TPM_ALG_ID { + TPM_ALG_ID::XOR + } +} + +impl TpmStructure for TPMS_SCHEME_XOR { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeShort(self.hashAlg.into()); + buf.writeShort(self.kdf.into()); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.hashAlg = TPM_ALG_ID(buf.readShort() as u16); + self.kdf = TPM_ALG_ID(buf.readShort() as u16); + Ok(()) + } + +} + +impl TpmMarshaller for TPMS_SCHEME_XOR { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// Custom data structure representing an empty element (i.e. the one with +/// no data to marshal) for selector algorithm TPM_ALG_NULL for the union TPMU_SCHEME_KEYEDHASH +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPMS_NULL_SCHEME_KEYEDHASH { +} + +impl TPMS_NULL_SCHEME_KEYEDHASH { + fn GetUnionSelector() -> TPM_ALG_ID { + TPM_ALG_ID::NULL + } +} + +impl TpmStructure for TPMS_NULL_SCHEME_KEYEDHASH { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + Ok(()) + } + +} + +impl TpmMarshaller for TPMS_NULL_SCHEME_KEYEDHASH { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// This structure is used for a hash signing object. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPMT_KEYEDHASH_SCHEME { + /// Selects the scheme + + /// The scheme parameters + /// One of: TPMS_SCHEME_HMAC, TPMS_SCHEME_XOR, TPMS_NULL_SCHEME_KEYEDHASH. + pub details: Option, +} + +impl TPMT_KEYEDHASH_SCHEME { + /// Creates a new instance with the specified values + pub fn new( + details: &Option, + ) -> Self { + Self { + details: details.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPMT_KEYEDHASH_SCHEME { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + if (self.details.is_none()) { return Ok(()) }; + buf.writeShort(self.details.as_ref().unwrap().GetUnionSelector().into()); + self.details.as_ref().unwrap().toTpm(buf)?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + let r#scheme: TPM_ALG_ID = TPM_ALG_ID(buf.readShort() as u16); + self.details = TPMU_SCHEME_KEYEDHASH::create(r#scheme)?; + self.details.as_mut().unwrap().initFromTpm(buf)?; + Ok(()) + } + +} + +impl TpmMarshaller for TPMT_KEYEDHASH_SCHEME { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// These are the RSA schemes that only need a hash algorithm as a scheme parameter. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPMS_SIG_SCHEME_RSASSA { + /// The hash algorithm used to digest the message + #[derivative(Default(value="TPM_ALG_ID::NULL"))] + pub hashAlg: TPM_ALG_ID, +} + +impl TPMS_SIG_SCHEME_RSASSA { + fn GetUnionSelector() -> TPM_ALG_ID { + TPM_ALG_ID::RSASSA + } +} + +impl TpmStructure for TPMS_SIG_SCHEME_RSASSA { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeShort(self.hashAlg.into()); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.hashAlg = TPM_ALG_ID(buf.readShort() as u16); + Ok(()) + } + +} + +impl TpmMarshaller for TPMS_SIG_SCHEME_RSASSA { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// These are the RSA schemes that only need a hash algorithm as a scheme parameter. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPMS_SIG_SCHEME_RSAPSS { + /// The hash algorithm used to digest the message + #[derivative(Default(value="TPM_ALG_ID::NULL"))] + pub hashAlg: TPM_ALG_ID, +} + +impl TPMS_SIG_SCHEME_RSAPSS { + fn GetUnionSelector() -> TPM_ALG_ID { + TPM_ALG_ID::RSAPSS + } +} + +impl TpmStructure for TPMS_SIG_SCHEME_RSAPSS { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeShort(self.hashAlg.into()); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.hashAlg = TPM_ALG_ID(buf.readShort() as u16); + Ok(()) + } + +} + +impl TpmMarshaller for TPMS_SIG_SCHEME_RSAPSS { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// Most of the ECC signature schemes only require a hash algorithm to complete the +/// definition and can be typed as TPMS_SCHEME_HASH. Anonymous algorithms also require a +/// count value so they are typed to be TPMS_SCHEME_ECDAA. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPMS_SIG_SCHEME_ECDSA { + /// The hash algorithm used to digest the message + #[derivative(Default(value="TPM_ALG_ID::NULL"))] + pub hashAlg: TPM_ALG_ID, +} + +impl TPMS_SIG_SCHEME_ECDSA { + fn GetUnionSelector() -> TPM_ALG_ID { + TPM_ALG_ID::ECDSA + } +} + +impl TpmStructure for TPMS_SIG_SCHEME_ECDSA { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeShort(self.hashAlg.into()); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.hashAlg = TPM_ALG_ID(buf.readShort() as u16); + Ok(()) + } + +} + +impl TpmMarshaller for TPMS_SIG_SCHEME_ECDSA { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// Most of the ECC signature schemes only require a hash algorithm to complete the +/// definition and can be typed as TPMS_SCHEME_HASH. Anonymous algorithms also require a +/// count value so they are typed to be TPMS_SCHEME_ECDAA. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPMS_SIG_SCHEME_SM2 { + /// The hash algorithm used to digest the message + #[derivative(Default(value="TPM_ALG_ID::NULL"))] + pub hashAlg: TPM_ALG_ID, +} + +impl TPMS_SIG_SCHEME_SM2 { + fn GetUnionSelector() -> TPM_ALG_ID { + TPM_ALG_ID::SM2 + } +} + +impl TpmStructure for TPMS_SIG_SCHEME_SM2 { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeShort(self.hashAlg.into()); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.hashAlg = TPM_ALG_ID(buf.readShort() as u16); + Ok(()) + } + +} + +impl TpmMarshaller for TPMS_SIG_SCHEME_SM2 { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// Most of the ECC signature schemes only require a hash algorithm to complete the +/// definition and can be typed as TPMS_SCHEME_HASH. Anonymous algorithms also require a +/// count value so they are typed to be TPMS_SCHEME_ECDAA. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPMS_SIG_SCHEME_ECSCHNORR { + /// The hash algorithm used to digest the message + #[derivative(Default(value="TPM_ALG_ID::NULL"))] + pub hashAlg: TPM_ALG_ID, +} + +impl TPMS_SIG_SCHEME_ECSCHNORR { + fn GetUnionSelector() -> TPM_ALG_ID { + TPM_ALG_ID::ECSCHNORR + } +} + +impl TpmStructure for TPMS_SIG_SCHEME_ECSCHNORR { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeShort(self.hashAlg.into()); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.hashAlg = TPM_ALG_ID(buf.readShort() as u16); + Ok(()) + } + +} + +impl TpmMarshaller for TPMS_SIG_SCHEME_ECSCHNORR { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// Most of the ECC signature schemes only require a hash algorithm to complete the +/// definition and can be typed as TPMS_SCHEME_HASH. Anonymous algorithms also require a +/// count value so they are typed to be TPMS_SCHEME_ECDAA. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPMS_SIG_SCHEME_ECDAA { + /// The hash algorithm used to digest the message + #[derivative(Default(value="TPM_ALG_ID::NULL"))] + pub hashAlg: TPM_ALG_ID, + + /// The counter value that is used between TPM2_Commit() and the sign operation + pub count: u16, +} + +impl TPMS_SIG_SCHEME_ECDAA { + fn GetUnionSelector() -> TPM_ALG_ID { + TPM_ALG_ID::ECDAA + } +} + +impl TpmStructure for TPMS_SIG_SCHEME_ECDAA { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeShort(self.hashAlg.into()); + buf.writeShort(self.count as u16); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.hashAlg = TPM_ALG_ID(buf.readShort() as u16); + self.count = buf.readShort() as u16; + Ok(()) + } + +} + +impl TpmMarshaller for TPMS_SIG_SCHEME_ECDAA { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// Custom data structure representing an empty element (i.e. the one with +/// no data to marshal) for selector algorithm TPM_ALG_NULL for the union TPMU_SIG_SCHEME +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPMS_NULL_SIG_SCHEME { +} + +impl TPMS_NULL_SIG_SCHEME { + fn GetUnionSelector() -> TPM_ALG_ID { + TPM_ALG_ID::NULL + } +} + +impl TpmStructure for TPMS_NULL_SIG_SCHEME { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + Ok(()) + } + +} + +impl TpmMarshaller for TPMS_NULL_SIG_SCHEME { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// Table 162 Definition of TPMT_SIG_SCHEME Structure +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPMT_SIG_SCHEME { + /// Scheme selector + + /// Scheme parameters + /// One of: TPMS_SIG_SCHEME_RSASSA, TPMS_SIG_SCHEME_RSAPSS, TPMS_SIG_SCHEME_ECDSA, + /// TPMS_SIG_SCHEME_ECDAA, TPMS_SIG_SCHEME_SM2, TPMS_SIG_SCHEME_ECSCHNORR, + /// TPMS_SCHEME_HMAC, TPMS_SCHEME_HASH, TPMS_NULL_SIG_SCHEME. + pub details: Option, +} + +impl TPMT_SIG_SCHEME { + /// Creates a new instance with the specified values + pub fn new( + details: &Option, + ) -> Self { + Self { + details: details.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPMT_SIG_SCHEME { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + if (self.details.is_none()) { return Ok(()) }; + buf.writeShort(self.details.as_ref().unwrap().GetUnionSelector().into()); + self.details.as_ref().unwrap().toTpm(buf)?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + let r#scheme: TPM_ALG_ID = TPM_ALG_ID(buf.readShort() as u16); + self.details = TPMU_SIG_SCHEME::create(r#scheme)?; + self.details.as_mut().unwrap().initFromTpm(buf)?; + Ok(()) + } + +} + +impl TpmMarshaller for TPMT_SIG_SCHEME { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// These are the RSA encryption schemes that only need a hash algorithm as a controlling parameter. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPMS_ENC_SCHEME_OAEP { + /// The hash algorithm used to digest the message + #[derivative(Default(value="TPM_ALG_ID::NULL"))] + pub hashAlg: TPM_ALG_ID, +} + +impl TPMS_ENC_SCHEME_OAEP { + fn GetUnionSelector() -> TPM_ALG_ID { + TPM_ALG_ID::OAEP + } +} + +impl TpmStructure for TPMS_ENC_SCHEME_OAEP { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeShort(self.hashAlg.into()); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.hashAlg = TPM_ALG_ID(buf.readShort() as u16); + Ok(()) + } + +} + +impl TpmMarshaller for TPMS_ENC_SCHEME_OAEP { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// These are the RSA encryption schemes that only need a hash algorithm as a controlling parameter. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPMS_ENC_SCHEME_RSAES { +} + +impl TPMS_ENC_SCHEME_RSAES { + fn GetUnionSelector() -> TPM_ALG_ID { + TPM_ALG_ID::RSAES + } +} + +impl TpmStructure for TPMS_ENC_SCHEME_RSAES { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + Ok(()) + } + +} + +impl TpmMarshaller for TPMS_ENC_SCHEME_RSAES { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// These are the ECC schemes that only need a hash algorithm as a controlling parameter. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPMS_KEY_SCHEME_ECDH { + /// The hash algorithm used to digest the message + #[derivative(Default(value="TPM_ALG_ID::NULL"))] + pub hashAlg: TPM_ALG_ID, +} + +impl TPMS_KEY_SCHEME_ECDH { + fn GetUnionSelector() -> TPM_ALG_ID { + TPM_ALG_ID::ECDH + } +} + +impl TpmStructure for TPMS_KEY_SCHEME_ECDH { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeShort(self.hashAlg.into()); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.hashAlg = TPM_ALG_ID(buf.readShort() as u16); + Ok(()) + } + +} + +impl TpmMarshaller for TPMS_KEY_SCHEME_ECDH { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// These are the ECC schemes that only need a hash algorithm as a controlling parameter. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPMS_KEY_SCHEME_ECMQV { + /// The hash algorithm used to digest the message + #[derivative(Default(value="TPM_ALG_ID::NULL"))] + pub hashAlg: TPM_ALG_ID, +} + +impl TPMS_KEY_SCHEME_ECMQV { + fn GetUnionSelector() -> TPM_ALG_ID { + TPM_ALG_ID::ECMQV + } +} + +impl TpmStructure for TPMS_KEY_SCHEME_ECMQV { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeShort(self.hashAlg.into()); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.hashAlg = TPM_ALG_ID(buf.readShort() as u16); + Ok(()) + } + +} + +impl TpmMarshaller for TPMS_KEY_SCHEME_ECMQV { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// These structures are used to define the key derivation for symmetric secret sharing +/// using asymmetric methods. A secret sharing scheme is required in any asymmetric key +/// with the decrypt attribute SET. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPMS_KDF_SCHEME_MGF1 { + /// The hash algorithm used to digest the message + #[derivative(Default(value="TPM_ALG_ID::NULL"))] + pub hashAlg: TPM_ALG_ID, +} + +impl TPMS_KDF_SCHEME_MGF1 { + fn GetUnionSelector() -> TPM_ALG_ID { + TPM_ALG_ID::MGF1 + } +} + +impl TpmStructure for TPMS_KDF_SCHEME_MGF1 { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeShort(self.hashAlg.into()); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.hashAlg = TPM_ALG_ID(buf.readShort() as u16); + Ok(()) + } + +} + +impl TpmMarshaller for TPMS_KDF_SCHEME_MGF1 { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// These structures are used to define the key derivation for symmetric secret sharing +/// using asymmetric methods. A secret sharing scheme is required in any asymmetric key +/// with the decrypt attribute SET. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPMS_KDF_SCHEME_KDF1_SP800_56A { + /// The hash algorithm used to digest the message + #[derivative(Default(value="TPM_ALG_ID::NULL"))] + pub hashAlg: TPM_ALG_ID, +} + +impl TPMS_KDF_SCHEME_KDF1_SP800_56A { + fn GetUnionSelector() -> TPM_ALG_ID { + TPM_ALG_ID::KDF1_SP800_56A + } +} + +impl TpmStructure for TPMS_KDF_SCHEME_KDF1_SP800_56A { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeShort(self.hashAlg.into()); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.hashAlg = TPM_ALG_ID(buf.readShort() as u16); + Ok(()) + } + +} + +impl TpmMarshaller for TPMS_KDF_SCHEME_KDF1_SP800_56A { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// These structures are used to define the key derivation for symmetric secret sharing +/// using asymmetric methods. A secret sharing scheme is required in any asymmetric key +/// with the decrypt attribute SET. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPMS_KDF_SCHEME_KDF2 { + /// The hash algorithm used to digest the message + #[derivative(Default(value="TPM_ALG_ID::NULL"))] + pub hashAlg: TPM_ALG_ID, +} + +impl TPMS_KDF_SCHEME_KDF2 { + fn GetUnionSelector() -> TPM_ALG_ID { + TPM_ALG_ID::KDF2 + } +} + +impl TpmStructure for TPMS_KDF_SCHEME_KDF2 { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeShort(self.hashAlg.into()); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.hashAlg = TPM_ALG_ID(buf.readShort() as u16); + Ok(()) + } + +} + +impl TpmMarshaller for TPMS_KDF_SCHEME_KDF2 { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// These structures are used to define the key derivation for symmetric secret sharing +/// using asymmetric methods. A secret sharing scheme is required in any asymmetric key +/// with the decrypt attribute SET. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPMS_KDF_SCHEME_KDF1_SP800_108 { + /// The hash algorithm used to digest the message + #[derivative(Default(value="TPM_ALG_ID::NULL"))] + pub hashAlg: TPM_ALG_ID, +} + +impl TPMS_KDF_SCHEME_KDF1_SP800_108 { + fn GetUnionSelector() -> TPM_ALG_ID { + TPM_ALG_ID::KDF1_SP800_108 + } +} + +impl TpmStructure for TPMS_KDF_SCHEME_KDF1_SP800_108 { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeShort(self.hashAlg.into()); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.hashAlg = TPM_ALG_ID(buf.readShort() as u16); + Ok(()) + } + +} + +impl TpmMarshaller for TPMS_KDF_SCHEME_KDF1_SP800_108 { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// Custom data structure representing an empty element (i.e. the one with +/// no data to marshal) for selector algorithm TPM_ALG_NULL for the union TPMU_KDF_SCHEME +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPMS_NULL_KDF_SCHEME { +} + +impl TPMS_NULL_KDF_SCHEME { + fn GetUnionSelector() -> TPM_ALG_ID { + TPM_ALG_ID::NULL + } +} + +impl TpmStructure for TPMS_NULL_KDF_SCHEME { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + Ok(()) + } + +} + +impl TpmMarshaller for TPMS_NULL_KDF_SCHEME { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// Table 167 Definition of TPMT_KDF_SCHEME Structure +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPMT_KDF_SCHEME { + /// Scheme selector + + /// Scheme parameters + /// One of: TPMS_KDF_SCHEME_MGF1, TPMS_KDF_SCHEME_KDF1_SP800_56A, TPMS_KDF_SCHEME_KDF2, + /// TPMS_KDF_SCHEME_KDF1_SP800_108, TPMS_SCHEME_HASH, TPMS_NULL_KDF_SCHEME. + pub details: Option, +} + +impl TPMT_KDF_SCHEME { + /// Creates a new instance with the specified values + pub fn new( + details: &Option, + ) -> Self { + Self { + details: details.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPMT_KDF_SCHEME { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + if (self.details.is_none()) { return Ok(()) }; + buf.writeShort(self.details.as_ref().unwrap().GetUnionSelector().into()); + self.details.as_ref().unwrap().toTpm(buf)?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + let r#scheme: TPM_ALG_ID = TPM_ALG_ID(buf.readShort() as u16); + self.details = TPMU_KDF_SCHEME::create(r#scheme)?; + self.details.as_mut().unwrap().initFromTpm(buf)?; + Ok(()) + } + +} + +impl TpmMarshaller for TPMT_KDF_SCHEME { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// Custom data structure representing an empty element (i.e. the one with +/// no data to marshal) for selector algorithm TPM_ALG_NULL for the union TPMU_ASYM_SCHEME +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPMS_NULL_ASYM_SCHEME { +} + +impl TPMS_NULL_ASYM_SCHEME { + fn GetUnionSelector() -> TPM_ALG_ID { + TPM_ALG_ID::NULL + } +} + +impl TpmStructure for TPMS_NULL_ASYM_SCHEME { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + Ok(()) + } + +} + +impl TpmMarshaller for TPMS_NULL_ASYM_SCHEME { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// This structure is defined to allow overlay of all of the schemes for any asymmetric +/// object. This structure is not sent on the interface. It is defined so that common +/// functions may operate on any similar scheme structure. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPMT_ASYM_SCHEME { + /// Scheme selector + + /// Scheme parameters + /// One of: TPMS_KEY_SCHEME_ECDH, TPMS_KEY_SCHEME_ECMQV, TPMS_SIG_SCHEME_RSASSA, + /// TPMS_SIG_SCHEME_RSAPSS, TPMS_SIG_SCHEME_ECDSA, TPMS_SIG_SCHEME_ECDAA, + /// TPMS_SIG_SCHEME_SM2, TPMS_SIG_SCHEME_ECSCHNORR, TPMS_ENC_SCHEME_RSAES, + /// TPMS_ENC_SCHEME_OAEP, TPMS_SCHEME_HASH, TPMS_NULL_ASYM_SCHEME. + pub details: Option, +} + +impl TPMT_ASYM_SCHEME { + /// Creates a new instance with the specified values + pub fn new( + details: &Option, + ) -> Self { + Self { + details: details.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPMT_ASYM_SCHEME { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + if (self.details.is_none()) { return Ok(()) }; + buf.writeShort(self.details.as_ref().unwrap().GetUnionSelector().into()); + self.details.as_ref().unwrap().toTpm(buf)?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + let r#scheme: TPM_ALG_ID = TPM_ALG_ID(buf.readShort() as u16); + self.details = TPMU_ASYM_SCHEME::create(r#scheme)?; + self.details.as_mut().unwrap().initFromTpm(buf)?; + Ok(()) + } + +} + +impl TpmMarshaller for TPMT_ASYM_SCHEME { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// Table 172 Definition of {RSA} TPMT_RSA_SCHEME Structure +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPMT_RSA_SCHEME { + /// Scheme selector + + /// Scheme parameters + /// One of: TPMS_KEY_SCHEME_ECDH, TPMS_KEY_SCHEME_ECMQV, TPMS_SIG_SCHEME_RSASSA, + /// TPMS_SIG_SCHEME_RSAPSS, TPMS_SIG_SCHEME_ECDSA, TPMS_SIG_SCHEME_ECDAA, + /// TPMS_SIG_SCHEME_SM2, TPMS_SIG_SCHEME_ECSCHNORR, TPMS_ENC_SCHEME_RSAES, + /// TPMS_ENC_SCHEME_OAEP, TPMS_SCHEME_HASH, TPMS_NULL_ASYM_SCHEME. + pub details: Option, +} + +impl TPMT_RSA_SCHEME { + /// Creates a new instance with the specified values + pub fn new( + details: &Option, + ) -> Self { + Self { + details: details.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPMT_RSA_SCHEME { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + if (self.details.is_none()) { return Ok(()) }; + buf.writeShort(self.details.as_ref().unwrap().GetUnionSelector().into()); + self.details.as_ref().unwrap().toTpm(buf)?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + let r#scheme: TPM_ALG_ID = TPM_ALG_ID(buf.readShort() as u16); + self.details = TPMU_ASYM_SCHEME::create(r#scheme)?; + self.details.as_mut().unwrap().initFromTpm(buf)?; + Ok(()) + } + +} + +impl TpmMarshaller for TPMT_RSA_SCHEME { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// Table 174 Definition of {RSA} TPMT_RSA_DECRYPT Structure +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPMT_RSA_DECRYPT { + /// Scheme selector + + /// Scheme parameters + /// One of: TPMS_KEY_SCHEME_ECDH, TPMS_KEY_SCHEME_ECMQV, TPMS_SIG_SCHEME_RSASSA, + /// TPMS_SIG_SCHEME_RSAPSS, TPMS_SIG_SCHEME_ECDSA, TPMS_SIG_SCHEME_ECDAA, + /// TPMS_SIG_SCHEME_SM2, TPMS_SIG_SCHEME_ECSCHNORR, TPMS_ENC_SCHEME_RSAES, + /// TPMS_ENC_SCHEME_OAEP, TPMS_SCHEME_HASH, TPMS_NULL_ASYM_SCHEME. + pub details: Option, +} + +impl TPMT_RSA_DECRYPT { + /// Creates a new instance with the specified values + pub fn new( + details: &Option, + ) -> Self { + Self { + details: details.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPMT_RSA_DECRYPT { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + if (self.details.is_none()) { return Ok(()) }; + buf.writeShort(self.details.as_ref().unwrap().GetUnionSelector().into()); + self.details.as_ref().unwrap().toTpm(buf)?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + let r#scheme: TPM_ALG_ID = TPM_ALG_ID(buf.readShort() as u16); + self.details = TPMU_ASYM_SCHEME::create(r#scheme)?; + self.details.as_mut().unwrap().initFromTpm(buf)?; + Ok(()) + } + +} + +impl TpmMarshaller for TPMT_RSA_DECRYPT { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// This sized buffer holds the largest RSA public key supported by the TPM. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2B_PUBLIC_KEY_RSA { + /// Value + pub buffer: Vec, +} + +impl TPM2B_PUBLIC_KEY_RSA { + /// Creates a new instance with the specified values + pub fn new( + buffer: &Vec, + ) -> Self { + Self { + buffer: buffer.clone(), + ..Default::default() + } + } + + fn GetUnionSelector() -> TPM_ALG_ID { + TPM_ALG_ID::RSA + } +} + +impl TpmStructure for TPM2B_PUBLIC_KEY_RSA { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.buffer, 2); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.buffer = buf.readSizedByteBuf(2); + Ok(()) + } + +} + +impl TpmMarshaller for TPM2B_PUBLIC_KEY_RSA { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// This sized buffer holds the largest RSA prime number supported by the TPM. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2B_PRIVATE_KEY_RSA { + pub buffer: Vec, +} + +impl TPM2B_PRIVATE_KEY_RSA { + /// Creates a new instance with the specified values + pub fn new( + buffer: &Vec, + ) -> Self { + Self { + buffer: buffer.clone(), + ..Default::default() + } + } + + fn GetUnionSelector() -> TPM_ALG_ID { + TPM_ALG_ID::RSA + } +} + +impl TpmStructure for TPM2B_PRIVATE_KEY_RSA { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.buffer, 2); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.buffer = buf.readSizedByteBuf(2); + Ok(()) + } + +} + +impl TpmMarshaller for TPM2B_PRIVATE_KEY_RSA { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// This sized buffer holds the largest ECC parameter (coordinate) supported by the TPM. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2B_ECC_PARAMETER { + /// The parameter data + pub buffer: Vec, +} + +impl TPM2B_ECC_PARAMETER { + /// Creates a new instance with the specified values + pub fn new( + buffer: &Vec, + ) -> Self { + Self { + buffer: buffer.clone(), + ..Default::default() + } + } + + fn GetUnionSelector() -> TPM_ALG_ID { + TPM_ALG_ID::ECC + } +} + +impl TpmStructure for TPM2B_ECC_PARAMETER { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.buffer, 2); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.buffer = buf.readSizedByteBuf(2); + Ok(()) + } + +} + +impl TpmMarshaller for TPM2B_ECC_PARAMETER { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// This structure holds two ECC coordinates that, together, make up an ECC point. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPMS_ECC_POINT { + /// X coordinate + pub x: Vec, + + /// Y coordinate + pub y: Vec, +} + +impl TPMS_ECC_POINT { + /// Creates a new instance with the specified values + pub fn new( + x: &Vec, + y: &Vec, + ) -> Self { + Self { + x: x.clone(), + y: y.clone(), + ..Default::default() + } + } + + fn GetUnionSelector() -> TPM_ALG_ID { + TPM_ALG_ID::ECC + } +} + +impl TpmStructure for TPMS_ECC_POINT { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.x, 2); + buf.writeSizedByteBuf(&self.y, 2); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.x = buf.readSizedByteBuf(2); + self.y = buf.readSizedByteBuf(2); + Ok(()) + } + +} + +impl TpmMarshaller for TPMS_ECC_POINT { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// This structure is defined to allow a point to be a single sized parameter so that it +/// may be encrypted. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2B_ECC_POINT { + /// Coordinates + pub point: TPMS_ECC_POINT, +} + +impl TPM2B_ECC_POINT { + /// Creates a new instance with the specified values + pub fn new( + point: &TPMS_ECC_POINT, + ) -> Self { + Self { + point: point.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2B_ECC_POINT { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedObj(&self.point)?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + buf.readSizedObj(&mut self.point)?; + Ok(()) + } + +} + +impl TpmMarshaller for TPM2B_ECC_POINT { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// Table 183 Definition of (TPMT_SIG_SCHEME) {ECC} TPMT_ECC_SCHEME Structure +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPMT_ECC_SCHEME { + /// Scheme selector + + /// Scheme parameters + /// One of: TPMS_KEY_SCHEME_ECDH, TPMS_KEY_SCHEME_ECMQV, TPMS_SIG_SCHEME_RSASSA, + /// TPMS_SIG_SCHEME_RSAPSS, TPMS_SIG_SCHEME_ECDSA, TPMS_SIG_SCHEME_ECDAA, + /// TPMS_SIG_SCHEME_SM2, TPMS_SIG_SCHEME_ECSCHNORR, TPMS_ENC_SCHEME_RSAES, + /// TPMS_ENC_SCHEME_OAEP, TPMS_SCHEME_HASH, TPMS_NULL_ASYM_SCHEME. + pub details: Option, +} + +impl TPMT_ECC_SCHEME { + /// Creates a new instance with the specified values + pub fn new( + details: &Option, + ) -> Self { + Self { + details: details.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPMT_ECC_SCHEME { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + if (self.details.is_none()) { return Ok(()) }; + buf.writeShort(self.details.as_ref().unwrap().GetUnionSelector().into()); + self.details.as_ref().unwrap().toTpm(buf)?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + let r#scheme: TPM_ALG_ID = TPM_ALG_ID(buf.readShort() as u16); + self.details = TPMU_ASYM_SCHEME::create(r#scheme)?; + self.details.as_mut().unwrap().initFromTpm(buf)?; + Ok(()) + } + +} + +impl TpmMarshaller for TPMT_ECC_SCHEME { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// This structure is used to report on the curve parameters of an ECC curve. It is +/// returned by TPM2_ECC_Parameters(). +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPMS_ALGORITHM_DETAIL_ECC { + /// Identifier for the curve + pub curveID: TPM_ECC_CURVE, + + /// Size in bits of the key + pub keySize: u16, + + /// Scheme selector + + /// If not TPM_ALG_NULL, the required KDF and hash algorithm used in secret sharing operations + /// One of: TPMS_KDF_SCHEME_MGF1, TPMS_KDF_SCHEME_KDF1_SP800_56A, TPMS_KDF_SCHEME_KDF2, + /// TPMS_KDF_SCHEME_KDF1_SP800_108, TPMS_SCHEME_HASH, TPMS_NULL_KDF_SCHEME. + pub kdf: Option, + + /// Scheme selector + + /// If not TPM_ALG_NULL, this is the mandatory signature scheme that is required to be + /// used with this curve. + /// One of: TPMS_KEY_SCHEME_ECDH, TPMS_KEY_SCHEME_ECMQV, TPMS_SIG_SCHEME_RSASSA, + /// TPMS_SIG_SCHEME_RSAPSS, TPMS_SIG_SCHEME_ECDSA, TPMS_SIG_SCHEME_ECDAA, + /// TPMS_SIG_SCHEME_SM2, TPMS_SIG_SCHEME_ECSCHNORR, TPMS_ENC_SCHEME_RSAES, + /// TPMS_ENC_SCHEME_OAEP, TPMS_SCHEME_HASH, TPMS_NULL_ASYM_SCHEME. + pub sign: Option, + + /// Fp (the modulus) + pub p: Vec, + + /// Coefficient of the linear term in the curve equation + pub a: Vec, + + /// Constant term for curve equation + pub b: Vec, + + /// X coordinate of base point G + pub gX: Vec, + + /// Y coordinate of base point G + pub gY: Vec, + + /// Order of G + pub n: Vec, + + /// Cofactor (a size of zero indicates a cofactor of 1) + pub h: Vec, +} + +impl TPMS_ALGORITHM_DETAIL_ECC { + /// Creates a new instance with the specified values + pub fn new( + curveID: TPM_ECC_CURVE, + keySize: u16, + kdf: &Option, + sign: &Option, + p: &Vec, + a: &Vec, + b: &Vec, + gX: &Vec, + gY: &Vec, + n: &Vec, + h: &Vec, + ) -> Self { + Self { + curveID: curveID.clone(), + keySize: keySize.clone(), + kdf: kdf.clone(), + sign: sign.clone(), + p: p.clone(), + a: a.clone(), + b: b.clone(), + gX: gX.clone(), + gY: gY.clone(), + n: n.clone(), + h: h.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPMS_ALGORITHM_DETAIL_ECC { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeShort(self.curveID.into()); + buf.writeShort(self.keySize as u16); + buf.writeShort(self.kdf.as_ref().unwrap().GetUnionSelector().into()); + self.kdf.as_ref().unwrap().toTpm(buf)?; + buf.writeShort(self.sign.as_ref().unwrap().GetUnionSelector().into()); + self.sign.as_ref().unwrap().toTpm(buf)?; + buf.writeSizedByteBuf(&self.p, 2); + buf.writeSizedByteBuf(&self.a, 2); + buf.writeSizedByteBuf(&self.b, 2); + buf.writeSizedByteBuf(&self.gX, 2); + buf.writeSizedByteBuf(&self.gY, 2); + buf.writeSizedByteBuf(&self.n, 2); + buf.writeSizedByteBuf(&self.h, 2); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.curveID = TPM_ECC_CURVE(buf.readShort() as u16); + self.keySize = buf.readShort() as u16; + let r#kdfScheme: TPM_ALG_ID = TPM_ALG_ID(buf.readShort() as u16); + self.kdf = TPMU_KDF_SCHEME::create(r#kdfScheme)?; + self.kdf.as_mut().unwrap().initFromTpm(buf)?; + let r#signScheme: TPM_ALG_ID = TPM_ALG_ID(buf.readShort() as u16); + self.sign = TPMU_ASYM_SCHEME::create(r#signScheme)?; + self.sign.as_mut().unwrap().initFromTpm(buf)?; + self.p = buf.readSizedByteBuf(2); + self.a = buf.readSizedByteBuf(2); + self.b = buf.readSizedByteBuf(2); + self.gX = buf.readSizedByteBuf(2); + self.gY = buf.readSizedByteBuf(2); + self.n = buf.readSizedByteBuf(2); + self.h = buf.readSizedByteBuf(2); + Ok(()) + } + +} + +impl TpmMarshaller for TPMS_ALGORITHM_DETAIL_ECC { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// Table 185 Definition of {RSA} TPMS_SIGNATURE_RSA Structure +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPMS_SIGNATURE_RSA { + /// The hash algorithm used to digest the message + /// TPM_ALG_NULL is not allowed. + #[derivative(Default(value="TPM_ALG_ID::NULL"))] + pub hash: TPM_ALG_ID, + + /// The signature is the size of a public key. + pub sig: Vec, +} + +impl TPMS_SIGNATURE_RSA { + /// Creates a new instance with the specified values + pub fn new( + hash: TPM_ALG_ID, + sig: &Vec, + ) -> Self { + Self { + hash: hash.clone(), + sig: sig.clone(), + ..Default::default() + } + } + + fn GetUnionSelector() -> TPM_ALG_ID { + TPM_ALG_ID::RSASSA + } +} + +impl TpmStructure for TPMS_SIGNATURE_RSA { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeShort(self.hash.into()); + buf.writeSizedByteBuf(&self.sig, 2); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.hash = TPM_ALG_ID(buf.readShort() as u16); + self.sig = buf.readSizedByteBuf(2); + Ok(()) + } + +} + +impl TpmMarshaller for TPMS_SIGNATURE_RSA { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// Table 185 Definition of {RSA} TPMS_SIGNATURE_RSA Structure +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPMS_SIGNATURE_RSASSA { + /// The hash algorithm used to digest the message + /// TPM_ALG_NULL is not allowed. + #[derivative(Default(value="TPM_ALG_ID::NULL"))] + pub hash: TPM_ALG_ID, + + /// The signature is the size of a public key. + pub sig: Vec, +} + +impl TPMS_SIGNATURE_RSASSA { + fn GetUnionSelector() -> TPM_ALG_ID { + TPM_ALG_ID::RSASSA + } +} + +impl TpmStructure for TPMS_SIGNATURE_RSASSA { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeShort(self.hash.into()); + buf.writeSizedByteBuf(&self.sig, 2); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.hash = TPM_ALG_ID(buf.readShort() as u16); + self.sig = buf.readSizedByteBuf(2); + Ok(()) + } + +} + +impl TpmMarshaller for TPMS_SIGNATURE_RSASSA { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// Table 185 Definition of {RSA} TPMS_SIGNATURE_RSA Structure +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPMS_SIGNATURE_RSAPSS { + /// The hash algorithm used to digest the message + /// TPM_ALG_NULL is not allowed. + #[derivative(Default(value="TPM_ALG_ID::NULL"))] + pub hash: TPM_ALG_ID, + + /// The signature is the size of a public key. + pub sig: Vec, +} + +impl TPMS_SIGNATURE_RSAPSS { + fn GetUnionSelector() -> TPM_ALG_ID { + TPM_ALG_ID::RSAPSS + } +} + +impl TpmStructure for TPMS_SIGNATURE_RSAPSS { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeShort(self.hash.into()); + buf.writeSizedByteBuf(&self.sig, 2); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.hash = TPM_ALG_ID(buf.readShort() as u16); + self.sig = buf.readSizedByteBuf(2); + Ok(()) + } + +} + +impl TpmMarshaller for TPMS_SIGNATURE_RSAPSS { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// Table 187 Definition of {ECC} TPMS_SIGNATURE_ECC Structure +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPMS_SIGNATURE_ECC { + /// The hash algorithm used in the signature process + /// TPM_ALG_NULL is not allowed. + #[derivative(Default(value="TPM_ALG_ID::NULL"))] + pub hash: TPM_ALG_ID, + pub signatureR: Vec, + pub signatureS: Vec, +} + +impl TPMS_SIGNATURE_ECC { + /// Creates a new instance with the specified values + pub fn new( + hash: TPM_ALG_ID, + signatureR: &Vec, + signatureS: &Vec, + ) -> Self { + Self { + hash: hash.clone(), + signatureR: signatureR.clone(), + signatureS: signatureS.clone(), + ..Default::default() + } + } + + fn GetUnionSelector() -> TPM_ALG_ID { + TPM_ALG_ID::ECDSA + } +} + +impl TpmStructure for TPMS_SIGNATURE_ECC { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeShort(self.hash.into()); + buf.writeSizedByteBuf(&self.signatureR, 2); + buf.writeSizedByteBuf(&self.signatureS, 2); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.hash = TPM_ALG_ID(buf.readShort() as u16); + self.signatureR = buf.readSizedByteBuf(2); + self.signatureS = buf.readSizedByteBuf(2); + Ok(()) + } + +} + +impl TpmMarshaller for TPMS_SIGNATURE_ECC { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// Table 187 Definition of {ECC} TPMS_SIGNATURE_ECC Structure +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPMS_SIGNATURE_ECDSA { + /// The hash algorithm used in the signature process + /// TPM_ALG_NULL is not allowed. + #[derivative(Default(value="TPM_ALG_ID::NULL"))] + pub hash: TPM_ALG_ID, + pub signatureR: Vec, + pub signatureS: Vec, +} + +impl TPMS_SIGNATURE_ECDSA { + fn GetUnionSelector() -> TPM_ALG_ID { + TPM_ALG_ID::ECDSA + } +} + +impl TpmStructure for TPMS_SIGNATURE_ECDSA { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeShort(self.hash.into()); + buf.writeSizedByteBuf(&self.signatureR, 2); + buf.writeSizedByteBuf(&self.signatureS, 2); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.hash = TPM_ALG_ID(buf.readShort() as u16); + self.signatureR = buf.readSizedByteBuf(2); + self.signatureS = buf.readSizedByteBuf(2); + Ok(()) + } + +} + +impl TpmMarshaller for TPMS_SIGNATURE_ECDSA { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// Table 187 Definition of {ECC} TPMS_SIGNATURE_ECC Structure +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPMS_SIGNATURE_ECDAA { + /// The hash algorithm used in the signature process + /// TPM_ALG_NULL is not allowed. + #[derivative(Default(value="TPM_ALG_ID::NULL"))] + pub hash: TPM_ALG_ID, + pub signatureR: Vec, + pub signatureS: Vec, +} + +impl TPMS_SIGNATURE_ECDAA { + fn GetUnionSelector() -> TPM_ALG_ID { + TPM_ALG_ID::ECDAA + } +} + +impl TpmStructure for TPMS_SIGNATURE_ECDAA { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeShort(self.hash.into()); + buf.writeSizedByteBuf(&self.signatureR, 2); + buf.writeSizedByteBuf(&self.signatureS, 2); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.hash = TPM_ALG_ID(buf.readShort() as u16); + self.signatureR = buf.readSizedByteBuf(2); + self.signatureS = buf.readSizedByteBuf(2); + Ok(()) + } + +} + +impl TpmMarshaller for TPMS_SIGNATURE_ECDAA { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// Table 187 Definition of {ECC} TPMS_SIGNATURE_ECC Structure +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPMS_SIGNATURE_SM2 { + /// The hash algorithm used in the signature process + /// TPM_ALG_NULL is not allowed. + #[derivative(Default(value="TPM_ALG_ID::NULL"))] + pub hash: TPM_ALG_ID, + pub signatureR: Vec, + pub signatureS: Vec, +} + +impl TPMS_SIGNATURE_SM2 { + fn GetUnionSelector() -> TPM_ALG_ID { + TPM_ALG_ID::SM2 + } +} + +impl TpmStructure for TPMS_SIGNATURE_SM2 { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeShort(self.hash.into()); + buf.writeSizedByteBuf(&self.signatureR, 2); + buf.writeSizedByteBuf(&self.signatureS, 2); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.hash = TPM_ALG_ID(buf.readShort() as u16); + self.signatureR = buf.readSizedByteBuf(2); + self.signatureS = buf.readSizedByteBuf(2); + Ok(()) + } + +} + +impl TpmMarshaller for TPMS_SIGNATURE_SM2 { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// Table 187 Definition of {ECC} TPMS_SIGNATURE_ECC Structure +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPMS_SIGNATURE_ECSCHNORR { + /// The hash algorithm used in the signature process + /// TPM_ALG_NULL is not allowed. + #[derivative(Default(value="TPM_ALG_ID::NULL"))] + pub hash: TPM_ALG_ID, + pub signatureR: Vec, + pub signatureS: Vec, +} + +impl TPMS_SIGNATURE_ECSCHNORR { + fn GetUnionSelector() -> TPM_ALG_ID { + TPM_ALG_ID::ECSCHNORR + } +} + +impl TpmStructure for TPMS_SIGNATURE_ECSCHNORR { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeShort(self.hash.into()); + buf.writeSizedByteBuf(&self.signatureR, 2); + buf.writeSizedByteBuf(&self.signatureS, 2); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.hash = TPM_ALG_ID(buf.readShort() as u16); + self.signatureR = buf.readSizedByteBuf(2); + self.signatureS = buf.readSizedByteBuf(2); + Ok(()) + } + +} + +impl TpmMarshaller for TPMS_SIGNATURE_ECSCHNORR { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// Custom data structure representing an empty element (i.e. the one with +/// no data to marshal) for selector algorithm TPM_ALG_NULL for the union TPMU_SIGNATURE +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPMS_NULL_SIGNATURE { +} + +impl TPMS_NULL_SIGNATURE { + fn GetUnionSelector() -> TPM_ALG_ID { + TPM_ALG_ID::NULL + } +} + +impl TpmStructure for TPMS_NULL_SIGNATURE { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + Ok(()) + } + +} + +impl TpmMarshaller for TPMS_NULL_SIGNATURE { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// Table 190 shows the basic algorithm-agile structure when a symmetric or asymmetric +/// signature is indicated. The sigAlg parameter indicates the algorithm used for the +/// signature. This structure is output from commands such as the attestation commands and +/// TPM2_Sign, and is an input to commands such as TPM2_VerifySignature(), +/// TPM2_PolicySigned(), and TPM2_FieldUpgradeStart(). +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPMT_SIGNATURE { + /// Selector of the algorithm used to construct the signature + + /// This shall be the actual signature information. + /// One of: TPMS_SIGNATURE_RSASSA, TPMS_SIGNATURE_RSAPSS, TPMS_SIGNATURE_ECDSA, + /// TPMS_SIGNATURE_ECDAA, TPMS_SIGNATURE_SM2, TPMS_SIGNATURE_ECSCHNORR, TPMT_HA, + /// TPMS_SCHEME_HASH, TPMS_NULL_SIGNATURE. + pub signature: Option, +} + +impl TPMT_SIGNATURE { + /// Creates a new instance with the specified values + pub fn new( + signature: &Option, + ) -> Self { + Self { + signature: signature.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPMT_SIGNATURE { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + if (self.signature.is_none()) { return Ok(()) }; + buf.writeShort(self.signature.as_ref().unwrap().GetUnionSelector().into()); + self.signature.as_ref().unwrap().toTpm(buf)?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + let r#sigAlg: TPM_ALG_ID = TPM_ALG_ID(buf.readShort() as u16); + self.signature = TPMU_SIGNATURE::create(r#sigAlg)?; + self.signature.as_mut().unwrap().initFromTpm(buf)?; + Ok(()) + } + +} + +impl TpmMarshaller for TPMT_SIGNATURE { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// Table 192 Definition of TPM2B_ENCRYPTED_SECRET Structure +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2B_ENCRYPTED_SECRET { + /// Secret + pub secret: Vec, +} + +impl TPM2B_ENCRYPTED_SECRET { + /// Creates a new instance with the specified values + pub fn new( + secret: &Vec, + ) -> Self { + Self { + secret: secret.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2B_ENCRYPTED_SECRET { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.secret, 2); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.secret = buf.readSizedByteBuf(2); + Ok(()) + } + +} + +impl TpmMarshaller for TPM2B_ENCRYPTED_SECRET { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// This structure describes the parameters that would appear in the public area of a +/// KEYEDHASH object. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPMS_KEYEDHASH_PARMS { + /// Selects the scheme + + /// Indicates the signing method used for a keyedHash signing object. This field also + /// determines the size of the data field for a data object created with TPM2_Create() or + /// TPM2_CreatePrimary(). + /// One of: TPMS_SCHEME_HMAC, TPMS_SCHEME_XOR, TPMS_NULL_SCHEME_KEYEDHASH. + pub scheme: Option, +} + +impl TPMS_KEYEDHASH_PARMS { + /// Creates a new instance with the specified values + pub fn new( + scheme: &Option, + ) -> Self { + Self { + scheme: scheme.clone(), + ..Default::default() + } + } + + fn GetUnionSelector() -> TPM_ALG_ID { + TPM_ALG_ID::KEYEDHASH + } +} + +impl TpmStructure for TPMS_KEYEDHASH_PARMS { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + if (self.scheme.is_none()) { return Ok(()) }; + buf.writeShort(self.scheme.as_ref().unwrap().GetUnionSelector().into()); + self.scheme.as_ref().unwrap().toTpm(buf)?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + let r#schemeScheme: TPM_ALG_ID = TPM_ALG_ID(buf.readShort() as u16); + self.scheme = TPMU_SCHEME_KEYEDHASH::create(r#schemeScheme)?; + self.scheme.as_mut().unwrap().initFromTpm(buf)?; + Ok(()) + } + +} + +impl TpmMarshaller for TPMS_KEYEDHASH_PARMS { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// This structure contains the common public area parameters for an asymmetric key. The +/// first two parameters of the parameter definition structures of an asymmetric key shall +/// have the same two first components. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPMS_ASYM_PARMS { + /// The companion symmetric algorithm for a restricted decryption key and shall be set to + /// a supported symmetric algorithm + /// This field is optional for keys that are not decryption keys and shall be set to + /// TPM_ALG_NULL if not used. + pub symmetric: TPMT_SYM_DEF_OBJECT, + + /// Scheme selector + + /// For a key with the sign attribute SET, a valid signing scheme for the key type + /// for a key with the decrypt attribute SET, a valid key exchange protocol + /// for a key with sign and decrypt attributes, shall be TPM_ALG_NULL + /// One of: TPMS_KEY_SCHEME_ECDH, TPMS_KEY_SCHEME_ECMQV, TPMS_SIG_SCHEME_RSASSA, + /// TPMS_SIG_SCHEME_RSAPSS, TPMS_SIG_SCHEME_ECDSA, TPMS_SIG_SCHEME_ECDAA, + /// TPMS_SIG_SCHEME_SM2, TPMS_SIG_SCHEME_ECSCHNORR, TPMS_ENC_SCHEME_RSAES, + /// TPMS_ENC_SCHEME_OAEP, TPMS_SCHEME_HASH, TPMS_NULL_ASYM_SCHEME. + pub scheme: Option, +} + +impl TPMS_ASYM_PARMS { + /// Creates a new instance with the specified values + pub fn new( + symmetric: &TPMT_SYM_DEF_OBJECT, + scheme: &Option, + ) -> Self { + Self { + symmetric: symmetric.clone(), + scheme: scheme.clone(), + ..Default::default() + } + } + + fn GetUnionSelector() -> TPM_ALG_ID { + TPM_ALG_ID::ANY + } +} + +impl TpmStructure for TPMS_ASYM_PARMS { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + self.symmetric.toTpm(buf)?; + buf.writeShort(self.scheme.as_ref().unwrap().GetUnionSelector().into()); + self.scheme.as_ref().unwrap().toTpm(buf)?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.symmetric.initFromTpm(buf)?; + let r#schemeScheme: TPM_ALG_ID = TPM_ALG_ID(buf.readShort() as u16); + self.scheme = TPMU_ASYM_SCHEME::create(r#schemeScheme)?; + self.scheme.as_mut().unwrap().initFromTpm(buf)?; + Ok(()) + } + +} + +impl TpmMarshaller for TPMS_ASYM_PARMS { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// A TPM compatible with this specification and supporting RSA shall support two primes +/// and an exponent of zero. An exponent of zero indicates that the exponent is the +/// default of 216 + 1. Support for other values is optional. Use of other exponents in +/// duplicated keys is not recommended because the resulting keys would not be +/// interoperable with other TPMs. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPMS_RSA_PARMS { + /// For a restricted decryption key, shall be set to a supported symmetric algorithm, key + /// size, and mode. + /// if the key is not a restricted decryption key, this field shall be set to TPM_ALG_NULL. + pub symmetric: TPMT_SYM_DEF_OBJECT, + + /// Scheme selector + + /// Scheme.scheme shall be: + /// for an unrestricted signing key, either TPM_ALG_RSAPSS TPM_ALG_RSASSA or TPM_ALG_NULL + /// for a restricted signing key, either TPM_ALG_RSAPSS or TPM_ALG_RSASSA + /// for an unrestricted decryption key, TPM_ALG_RSAES, TPM_ALG_OAEP, or TPM_ALG_NULL + /// unless the object also has the sign attribute + /// for a restricted decryption key, TPM_ALG_NULL + /// NOTE When both sign and decrypt are SET, restricted shall be CLEAR and scheme shall be + /// TPM_ALG_NULL. + /// One of: TPMS_KEY_SCHEME_ECDH, TPMS_KEY_SCHEME_ECMQV, TPMS_SIG_SCHEME_RSASSA, + /// TPMS_SIG_SCHEME_RSAPSS, TPMS_SIG_SCHEME_ECDSA, TPMS_SIG_SCHEME_ECDAA, + /// TPMS_SIG_SCHEME_SM2, TPMS_SIG_SCHEME_ECSCHNORR, TPMS_ENC_SCHEME_RSAES, + /// TPMS_ENC_SCHEME_OAEP, TPMS_SCHEME_HASH, TPMS_NULL_ASYM_SCHEME. + pub scheme: Option, + + /// Number of bits in the public modulus + pub keyBits: u16, + + /// The public exponent + /// A prime number greater than 2. + pub exponent: u32, +} + +impl TPMS_RSA_PARMS { + /// Creates a new instance with the specified values + pub fn new( + symmetric: &TPMT_SYM_DEF_OBJECT, + scheme: &Option, + keyBits: u16, + exponent: u32, + ) -> Self { + Self { + symmetric: symmetric.clone(), + scheme: scheme.clone(), + keyBits: keyBits.clone(), + exponent: exponent.clone(), + ..Default::default() + } + } + + fn GetUnionSelector() -> TPM_ALG_ID { + TPM_ALG_ID::RSA + } +} + +impl TpmStructure for TPMS_RSA_PARMS { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + self.symmetric.toTpm(buf)?; + buf.writeShort(self.scheme.as_ref().unwrap().GetUnionSelector().into()); + self.scheme.as_ref().unwrap().toTpm(buf)?; + buf.writeShort(self.keyBits as u16); + buf.writeInt(self.exponent as u32); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.symmetric.initFromTpm(buf)?; + let r#schemeScheme: TPM_ALG_ID = TPM_ALG_ID(buf.readShort() as u16); + self.scheme = TPMU_ASYM_SCHEME::create(r#schemeScheme)?; + self.scheme.as_mut().unwrap().initFromTpm(buf)?; + self.keyBits = buf.readShort() as u16; + self.exponent = buf.readInt() as u32; + Ok(()) + } + +} + +impl TpmMarshaller for TPMS_RSA_PARMS { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// This structure contains the parameters for prime modulus ECC. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPMS_ECC_PARMS { + /// For a restricted decryption key, shall be set to a supported symmetric algorithm, key + /// size. and mode. + /// if the key is not a restricted decryption key, this field shall be set to TPM_ALG_NULL. + pub symmetric: TPMT_SYM_DEF_OBJECT, + + /// Scheme selector + + /// If the sign attribute of the key is SET, then this shall be a valid signing scheme. + /// NOTE If the sign parameter in curveID indicates a mandatory scheme, then this field + /// shall have the same value. + /// If the decrypt attribute of the key is SET, then this shall be a valid key exchange + /// scheme or TPM_ALG_NULL. + /// If the key is a Storage Key, then this field shall be TPM_ALG_NULL. + /// One of: TPMS_KEY_SCHEME_ECDH, TPMS_KEY_SCHEME_ECMQV, TPMS_SIG_SCHEME_RSASSA, + /// TPMS_SIG_SCHEME_RSAPSS, TPMS_SIG_SCHEME_ECDSA, TPMS_SIG_SCHEME_ECDAA, + /// TPMS_SIG_SCHEME_SM2, TPMS_SIG_SCHEME_ECSCHNORR, TPMS_ENC_SCHEME_RSAES, + /// TPMS_ENC_SCHEME_OAEP, TPMS_SCHEME_HASH, TPMS_NULL_ASYM_SCHEME. + pub scheme: Option, + + /// ECC curve ID + pub curveID: TPM_ECC_CURVE, + + /// Scheme selector + + /// An optional key derivation scheme for generating a symmetric key from a Z value + /// If the kdf parameter associated with curveID is not TPM_ALG_NULL then this is required + /// to be NULL. + /// NOTE There are currently no commands where this parameter has effect and, in the + /// reference code, this field needs to be set to TPM_ALG_NULL. + /// One of: TPMS_KDF_SCHEME_MGF1, TPMS_KDF_SCHEME_KDF1_SP800_56A, TPMS_KDF_SCHEME_KDF2, + /// TPMS_KDF_SCHEME_KDF1_SP800_108, TPMS_SCHEME_HASH, TPMS_NULL_KDF_SCHEME. + pub kdf: Option, +} + +impl TPMS_ECC_PARMS { + /// Creates a new instance with the specified values + pub fn new( + symmetric: &TPMT_SYM_DEF_OBJECT, + scheme: &Option, + curveID: TPM_ECC_CURVE, + kdf: &Option, + ) -> Self { + Self { + symmetric: symmetric.clone(), + scheme: scheme.clone(), + curveID: curveID.clone(), + kdf: kdf.clone(), + ..Default::default() + } + } + + fn GetUnionSelector() -> TPM_ALG_ID { + TPM_ALG_ID::ECC + } +} + +impl TpmStructure for TPMS_ECC_PARMS { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + self.symmetric.toTpm(buf)?; + buf.writeShort(self.scheme.as_ref().unwrap().GetUnionSelector().into()); + self.scheme.as_ref().unwrap().toTpm(buf)?; + buf.writeShort(self.curveID.into()); + buf.writeShort(self.kdf.as_ref().unwrap().GetUnionSelector().into()); + self.kdf.as_ref().unwrap().toTpm(buf)?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.symmetric.initFromTpm(buf)?; + let r#schemeScheme: TPM_ALG_ID = TPM_ALG_ID(buf.readShort() as u16); + self.scheme = TPMU_ASYM_SCHEME::create(r#schemeScheme)?; + self.scheme.as_mut().unwrap().initFromTpm(buf)?; + self.curveID = TPM_ECC_CURVE(buf.readShort() as u16); + let r#kdfScheme: TPM_ALG_ID = TPM_ALG_ID(buf.readShort() as u16); + self.kdf = TPMU_KDF_SCHEME::create(r#kdfScheme)?; + self.kdf.as_mut().unwrap().initFromTpm(buf)?; + Ok(()) + } + +} + +impl TpmMarshaller for TPMS_ECC_PARMS { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// This structure is used in TPM2_TestParms() to validate that a set of algorithm +/// parameters is supported by the TPM. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPMT_PUBLIC_PARMS { + /// The algorithm to be tested + + /// The algorithm details + /// One of: TPMS_KEYEDHASH_PARMS, TPMS_SYMCIPHER_PARMS, TPMS_RSA_PARMS, TPMS_ECC_PARMS, + /// TPMS_ASYM_PARMS. + pub parameters: Option, +} + +impl TPMT_PUBLIC_PARMS { + /// Creates a new instance with the specified values + pub fn new( + parameters: &Option, + ) -> Self { + Self { + parameters: parameters.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPMT_PUBLIC_PARMS { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + if (self.parameters.is_none()) { return Ok(()) }; + buf.writeShort(self.parameters.as_ref().unwrap().GetUnionSelector().into()); + self.parameters.as_ref().unwrap().toTpm(buf)?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + let r#type: TPM_ALG_ID = TPM_ALG_ID(buf.readShort() as u16); + self.parameters = TPMU_PUBLIC_PARMS::create(r#type)?; + self.parameters.as_mut().unwrap().initFromTpm(buf)?; + Ok(()) + } + +} + +impl TpmMarshaller for TPMT_PUBLIC_PARMS { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// Table 201 defines the public area structure. The Name of the object is nameAlg +/// concatenated with the digest of this structure using nameAlg. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPMT_PUBLIC { + /// Algorithm associated with this object + + /// Algorithm used for computing the Name of the object + /// NOTE The "+" indicates that the instance of a TPMT_PUBLIC may have a "+" to indicate + /// that the nameAlg may be TPM_ALG_NULL. + #[derivative(Default(value="TPM_ALG_ID::NULL"))] + pub nameAlg: TPM_ALG_ID, + + /// Attributes that, along with type, determine the manipulations of this object + pub objectAttributes: TPMA_OBJECT, + + /// Optional policy for using this key + /// The policy is computed using the nameAlg of the object. + /// NOTE Shall be the Empty Policy if no authorization policy is present. + pub authPolicy: Vec, + + /// The algorithm or structure details + /// One of: TPMS_KEYEDHASH_PARMS, TPMS_SYMCIPHER_PARMS, TPMS_RSA_PARMS, TPMS_ECC_PARMS, + /// TPMS_ASYM_PARMS. + pub parameters: Option, + + /// The unique identifier of the structure + /// For an asymmetric key, this would be the public key. + /// One of: TPM2B_DIGEST_KEYEDHASH, TPM2B_DIGEST_SYMCIPHER, TPM2B_PUBLIC_KEY_RSA, + /// TPMS_ECC_POINT, TPMS_DERIVE. + pub unique: Option, +} + +impl TPMT_PUBLIC { + /// Creates a new instance with the specified values + pub fn new( + nameAlg: TPM_ALG_ID, + objectAttributes: TPMA_OBJECT, + authPolicy: &Vec, + parameters: &Option, + unique: &Option, + ) -> Self { + Self { + nameAlg: nameAlg.clone(), + objectAttributes: objectAttributes.clone(), + authPolicy: authPolicy.clone(), + parameters: parameters.clone(), + unique: unique.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPMT_PUBLIC { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + if (self.parameters.is_none()) { return Ok(()) }; + buf.writeShort(self.parameters.as_ref().unwrap().GetUnionSelector().into()); + buf.writeShort(self.nameAlg.into()); + buf.writeInt(self.objectAttributes.into()); + buf.writeSizedByteBuf(&self.authPolicy, 2); + self.parameters.as_ref().unwrap().toTpm(buf)?; + self.unique.as_ref().unwrap().toTpm(buf)?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + let r#type: TPM_ALG_ID = TPM_ALG_ID(buf.readShort() as u16); + self.nameAlg = TPM_ALG_ID(buf.readShort() as u16); + self.objectAttributes = TPMA_OBJECT(buf.readInt() as u32); + self.authPolicy = buf.readSizedByteBuf(2); + self.parameters = TPMU_PUBLIC_PARMS::create(r#type)?; + self.parameters.as_mut().unwrap().initFromTpm(buf)?; + self.unique = TPMU_PUBLIC_ID::create(r#type)?; + self.unique.as_mut().unwrap().initFromTpm(buf)?; + Ok(()) + } + +} + +impl TpmMarshaller for TPMT_PUBLIC { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// This sized buffer is used to embed a TPMT_PUBLIC in a load command and in any response +/// that returns a public area. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2B_PUBLIC { + /// The public area + /// NOTE The + indicates that the caller may specify that use of TPM_ALG_NULL is allowed + /// for nameAlg. + pub publicArea: TPMT_PUBLIC, +} + +impl TPM2B_PUBLIC { + /// Creates a new instance with the specified values + pub fn new( + publicArea: &TPMT_PUBLIC, + ) -> Self { + Self { + publicArea: publicArea.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2B_PUBLIC { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedObj(&self.publicArea)?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + buf.readSizedObj(&mut self.publicArea)?; + Ok(()) + } + +} + +impl TpmMarshaller for TPM2B_PUBLIC { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// This sized buffer is used to embed a TPMT_TEMPLATE for TPM2_CreateLoaded(). +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2B_TEMPLATE { + /// The public area + pub buffer: Vec, +} + +impl TPM2B_TEMPLATE { + /// Creates a new instance with the specified values + pub fn new( + buffer: &Vec, + ) -> Self { + Self { + buffer: buffer.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2B_TEMPLATE { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.buffer, 2); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.buffer = buf.readSizedByteBuf(2); + Ok(()) + } + +} + +impl TpmMarshaller for TPM2B_TEMPLATE { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// This structure is defined for coding purposes. For IO to the TPM, the sensitive +/// portion of the key will be in a canonical form. For an RSA key, this will be one of +/// the prime factors of the public modulus. After loading, it is typical that other +/// values will be computed so that computations using the private key will not need to +/// start with just one prime factor. This structure can be used to store the results of +/// such vendor-specific calculations. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2B_PRIVATE_VENDOR_SPECIFIC { + pub buffer: Vec, +} + +impl TPM2B_PRIVATE_VENDOR_SPECIFIC { + /// Creates a new instance with the specified values + pub fn new( + buffer: &Vec, + ) -> Self { + Self { + buffer: buffer.clone(), + ..Default::default() + } + } + + fn GetUnionSelector() -> TPM_ALG_ID { + TPM_ALG_ID::ANY + } +} + +impl TpmStructure for TPM2B_PRIVATE_VENDOR_SPECIFIC { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.buffer, 2); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.buffer = buf.readSizedByteBuf(2); + Ok(()) + } + +} + +impl TpmMarshaller for TPM2B_PRIVATE_VENDOR_SPECIFIC { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// AuthValue shall not be larger than the size of the digest produced by the nameAlg of +/// the object. seedValue shall be the size of the digest produced by the nameAlg of the object. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPMT_SENSITIVE { + /// Identifier for the sensitive area + /// This shall be the same as the type parameter of the associated public area. + + /// User authorization data + /// The authValue may be a zero-length string. + pub authValue: Vec, + + /// For a parent object, the optional protection seed; for other objects, the obfuscation value + pub seedValue: Vec, + + /// The type-specific private data + /// One of: TPM2B_PRIVATE_KEY_RSA, TPM2B_ECC_PARAMETER, TPM2B_SENSITIVE_DATA, + /// TPM2B_SYM_KEY, TPM2B_PRIVATE_VENDOR_SPECIFIC. + pub sensitive: Option, +} + +impl TPMT_SENSITIVE { + /// Creates a new instance with the specified values + pub fn new( + authValue: &Vec, + seedValue: &Vec, + sensitive: &Option, + ) -> Self { + Self { + authValue: authValue.clone(), + seedValue: seedValue.clone(), + sensitive: sensitive.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPMT_SENSITIVE { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + if (self.sensitive.is_none()) { return Ok(()) }; + buf.writeShort(self.sensitive.as_ref().unwrap().GetUnionSelector().into()); + buf.writeSizedByteBuf(&self.authValue, 2); + buf.writeSizedByteBuf(&self.seedValue, 2); + self.sensitive.as_ref().unwrap().toTpm(buf)?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + let r#sensitiveType: TPM_ALG_ID = TPM_ALG_ID(buf.readShort() as u16); + self.authValue = buf.readSizedByteBuf(2); + self.seedValue = buf.readSizedByteBuf(2); + self.sensitive = TPMU_SENSITIVE_COMPOSITE::create(r#sensitiveType)?; + self.sensitive.as_mut().unwrap().initFromTpm(buf)?; + Ok(()) + } + +} + +impl TpmMarshaller for TPMT_SENSITIVE { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// The TPM2B_SENSITIVE structure is used as a parameter in TPM2_LoadExternal(). It is an +/// unencrypted sensitive area but it may be encrypted using parameter encryption. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2B_SENSITIVE { + /// An unencrypted sensitive area + pub sensitiveArea: TPMT_SENSITIVE, +} + +impl TPM2B_SENSITIVE { + /// Creates a new instance with the specified values + pub fn new( + sensitiveArea: &TPMT_SENSITIVE, + ) -> Self { + Self { + sensitiveArea: sensitiveArea.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2B_SENSITIVE { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedObj(&self.sensitiveArea)?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + buf.readSizedObj(&mut self.sensitiveArea)?; + Ok(()) + } + +} + +impl TpmMarshaller for TPM2B_SENSITIVE { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// This structure is defined to size the contents of a TPM2B_PRIVATE. This structure is +/// not directly marshaled or unmarshaled. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct _PRIVATE { + pub integrityOuter: Vec, + + /// Could also be a TPM2B_IV + pub integrityInner: Vec, + + /// The sensitive area + pub sensitive: TPMT_SENSITIVE, +} + +impl _PRIVATE { + /// Creates a new instance with the specified values + pub fn new( + integrityOuter: &Vec, + integrityInner: &Vec, + sensitive: &TPMT_SENSITIVE, + ) -> Self { + Self { + integrityOuter: integrityOuter.clone(), + integrityInner: integrityInner.clone(), + sensitive: sensitive.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for _PRIVATE { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::<_PRIVATE>()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.integrityOuter, 2); + buf.writeSizedByteBuf(&self.integrityInner, 2); + buf.writeSizedObj(&self.sensitive)?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.integrityOuter = buf.readSizedByteBuf(2); + self.integrityInner = buf.readSizedByteBuf(2); + buf.readSizedObj(&mut self.sensitive)?; + Ok(()) + } + +} + +impl TpmMarshaller for _PRIVATE { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// The TPM2B_PRIVATE structure is used as a parameter in multiple commands that create, +/// load, and modify the sensitive area of an object. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2B_PRIVATE { + /// An encrypted private area + pub buffer: Vec, +} + +impl TPM2B_PRIVATE { + /// Creates a new instance with the specified values + pub fn new( + buffer: &Vec, + ) -> Self { + Self { + buffer: buffer.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2B_PRIVATE { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.buffer, 2); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.buffer = buf.readSizedByteBuf(2); + Ok(()) + } + +} + +impl TpmMarshaller for TPM2B_PRIVATE { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// This structure is used for sizing the TPM2B_ID_OBJECT. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPMS_ID_OBJECT { + /// HMAC using the nameAlg of the storage key on the target TPM + pub integrityHMAC: Vec, + + /// Credential protector information returned if name matches the referenced object + /// All of the encIdentity is encrypted, including the size field. + /// NOTE The TPM is not required to check that the size is not larger than the digest of + /// the nameAlg. However, if the size is larger, the ID object may not be usable on a TPM + /// that has no digest larger than produced by nameAlg. + pub encIdentity: Vec, +} + +impl TPMS_ID_OBJECT { + /// Creates a new instance with the specified values + pub fn new( + integrityHMAC: &Vec, + encIdentity: &Vec, + ) -> Self { + Self { + integrityHMAC: integrityHMAC.clone(), + encIdentity: encIdentity.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPMS_ID_OBJECT { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.integrityHMAC, 2); + buf.writeByteBuf(&self.encIdentity); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.integrityHMAC = buf.readSizedByteBuf(2); + self.encIdentity = buf.readByteBuf(buf.getCurStuctRemainingSize()); + Ok(()) + } + +} + +impl TpmMarshaller for TPMS_ID_OBJECT { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// This structure is an output from TPM2_MakeCredential() and is an input to +/// TPM2_ActivateCredential(). +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2B_ID_OBJECT { + /// An encrypted credential area + pub credential: TPMS_ID_OBJECT, +} + +impl TPM2B_ID_OBJECT { + /// Creates a new instance with the specified values + pub fn new( + credential: &TPMS_ID_OBJECT, + ) -> Self { + Self { + credential: credential.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2B_ID_OBJECT { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedObj(&self.credential)?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + buf.readSizedObj(&mut self.credential)?; + Ok(()) + } + +} + +impl TpmMarshaller for TPM2B_ID_OBJECT { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// This is the data that can be written to and read from a TPM_NT_PIN_PASS or +/// TPM_NT_PIN_FAIL non-volatile index. pinCount is the most significant octets. pinLimit +/// is the least significant octets. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPMS_NV_PIN_COUNTER_PARAMETERS { + /// This counter shows the current number of successful authValue authorization attempts + /// to access a TPM_NT_PIN_PASS index or the current number of unsuccessful authValue + /// authorization attempts to access a TPM_NT_PIN_FAIL index. + pub pinCount: u32, + + /// This threshold is the value of pinCount at which the authValue authorization of the + /// host TPM_NT_PIN_PASS or TPM_NT_PIN_FAIL index is locked out. + pub pinLimit: u32, +} + +impl TPMS_NV_PIN_COUNTER_PARAMETERS { + /// Creates a new instance with the specified values + pub fn new( + pinCount: u32, + pinLimit: u32, + ) -> Self { + Self { + pinCount: pinCount.clone(), + pinLimit: pinLimit.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPMS_NV_PIN_COUNTER_PARAMETERS { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeInt(self.pinCount as u32); + buf.writeInt(self.pinLimit as u32); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.pinCount = buf.readInt() as u32; + self.pinLimit = buf.readInt() as u32; + Ok(()) + } + +} + +impl TpmMarshaller for TPMS_NV_PIN_COUNTER_PARAMETERS { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// This structure describes an NV Index. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPMS_NV_PUBLIC { + /// The handle of the data area + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub nvIndex: TPM_HANDLE, + + /// Hash algorithm used to compute the name of the Index and used for the authPolicy. For + /// an extend index, the hash algorithm used for the extend. + #[derivative(Default(value="TPM_ALG_ID::NULL"))] + pub nameAlg: TPM_ALG_ID, + + /// The Index attributes + pub attributes: TPMA_NV, + + /// Optional access policy for the Index + /// The policy is computed using the nameAlg + /// NOTE Shall be the Empty Policy if no authorization policy is present. + pub authPolicy: Vec, + + /// The size of the data area + /// The maximum size is implementation-dependent. The minimum maximum size is platform-specific. + pub dataSize: u16, +} + +impl TPMS_NV_PUBLIC { + /// Creates a new instance with the specified values + pub fn new( + nvIndex: &TPM_HANDLE, + nameAlg: TPM_ALG_ID, + attributes: TPMA_NV, + authPolicy: &Vec, + dataSize: u16, + ) -> Self { + Self { + nvIndex: nvIndex.clone(), + nameAlg: nameAlg.clone(), + attributes: attributes.clone(), + authPolicy: authPolicy.clone(), + dataSize: dataSize.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPMS_NV_PUBLIC { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + self.nvIndex.toTpm(buf)?; + buf.writeShort(self.nameAlg.into()); + buf.writeInt(self.attributes.into()); + buf.writeSizedByteBuf(&self.authPolicy, 2); + buf.writeShort(self.dataSize as u16); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.nvIndex.initFromTpm(buf)?; + self.nameAlg = TPM_ALG_ID(buf.readShort() as u16); + self.attributes = TPMA_NV(buf.readInt() as u32); + self.authPolicy = buf.readSizedByteBuf(2); + self.dataSize = buf.readShort() as u16; + Ok(()) + } + +} + +impl TpmMarshaller for TPMS_NV_PUBLIC { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// This structure is used when a TPMS_NV_PUBLIC is sent on the TPM interface. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2B_NV_PUBLIC { + /// The public area + pub nvPublic: TPMS_NV_PUBLIC, +} + +impl TPM2B_NV_PUBLIC { + /// Creates a new instance with the specified values + pub fn new( + nvPublic: &TPMS_NV_PUBLIC, + ) -> Self { + Self { + nvPublic: nvPublic.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2B_NV_PUBLIC { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedObj(&self.nvPublic)?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + buf.readSizedObj(&mut self.nvPublic)?; + Ok(()) + } + +} + +impl TpmMarshaller for TPM2B_NV_PUBLIC { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// This structure holds the object or session context data. When saved, the full +/// structure is encrypted. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2B_CONTEXT_SENSITIVE { + /// The sensitive data + pub buffer: Vec, +} + +impl TPM2B_CONTEXT_SENSITIVE { + /// Creates a new instance with the specified values + pub fn new( + buffer: &Vec, + ) -> Self { + Self { + buffer: buffer.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2B_CONTEXT_SENSITIVE { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.buffer, 2); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.buffer = buf.readSizedByteBuf(2); + Ok(()) + } + +} + +impl TpmMarshaller for TPM2B_CONTEXT_SENSITIVE { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// This structure holds the integrity value and the encrypted data for a context. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPMS_CONTEXT_DATA { + /// The integrity value + pub integrity: Vec, + + /// The sensitive area + pub encrypted: Vec, +} + +impl TPMS_CONTEXT_DATA { + /// Creates a new instance with the specified values + pub fn new( + integrity: &Vec, + encrypted: &Vec, + ) -> Self { + Self { + integrity: integrity.clone(), + encrypted: encrypted.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPMS_CONTEXT_DATA { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.integrity, 2); + buf.writeByteBuf(&self.encrypted); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.integrity = buf.readSizedByteBuf(2); + self.encrypted = buf.readByteBuf(buf.getCurStuctRemainingSize()); + Ok(()) + } + +} + +impl TpmMarshaller for TPMS_CONTEXT_DATA { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// This structure is used in a TPMS_CONTEXT. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2B_CONTEXT_DATA { + pub buffer: TPMS_CONTEXT_DATA, +} + +impl TPM2B_CONTEXT_DATA { + /// Creates a new instance with the specified values + pub fn new( + buffer: &TPMS_CONTEXT_DATA, + ) -> Self { + Self { + buffer: buffer.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2B_CONTEXT_DATA { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedObj(&self.buffer)?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + buf.readSizedObj(&mut self.buffer)?; + Ok(()) + } + +} + +impl TpmMarshaller for TPM2B_CONTEXT_DATA { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// This structure is used in TPM2_ContextLoad() and TPM2_ContextSave(). If the values of +/// the TPMS_CONTEXT structure in TPM2_ContextLoad() are not the same as the values when +/// the context was saved (TPM2_ContextSave()), then the TPM shall not load the context. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPMS_CONTEXT { + /// The sequence number of the context + /// NOTE Transient object contexts and session contexts used different counters. + pub sequence: u64, + + /// A handle indicating if the context is a session, object, or sequence object (see Table + /// 222 Context Handle Values + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub savedHandle: TPM_HANDLE, + + /// The hierarchy of the context + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub hierarchy: TPM_HANDLE, + + /// The context data and integrity HMAC + pub contextBlob: TPMS_CONTEXT_DATA, +} + +impl TPMS_CONTEXT { + /// Creates a new instance with the specified values + pub fn new( + sequence: u64, + savedHandle: &TPM_HANDLE, + hierarchy: &TPM_HANDLE, + contextBlob: &TPMS_CONTEXT_DATA, + ) -> Self { + Self { + sequence: sequence.clone(), + savedHandle: savedHandle.clone(), + hierarchy: hierarchy.clone(), + contextBlob: contextBlob.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPMS_CONTEXT { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeInt64(self.sequence as u64); + self.savedHandle.toTpm(buf)?; + self.hierarchy.toTpm(buf)?; + buf.writeSizedObj(&self.contextBlob)?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.sequence = buf.readInt64() as u64; + self.savedHandle.initFromTpm(buf)?; + self.hierarchy.initFromTpm(buf)?; + buf.readSizedObj(&mut self.contextBlob)?; + Ok(()) + } + +} + +impl TpmMarshaller for TPMS_CONTEXT { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// This structure provides information relating to the creation environment for the +/// object. The creation data includes the parent Name, parent Qualified Name, and the +/// digest of selected PCR. These values represent the environment in which the object was +/// created. Creation data allows a relying party to determine if an object was created +/// when some appropriate protections were present. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPMS_CREATION_DATA { + /// List indicating the PCR included in pcrDigest + pub pcrSelect: Vec, + + /// Digest of the selected PCR using nameAlg of the object for which this structure is + /// being created + /// pcrDigest.size shall be zero if the pcrSelect list is empty. + pub pcrDigest: Vec, + + /// The locality at which the object was created + pub locality: TPMA_LOCALITY, + + /// NameAlg of the parent + #[derivative(Default(value="TPM_ALG_ID::NULL"))] + pub parentNameAlg: TPM_ALG_ID, + + /// Name of the parent at time of creation + /// The size will match digest size associated with parentNameAlg unless it is + /// TPM_ALG_NULL, in which case the size will be 4 and parentName will be the hierarchy handle. + pub parentName: Vec, + + /// Qualified Name of the parent at the time of creation + /// Size is the same as parentName. + pub parentQualifiedName: Vec, + + /// Association with additional information added by the key creator + /// This will be the contents of the outsideInfo parameter in TPM2_Create() or TPM2_CreatePrimary(). + pub outsideInfo: Vec, +} + +impl TPMS_CREATION_DATA { + /// Creates a new instance with the specified values + pub fn new( + pcrSelect: &Vec, + pcrDigest: &Vec, + locality: TPMA_LOCALITY, + parentNameAlg: TPM_ALG_ID, + parentName: &Vec, + parentQualifiedName: &Vec, + outsideInfo: &Vec, + ) -> Self { + Self { + pcrSelect: pcrSelect.clone(), + pcrDigest: pcrDigest.clone(), + locality: locality.clone(), + parentNameAlg: parentNameAlg.clone(), + parentName: parentName.clone(), + parentQualifiedName: parentQualifiedName.clone(), + outsideInfo: outsideInfo.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPMS_CREATION_DATA { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeObjArr(self.pcrSelect.as_ref())?; + buf.writeSizedByteBuf(&self.pcrDigest, 2); + buf.writeByte(self.locality.into()); + buf.writeShort(self.parentNameAlg.into()); + buf.writeSizedByteBuf(&self.parentName, 2); + buf.writeSizedByteBuf(&self.parentQualifiedName, 2); + buf.writeSizedByteBuf(&self.outsideInfo, 2); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + buf.readObjArr(self.pcrSelect.as_mut())?; + self.pcrDigest = buf.readSizedByteBuf(2); + self.locality = TPMA_LOCALITY(buf.readByte() as u8); + self.parentNameAlg = TPM_ALG_ID(buf.readShort() as u16); + self.parentName = buf.readSizedByteBuf(2); + self.parentQualifiedName = buf.readSizedByteBuf(2); + self.outsideInfo = buf.readSizedByteBuf(2); + Ok(()) + } + +} + +impl TpmMarshaller for TPMS_CREATION_DATA { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// This structure is created by TPM2_Create() and TPM2_CreatePrimary(). It is never +/// entered into the TPM and never has a size of zero. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2B_CREATION_DATA { + pub creationData: TPMS_CREATION_DATA, +} + +impl TPM2B_CREATION_DATA { + /// Creates a new instance with the specified values + pub fn new( + creationData: &TPMS_CREATION_DATA, + ) -> Self { + Self { + creationData: creationData.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2B_CREATION_DATA { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedObj(&self.creationData)?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + buf.readSizedObj(&mut self.creationData)?; + Ok(()) + } + +} + +impl TpmMarshaller for TPM2B_CREATION_DATA { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// TPMS_AC_OUTPUT is used to return information about an AC. The tag structure parameter +/// indicates the type of the data value. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPMS_AC_OUTPUT { + /// Tag indicating the contents of data + pub tag: TPM_AT, + + /// The data returned from the AC + pub data: u32, +} + +impl TPMS_AC_OUTPUT { + /// Creates a new instance with the specified values + pub fn new( + tag: TPM_AT, + data: u32, + ) -> Self { + Self { + tag: tag.clone(), + data: data.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPMS_AC_OUTPUT { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeInt(self.tag.into()); + buf.writeInt(self.data as u32); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.tag = TPM_AT(buf.readInt() as u32); + self.data = buf.readInt() as u32; + Ok(()) + } + +} + +impl TpmMarshaller for TPMS_AC_OUTPUT { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// This list is only used in TPM2_AC_GetCapability(). +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPML_AC_CAPABILITIES { + /// A list of AC values + pub acCapabilities: Vec, +} + +impl TPML_AC_CAPABILITIES { + /// Creates a new instance with the specified values + pub fn new( + acCapabilities: &Vec, + ) -> Self { + Self { + acCapabilities: acCapabilities.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPML_AC_CAPABILITIES { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeObjArr(self.acCapabilities.as_ref())?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + buf.readObjArr(self.acCapabilities.as_mut())?; + Ok(()) + } + +} + +impl TpmMarshaller for TPML_AC_CAPABILITIES { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// TPM2_Startup() is always preceded by _TPM_Init, which is the physical indication that +/// TPM initialization is necessary because of a system-wide reset. TPM2_Startup() is only +/// valid after _TPM_Init. Additional TPM2_Startup() commands are not allowed after it has +/// completed successfully. If a TPM requires TPM2_Startup() and another command is +/// received, or if the TPM receives TPM2_Startup() when it is not required, the TPM shall +/// return TPM_RC_INITIALIZE. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_Startup_REQUEST { + /// TPM_SU_CLEAR or TPM_SU_STATE + pub startupType: TPM_SU, +} + +impl TPM2_Startup_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + startupType: TPM_SU, + ) -> Self { + Self { + startupType: startupType.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_Startup_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeShort(self.startupType.into()); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.startupType = TPM_SU(buf.readShort() as u16); + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_Startup_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_Startup_REQUEST { + fn num_handles(&self) -> u16 { 0 } + +} + +impl ReqStructure for TPM2_Startup_REQUEST { + fn num_auth_handles(&self) -> u16 { 0 } + + fn get_handles(&self) -> Vec { vec![] } +} + +/// This command is used to prepare the TPM for a power cycle. The shutdownType parameter +/// indicates how the subsequent TPM2_Startup() will be processed. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_Shutdown_REQUEST { + /// TPM_SU_CLEAR or TPM_SU_STATE + pub shutdownType: TPM_SU, +} + +impl TPM2_Shutdown_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + shutdownType: TPM_SU, + ) -> Self { + Self { + shutdownType: shutdownType.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_Shutdown_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeShort(self.shutdownType.into()); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.shutdownType = TPM_SU(buf.readShort() as u16); + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_Shutdown_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_Shutdown_REQUEST { + fn num_handles(&self) -> u16 { 0 } + +} + +impl ReqStructure for TPM2_Shutdown_REQUEST { + fn num_auth_handles(&self) -> u16 { 0 } + + fn get_handles(&self) -> Vec { vec![] } +} + +/// This command causes the TPM to perform a test of its capabilities. If the fullTest is +/// YES, the TPM will test all functions. If fullTest = NO, the TPM will only test those +/// functions that have not previously been tested. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_SelfTest_REQUEST { + /// YES if full test to be performed + /// NO if only test of untested functions required + pub fullTest: u8, +} + +impl TPM2_SelfTest_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + fullTest: u8, + ) -> Self { + Self { + fullTest: fullTest.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_SelfTest_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeByte(self.fullTest as u8); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.fullTest = buf.readByte() as u8; + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_SelfTest_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_SelfTest_REQUEST { + fn num_handles(&self) -> u16 { 0 } + +} + +impl ReqStructure for TPM2_SelfTest_REQUEST { + fn num_auth_handles(&self) -> u16 { 0 } + + fn get_handles(&self) -> Vec { vec![] } +} + +/// This command causes the TPM to perform a test of the selected algorithms. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_IncrementalSelfTest_REQUEST { + /// List of algorithms that should be tested + pub toTest: Vec, +} + +impl TPM2_IncrementalSelfTest_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + toTest: &Vec, + ) -> Self { + Self { + toTest: toTest.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_IncrementalSelfTest_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeValArr(self.toTest.as_ref(), 2); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + buf.readValArr(self.toTest.as_mut(), 2)?; + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_IncrementalSelfTest_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_IncrementalSelfTest_REQUEST { + fn num_handles(&self) -> u16 { 0 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 4, val_len: 2 } } +} + +impl ReqStructure for TPM2_IncrementalSelfTest_REQUEST { + fn num_auth_handles(&self) -> u16 { 0 } + + fn get_handles(&self) -> Vec { vec![] } +} + +/// This command causes the TPM to perform a test of the selected algorithms. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct IncrementalSelfTestResponse { + /// List of algorithms that need testing + pub toDoList: Vec, +} + +impl IncrementalSelfTestResponse { +} + +impl TpmStructure for IncrementalSelfTestResponse { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeValArr(self.toDoList.as_ref(), 2); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + buf.readValArr(self.toDoList.as_mut(), 2)?; + Ok(()) + } + +} + +impl TpmMarshaller for IncrementalSelfTestResponse { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for IncrementalSelfTestResponse { + fn num_handles(&self) -> u16 { 0 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 4, val_len: 2 } } +} + +impl RespStructure for IncrementalSelfTestResponse { + fn get_handle(&self) -> TPM_HANDLE { TPM_HANDLE::default() } + + fn set_handle(&mut self, _handle: &TPM_HANDLE) { } +} + +/// This command returns manufacturer-specific information regarding the results of a +/// self-test and an indication of the test status. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_GetTestResult_REQUEST { +} + +impl TPM2_GetTestResult_REQUEST { +} + +impl TpmStructure for TPM2_GetTestResult_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_GetTestResult_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_GetTestResult_REQUEST { + fn num_handles(&self) -> u16 { 0 } + +} + +impl ReqStructure for TPM2_GetTestResult_REQUEST { + fn num_auth_handles(&self) -> u16 { 0 } + + fn get_handles(&self) -> Vec { vec![] } +} + +/// This command returns manufacturer-specific information regarding the results of a +/// self-test and an indication of the test status. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct GetTestResultResponse { + /// Test result data + /// contains manufacturer-specific information + pub outData: Vec, + pub testResult: TPM_RC, +} + +impl GetTestResultResponse { +} + +impl TpmStructure for GetTestResultResponse { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.outData, 2); + buf.writeInt(self.testResult.into()); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.outData = buf.readSizedByteBuf(2); + self.testResult = TPM_RC(buf.readInt() as u32); + Ok(()) + } + +} + +impl TpmMarshaller for GetTestResultResponse { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for GetTestResultResponse { + fn num_handles(&self) -> u16 { 0 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 2, val_len: 1 } } +} + +impl RespStructure for GetTestResultResponse { + fn get_handle(&self) -> TPM_HANDLE { TPM_HANDLE::default() } + + fn set_handle(&mut self, _handle: &TPM_HANDLE) { } +} + +/// This command is used to start an authorization session using alternative methods of +/// establishing the session key (sessionKey). The session key is then used to derive +/// values used for authorization and for encrypting parameters. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_StartAuthSession_REQUEST { + /// Handle of a loaded decrypt key used to encrypt salt + /// may be TPM_RH_NULL + /// Auth Index: None + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub tpmKey: TPM_HANDLE, + + /// Entity providing the authValue + /// may be TPM_RH_NULL + /// Auth Index: None + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub bind: TPM_HANDLE, + + /// Initial nonceCaller, sets nonceTPM size for the session + /// shall be at least 16 octets + pub nonceCaller: Vec, + + /// Value encrypted according to the type of tpmKey + /// If tpmKey is TPM_RH_NULL, this shall be the Empty Buffer. + pub encryptedSalt: Vec, + + /// Indicates the type of the session; simple HMAC or policy (including a trial policy) + pub sessionType: TPM_SE, + + /// The algorithm and key size for parameter encryption + /// may select TPM_ALG_NULL + pub symmetric: TPMT_SYM_DEF, + + /// Hash algorithm to use for the session + /// Shall be a hash algorithm supported by the TPM and not TPM_ALG_NULL + #[derivative(Default(value="TPM_ALG_ID::NULL"))] + pub authHash: TPM_ALG_ID, +} + +impl TPM2_StartAuthSession_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + tpmKey: &TPM_HANDLE, + bind: &TPM_HANDLE, + nonceCaller: &Vec, + encryptedSalt: &Vec, + sessionType: TPM_SE, + symmetric: &TPMT_SYM_DEF, + authHash: TPM_ALG_ID, + ) -> Self { + Self { + tpmKey: tpmKey.clone(), + bind: bind.clone(), + nonceCaller: nonceCaller.clone(), + encryptedSalt: encryptedSalt.clone(), + sessionType: sessionType.clone(), + symmetric: symmetric.clone(), + authHash: authHash.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_StartAuthSession_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.nonceCaller, 2); + buf.writeSizedByteBuf(&self.encryptedSalt, 2); + buf.writeByte(self.sessionType.into()); + self.symmetric.toTpm(buf)?; + buf.writeShort(self.authHash.into()); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.nonceCaller = buf.readSizedByteBuf(2); + self.encryptedSalt = buf.readSizedByteBuf(2); + self.sessionType = TPM_SE(buf.readByte() as u8); + self.symmetric.initFromTpm(buf)?; + self.authHash = TPM_ALG_ID(buf.readShort() as u16); + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_StartAuthSession_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_StartAuthSession_REQUEST { + fn num_handles(&self) -> u16 { 2 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 2, val_len: 1 } } +} + +impl ReqStructure for TPM2_StartAuthSession_REQUEST { + fn num_auth_handles(&self) -> u16 { 0 } + + fn get_handles(&self) -> Vec { vec![self.tpmKey.clone(), self.bind.clone()] } +} + +/// This command is used to start an authorization session using alternative methods of +/// establishing the session key (sessionKey). The session key is then used to derive +/// values used for authorization and for encrypting parameters. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct StartAuthSessionResponse { + /// Handle for the newly created session + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub handle: TPM_HANDLE, + + /// The initial nonce from the TPM, used in the computation of the sessionKey + pub nonceTPM: Vec, +} + +impl StartAuthSessionResponse { +} + +impl TpmStructure for StartAuthSessionResponse { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.nonceTPM, 2); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.nonceTPM = buf.readSizedByteBuf(2); + Ok(()) + } + +} + +impl TpmMarshaller for StartAuthSessionResponse { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for StartAuthSessionResponse { + fn num_handles(&self) -> u16 { 1 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 2, val_len: 1 } } +} + +impl RespStructure for StartAuthSessionResponse { + fn get_handle(&self) -> TPM_HANDLE { self.handle.clone() } + + fn set_handle(&mut self, handle: &TPM_HANDLE) { self.handle = handle.clone(); } +} + +/// This command allows a policy authorization session to be returned to its initial +/// state. This command is used after the TPM returns TPM_RC_PCR_CHANGED. That response +/// code indicates that a policy will fail because the PCR have changed after +/// TPM2_PolicyPCR() was executed. Restarting the session allows the authorizations to be +/// replayed because the session restarts with the same nonceTPM. If the PCR are valid for +/// the policy, the policy may then succeed. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_PolicyRestart_REQUEST { + /// The handle for the policy session + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub sessionHandle: TPM_HANDLE, +} + +impl TPM2_PolicyRestart_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + sessionHandle: &TPM_HANDLE, + ) -> Self { + Self { + sessionHandle: sessionHandle.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_PolicyRestart_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_PolicyRestart_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_PolicyRestart_REQUEST { + fn num_handles(&self) -> u16 { 1 } + +} + +impl ReqStructure for TPM2_PolicyRestart_REQUEST { + fn num_auth_handles(&self) -> u16 { 0 } + + fn get_handles(&self) -> Vec { vec![self.sessionHandle.clone()] } +} + +/// This command is used to create an object that can be loaded into a TPM using +/// TPM2_Load(). If the command completes successfully, the TPM will create the new object +/// and return the objects creation data (creationData), its public area (outPublic), and +/// its encrypted sensitive area (outPrivate). Preservation of the returned data is the +/// responsibility of the caller. The object will need to be loaded (TPM2_Load()) before +/// it may be used. The only difference between the inPublic TPMT_PUBLIC template and the +/// outPublic TPMT_PUBLIC object is in the unique field. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_Create_REQUEST { + /// Handle of parent for new object + /// Auth Index: 1 + /// Auth Role: USER + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub parentHandle: TPM_HANDLE, + + /// The sensitive data + pub inSensitive: TPMS_SENSITIVE_CREATE, + + /// The public template + pub inPublic: TPMT_PUBLIC, + + /// Data that will be included in the creation data for this object to provide permanent, + /// verifiable linkage between this object and some object owner data + pub outsideInfo: Vec, + + /// PCR that will be used in creation data + pub creationPCR: Vec, +} + +impl TPM2_Create_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + parentHandle: &TPM_HANDLE, + inSensitive: &TPMS_SENSITIVE_CREATE, + inPublic: &TPMT_PUBLIC, + outsideInfo: &Vec, + creationPCR: &Vec, + ) -> Self { + Self { + parentHandle: parentHandle.clone(), + inSensitive: inSensitive.clone(), + inPublic: inPublic.clone(), + outsideInfo: outsideInfo.clone(), + creationPCR: creationPCR.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_Create_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedObj(&self.inSensitive)?; + buf.writeSizedObj(&self.inPublic)?; + buf.writeSizedByteBuf(&self.outsideInfo, 2); + buf.writeObjArr(self.creationPCR.as_ref())?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + buf.readSizedObj(&mut self.inSensitive)?; + buf.readSizedObj(&mut self.inPublic)?; + self.outsideInfo = buf.readSizedByteBuf(2); + buf.readObjArr(self.creationPCR.as_mut())?; + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_Create_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_Create_REQUEST { + fn num_handles(&self) -> u16 { 1 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 2, val_len: 1 } } +} + +impl ReqStructure for TPM2_Create_REQUEST { + fn num_auth_handles(&self) -> u16 { 1 } + + fn get_handles(&self) -> Vec { vec![self.parentHandle.clone()] } +} + +/// This command is used to create an object that can be loaded into a TPM using +/// TPM2_Load(). If the command completes successfully, the TPM will create the new object +/// and return the objects creation data (creationData), its public area (outPublic), and +/// its encrypted sensitive area (outPrivate). Preservation of the returned data is the +/// responsibility of the caller. The object will need to be loaded (TPM2_Load()) before +/// it may be used. The only difference between the inPublic TPMT_PUBLIC template and the +/// outPublic TPMT_PUBLIC object is in the unique field. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct CreateResponse { + /// The private portion of the object + pub outPrivate: TPM2B_PRIVATE, + + /// The public portion of the created object + pub outPublic: TPMT_PUBLIC, + + /// Contains a TPMS_CREATION_DATA + pub creationData: TPMS_CREATION_DATA, + + /// Digest of creationData using nameAlg of outPublic + pub creationHash: Vec, + + /// Ticket used by TPM2_CertifyCreation() to validate that the creation data was produced + /// by the TPM + pub creationTicket: TPMT_TK_CREATION, +} + +impl CreateResponse { +} + +impl TpmStructure for CreateResponse { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + self.outPrivate.toTpm(buf)?; + buf.writeSizedObj(&self.outPublic)?; + buf.writeSizedObj(&self.creationData)?; + buf.writeSizedByteBuf(&self.creationHash, 2); + self.creationTicket.toTpm(buf)?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.outPrivate.initFromTpm(buf)?; + buf.readSizedObj(&mut self.outPublic)?; + buf.readSizedObj(&mut self.creationData)?; + self.creationHash = buf.readSizedByteBuf(2); + self.creationTicket.initFromTpm(buf)?; + Ok(()) + } + +} + +impl TpmMarshaller for CreateResponse { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for CreateResponse { + fn num_handles(&self) -> u16 { 0 } + +} + +impl RespStructure for CreateResponse { + fn get_handle(&self) -> TPM_HANDLE { TPM_HANDLE::default() } + + fn set_handle(&mut self, _handle: &TPM_HANDLE) { } +} + +/// This command is used to load objects into the TPM. This command is used when both a +/// TPM2B_PUBLIC and TPM2B_PRIVATE are to be loaded. If only a TPM2B_PUBLIC is to be +/// loaded, the TPM2_LoadExternal command is used. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_Load_REQUEST { + /// TPM handle of parent key; shall not be a reserved handle + /// Auth Index: 1 + /// Auth Role: USER + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub parentHandle: TPM_HANDLE, + + /// The private portion of the object + pub inPrivate: TPM2B_PRIVATE, + + /// The public portion of the object + pub inPublic: TPMT_PUBLIC, +} + +impl TPM2_Load_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + parentHandle: &TPM_HANDLE, + inPrivate: &TPM2B_PRIVATE, + inPublic: &TPMT_PUBLIC, + ) -> Self { + Self { + parentHandle: parentHandle.clone(), + inPrivate: inPrivate.clone(), + inPublic: inPublic.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_Load_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + self.inPrivate.toTpm(buf)?; + buf.writeSizedObj(&self.inPublic)?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.inPrivate.initFromTpm(buf)?; + buf.readSizedObj(&mut self.inPublic)?; + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_Load_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_Load_REQUEST { + fn num_handles(&self) -> u16 { 1 } + +} + +impl ReqStructure for TPM2_Load_REQUEST { + fn num_auth_handles(&self) -> u16 { 1 } + + fn get_handles(&self) -> Vec { vec![self.parentHandle.clone()] } +} + +/// This command is used to load objects into the TPM. This command is used when both a +/// TPM2B_PUBLIC and TPM2B_PRIVATE are to be loaded. If only a TPM2B_PUBLIC is to be +/// loaded, the TPM2_LoadExternal command is used. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct LoadResponse { + /// Handle of type TPM_HT_TRANSIENT for the loaded object + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub handle: TPM_HANDLE, + + /// Name of the loaded object + pub name: Vec, +} + +impl LoadResponse { +} + +impl TpmStructure for LoadResponse { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.name, 2); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.name = buf.readSizedByteBuf(2); + Ok(()) + } + +} + +impl TpmMarshaller for LoadResponse { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for LoadResponse { + fn num_handles(&self) -> u16 { 1 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 2, val_len: 1 } } +} + +impl RespStructure for LoadResponse { + fn get_handle(&self) -> TPM_HANDLE { self.handle.clone() } + + fn set_handle(&mut self, handle: &TPM_HANDLE) { self.handle = handle.clone(); } + + fn get_resp_name(&self) -> Vec { self.name.clone() } +} + +/// This command is used to load an object that is not a Protected Object into the TPM. +/// The command allows loading of a public area or both a public and sensitive area. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_LoadExternal_REQUEST { + /// The sensitive portion of the object (optional) + pub inPrivate: TPMT_SENSITIVE, + + /// The public portion of the object + pub inPublic: TPMT_PUBLIC, + + /// Hierarchy with which the object area is associated + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub hierarchy: TPM_HANDLE, +} + +impl TPM2_LoadExternal_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + inPrivate: &TPMT_SENSITIVE, + inPublic: &TPMT_PUBLIC, + hierarchy: &TPM_HANDLE, + ) -> Self { + Self { + inPrivate: inPrivate.clone(), + inPublic: inPublic.clone(), + hierarchy: hierarchy.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_LoadExternal_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedObj(&self.inPrivate)?; + buf.writeSizedObj(&self.inPublic)?; + self.hierarchy.toTpm(buf)?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + buf.readSizedObj(&mut self.inPrivate)?; + buf.readSizedObj(&mut self.inPublic)?; + self.hierarchy.initFromTpm(buf)?; + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_LoadExternal_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_LoadExternal_REQUEST { + fn num_handles(&self) -> u16 { 0 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 2, val_len: 1 } } +} + +impl ReqStructure for TPM2_LoadExternal_REQUEST { + fn num_auth_handles(&self) -> u16 { 0 } + + fn get_handles(&self) -> Vec { vec![] } +} + +/// This command is used to load an object that is not a Protected Object into the TPM. +/// The command allows loading of a public area or both a public and sensitive area. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct LoadExternalResponse { + /// Handle of type TPM_HT_TRANSIENT for the loaded object + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub handle: TPM_HANDLE, + + /// Name of the loaded object + pub name: Vec, +} + +impl LoadExternalResponse { +} + +impl TpmStructure for LoadExternalResponse { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.name, 2); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.name = buf.readSizedByteBuf(2); + Ok(()) + } + +} + +impl TpmMarshaller for LoadExternalResponse { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for LoadExternalResponse { + fn num_handles(&self) -> u16 { 1 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 2, val_len: 1 } } +} + +impl RespStructure for LoadExternalResponse { + fn get_handle(&self) -> TPM_HANDLE { self.handle.clone() } + + fn set_handle(&mut self, handle: &TPM_HANDLE) { self.handle = handle.clone(); } + + fn get_resp_name(&self) -> Vec { self.name.clone() } +} + +/// This command allows access to the public area of a loaded object. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_ReadPublic_REQUEST { + /// TPM handle of an object + /// Auth Index: None + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub objectHandle: TPM_HANDLE, +} + +impl TPM2_ReadPublic_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + objectHandle: &TPM_HANDLE, + ) -> Self { + Self { + objectHandle: objectHandle.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_ReadPublic_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_ReadPublic_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_ReadPublic_REQUEST { + fn num_handles(&self) -> u16 { 1 } + +} + +impl ReqStructure for TPM2_ReadPublic_REQUEST { + fn num_auth_handles(&self) -> u16 { 0 } + + fn get_handles(&self) -> Vec { vec![self.objectHandle.clone()] } +} + +/// This command allows access to the public area of a loaded object. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct ReadPublicResponse { + /// Structure containing the public area of an object + pub outPublic: TPMT_PUBLIC, + + /// Name of the object + pub name: Vec, + + /// The Qualified Name of the object + pub qualifiedName: Vec, +} + +impl ReadPublicResponse { +} + +impl TpmStructure for ReadPublicResponse { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedObj(&self.outPublic)?; + buf.writeSizedByteBuf(&self.name, 2); + buf.writeSizedByteBuf(&self.qualifiedName, 2); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + buf.readSizedObj(&mut self.outPublic)?; + self.name = buf.readSizedByteBuf(2); + self.qualifiedName = buf.readSizedByteBuf(2); + Ok(()) + } + +} + +impl TpmMarshaller for ReadPublicResponse { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for ReadPublicResponse { + fn num_handles(&self) -> u16 { 0 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 2, val_len: 1 } } +} + +impl RespStructure for ReadPublicResponse { + fn get_handle(&self) -> TPM_HANDLE { TPM_HANDLE::default() } + + fn set_handle(&mut self, _handle: &TPM_HANDLE) { } + + fn get_resp_name(&self) -> Vec { self.name.clone() } +} + +/// This command enables the association of a credential with an object in a way that +/// ensures that the TPM has validated the parameters of the credentialed object. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_ActivateCredential_REQUEST { + /// Handle of the object associated with certificate in credentialBlob + /// Auth Index: 1 + /// Auth Role: ADMIN + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub activateHandle: TPM_HANDLE, + + /// Loaded key used to decrypt the TPMS_SENSITIVE in credentialBlob + /// Auth Index: 2 + /// Auth Role: USER + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub keyHandle: TPM_HANDLE, + + /// The credential + pub credentialBlob: TPMS_ID_OBJECT, + + /// KeyHandle algorithm-dependent encrypted seed that protects credentialBlob + pub secret: Vec, +} + +impl TPM2_ActivateCredential_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + activateHandle: &TPM_HANDLE, + keyHandle: &TPM_HANDLE, + credentialBlob: &TPMS_ID_OBJECT, + secret: &Vec, + ) -> Self { + Self { + activateHandle: activateHandle.clone(), + keyHandle: keyHandle.clone(), + credentialBlob: credentialBlob.clone(), + secret: secret.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_ActivateCredential_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedObj(&self.credentialBlob)?; + buf.writeSizedByteBuf(&self.secret, 2); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + buf.readSizedObj(&mut self.credentialBlob)?; + self.secret = buf.readSizedByteBuf(2); + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_ActivateCredential_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_ActivateCredential_REQUEST { + fn num_handles(&self) -> u16 { 2 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 2, val_len: 1 } } +} + +impl ReqStructure for TPM2_ActivateCredential_REQUEST { + fn num_auth_handles(&self) -> u16 { 2 } + + fn get_handles(&self) -> Vec { vec![self.activateHandle.clone(), self.keyHandle.clone()] } +} + +/// This command enables the association of a credential with an object in a way that +/// ensures that the TPM has validated the parameters of the credentialed object. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct ActivateCredentialResponse { + /// The decrypted certificate information + /// the data should be no larger than the size of the digest of the nameAlg associated + /// with keyHandle + pub certInfo: Vec, +} + +impl ActivateCredentialResponse { +} + +impl TpmStructure for ActivateCredentialResponse { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.certInfo, 2); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.certInfo = buf.readSizedByteBuf(2); + Ok(()) + } + +} + +impl TpmMarshaller for ActivateCredentialResponse { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for ActivateCredentialResponse { + fn num_handles(&self) -> u16 { 0 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 2, val_len: 1 } } +} + +impl RespStructure for ActivateCredentialResponse { + fn get_handle(&self) -> TPM_HANDLE { TPM_HANDLE::default() } + + fn set_handle(&mut self, _handle: &TPM_HANDLE) { } +} + +/// This command allows the TPM to perform the actions required of a Certificate Authority +/// (CA) in creating a TPM2B_ID_OBJECT containing an activation credential. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_MakeCredential_REQUEST { + /// Loaded public area, used to encrypt the sensitive area containing the credential key + /// Auth Index: None + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub handle: TPM_HANDLE, + + /// The credential information + pub credential: Vec, + + /// Name of the object to which the credential applies + pub objectName: Vec, +} + +impl TPM2_MakeCredential_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + handle: &TPM_HANDLE, + credential: &Vec, + objectName: &Vec, + ) -> Self { + Self { + handle: handle.clone(), + credential: credential.clone(), + objectName: objectName.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_MakeCredential_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.credential, 2); + buf.writeSizedByteBuf(&self.objectName, 2); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.credential = buf.readSizedByteBuf(2); + self.objectName = buf.readSizedByteBuf(2); + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_MakeCredential_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_MakeCredential_REQUEST { + fn num_handles(&self) -> u16 { 1 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 2, val_len: 1 } } +} + +impl ReqStructure for TPM2_MakeCredential_REQUEST { + fn num_auth_handles(&self) -> u16 { 0 } + + fn get_handles(&self) -> Vec { vec![self.handle.clone()] } +} + +/// This command allows the TPM to perform the actions required of a Certificate Authority +/// (CA) in creating a TPM2B_ID_OBJECT containing an activation credential. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct MakeCredentialResponse { + /// The credential + pub credentialBlob: TPMS_ID_OBJECT, + + /// Handle algorithm-dependent data that wraps the key that encrypts credentialBlob + pub secret: Vec, +} + +impl MakeCredentialResponse { +} + +impl TpmStructure for MakeCredentialResponse { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedObj(&self.credentialBlob)?; + buf.writeSizedByteBuf(&self.secret, 2); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + buf.readSizedObj(&mut self.credentialBlob)?; + self.secret = buf.readSizedByteBuf(2); + Ok(()) + } + +} + +impl TpmMarshaller for MakeCredentialResponse { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for MakeCredentialResponse { + fn num_handles(&self) -> u16 { 0 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 2, val_len: 1 } } +} + +impl RespStructure for MakeCredentialResponse { + fn get_handle(&self) -> TPM_HANDLE { TPM_HANDLE::default() } + + fn set_handle(&mut self, _handle: &TPM_HANDLE) { } +} + +/// This command returns the data in a loaded Sealed Data Object. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_Unseal_REQUEST { + /// Handle of a loaded data object + /// Auth Index: 1 + /// Auth Role: USER + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub itemHandle: TPM_HANDLE, +} + +impl TPM2_Unseal_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + itemHandle: &TPM_HANDLE, + ) -> Self { + Self { + itemHandle: itemHandle.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_Unseal_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_Unseal_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_Unseal_REQUEST { + fn num_handles(&self) -> u16 { 1 } + +} + +impl ReqStructure for TPM2_Unseal_REQUEST { + fn num_auth_handles(&self) -> u16 { 1 } + + fn get_handles(&self) -> Vec { vec![self.itemHandle.clone()] } +} + +/// This command returns the data in a loaded Sealed Data Object. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct UnsealResponse { + /// Unsealed data + /// Size of outData is limited to be no more than 128 octets. + pub outData: Vec, +} + +impl UnsealResponse { +} + +impl TpmStructure for UnsealResponse { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.outData, 2); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.outData = buf.readSizedByteBuf(2); + Ok(()) + } + +} + +impl TpmMarshaller for UnsealResponse { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for UnsealResponse { + fn num_handles(&self) -> u16 { 0 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 2, val_len: 1 } } +} + +impl RespStructure for UnsealResponse { + fn get_handle(&self) -> TPM_HANDLE { TPM_HANDLE::default() } + + fn set_handle(&mut self, _handle: &TPM_HANDLE) { } +} + +/// This command is used to change the authorization secret for a TPM-resident object. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_ObjectChangeAuth_REQUEST { + /// Handle of the object + /// Auth Index: 1 + /// Auth Role: ADMIN + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub objectHandle: TPM_HANDLE, + + /// Handle of the parent + /// Auth Index: None + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub parentHandle: TPM_HANDLE, + + /// New authorization value + pub newAuth: Vec, +} + +impl TPM2_ObjectChangeAuth_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + objectHandle: &TPM_HANDLE, + parentHandle: &TPM_HANDLE, + newAuth: &Vec, + ) -> Self { + Self { + objectHandle: objectHandle.clone(), + parentHandle: parentHandle.clone(), + newAuth: newAuth.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_ObjectChangeAuth_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.newAuth, 2); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.newAuth = buf.readSizedByteBuf(2); + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_ObjectChangeAuth_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_ObjectChangeAuth_REQUEST { + fn num_handles(&self) -> u16 { 2 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 2, val_len: 1 } } +} + +impl ReqStructure for TPM2_ObjectChangeAuth_REQUEST { + fn num_auth_handles(&self) -> u16 { 1 } + + fn get_handles(&self) -> Vec { vec![self.objectHandle.clone(), self.parentHandle.clone()] } +} + +/// This command is used to change the authorization secret for a TPM-resident object. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct ObjectChangeAuthResponse { + /// Private area containing the new authorization value + pub outPrivate: TPM2B_PRIVATE, +} + +impl ObjectChangeAuthResponse { +} + +impl TpmStructure for ObjectChangeAuthResponse { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + self.outPrivate.toTpm(buf)?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.outPrivate.initFromTpm(buf)?; + Ok(()) + } + +} + +impl TpmMarshaller for ObjectChangeAuthResponse { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for ObjectChangeAuthResponse { + fn num_handles(&self) -> u16 { 0 } + +} + +impl RespStructure for ObjectChangeAuthResponse { + fn get_handle(&self) -> TPM_HANDLE { TPM_HANDLE::default() } + + fn set_handle(&mut self, _handle: &TPM_HANDLE) { } +} + +/// This command creates an object and loads it in the TPM. This command allows creation +/// of any type of object (Primary, Ordinary, or Derived) depending on the type of +/// parentHandle. If parentHandle references a Primary Seed, then a Primary Object is +/// created; if parentHandle references a Storage Parent, then an Ordinary Object is +/// created; and if parentHandle references a Derivation Parent, then a Derived Object is generated. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_CreateLoaded_REQUEST { + /// Handle of a transient storage key, a persistent storage key, TPM_RH_ENDORSEMENT, + /// TPM_RH_OWNER, TPM_RH_PLATFORM+{PP}, or TPM_RH_NULL + /// Auth Index: 1 + /// Auth Role: USER + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub parentHandle: TPM_HANDLE, + + /// The sensitive data, see TPM 2.0 Part 1 Sensitive Values + pub inSensitive: TPMS_SENSITIVE_CREATE, + + /// The public template + pub inPublic: Vec, +} + +impl TPM2_CreateLoaded_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + parentHandle: &TPM_HANDLE, + inSensitive: &TPMS_SENSITIVE_CREATE, + inPublic: &Vec, + ) -> Self { + Self { + parentHandle: parentHandle.clone(), + inSensitive: inSensitive.clone(), + inPublic: inPublic.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_CreateLoaded_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedObj(&self.inSensitive)?; + buf.writeSizedByteBuf(&self.inPublic, 2); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + buf.readSizedObj(&mut self.inSensitive)?; + self.inPublic = buf.readSizedByteBuf(2); + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_CreateLoaded_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_CreateLoaded_REQUEST { + fn num_handles(&self) -> u16 { 1 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 2, val_len: 1 } } +} + +impl ReqStructure for TPM2_CreateLoaded_REQUEST { + fn num_auth_handles(&self) -> u16 { 1 } + + fn get_handles(&self) -> Vec { vec![self.parentHandle.clone()] } +} + +/// This command creates an object and loads it in the TPM. This command allows creation +/// of any type of object (Primary, Ordinary, or Derived) depending on the type of +/// parentHandle. If parentHandle references a Primary Seed, then a Primary Object is +/// created; if parentHandle references a Storage Parent, then an Ordinary Object is +/// created; and if parentHandle references a Derivation Parent, then a Derived Object is generated. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct CreateLoadedResponse { + /// Handle of type TPM_HT_TRANSIENT for created object + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub handle: TPM_HANDLE, + + /// The sensitive area of the object (optional) + pub outPrivate: TPM2B_PRIVATE, + + /// The public portion of the created object + pub outPublic: TPMT_PUBLIC, + + /// The name of the created object + pub name: Vec, +} + +impl CreateLoadedResponse { +} + +impl TpmStructure for CreateLoadedResponse { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + self.outPrivate.toTpm(buf)?; + buf.writeSizedObj(&self.outPublic)?; + buf.writeSizedByteBuf(&self.name, 2); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.outPrivate.initFromTpm(buf)?; + buf.readSizedObj(&mut self.outPublic)?; + self.name = buf.readSizedByteBuf(2); + Ok(()) + } + +} + +impl TpmMarshaller for CreateLoadedResponse { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for CreateLoadedResponse { + fn num_handles(&self) -> u16 { 1 } + +} + +impl RespStructure for CreateLoadedResponse { + fn get_handle(&self) -> TPM_HANDLE { self.handle.clone() } + + fn set_handle(&mut self, handle: &TPM_HANDLE) { self.handle = handle.clone(); } + + fn get_resp_name(&self) -> Vec { self.name.clone() } +} + +/// This command duplicates a loaded object so that it may be used in a different +/// hierarchy. The new parent key for the duplicate may be on the same or different TPM or +/// TPM_RH_NULL. Only the public area of newParentHandle is required to be loaded. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_Duplicate_REQUEST { + /// Loaded object to duplicate + /// Auth Index: 1 + /// Auth Role: DUP + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub objectHandle: TPM_HANDLE, + + /// Shall reference the public area of an asymmetric key + /// Auth Index: None + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub newParentHandle: TPM_HANDLE, + + /// Optional symmetric encryption key + /// The size for this key is set to zero when the TPM is to generate the key. This + /// parameter may be encrypted. + pub encryptionKeyIn: Vec, + + /// Definition for the symmetric algorithm to be used for the inner wrapper + /// may be TPM_ALG_NULL if no inner wrapper is applied + pub symmetricAlg: TPMT_SYM_DEF_OBJECT, +} + +impl TPM2_Duplicate_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + objectHandle: &TPM_HANDLE, + newParentHandle: &TPM_HANDLE, + encryptionKeyIn: &Vec, + symmetricAlg: &TPMT_SYM_DEF_OBJECT, + ) -> Self { + Self { + objectHandle: objectHandle.clone(), + newParentHandle: newParentHandle.clone(), + encryptionKeyIn: encryptionKeyIn.clone(), + symmetricAlg: symmetricAlg.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_Duplicate_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.encryptionKeyIn, 2); + self.symmetricAlg.toTpm(buf)?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.encryptionKeyIn = buf.readSizedByteBuf(2); + self.symmetricAlg.initFromTpm(buf)?; + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_Duplicate_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_Duplicate_REQUEST { + fn num_handles(&self) -> u16 { 2 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 2, val_len: 1 } } +} + +impl ReqStructure for TPM2_Duplicate_REQUEST { + fn num_auth_handles(&self) -> u16 { 1 } + + fn get_handles(&self) -> Vec { vec![self.objectHandle.clone(), self.newParentHandle.clone()] } +} + +/// This command duplicates a loaded object so that it may be used in a different +/// hierarchy. The new parent key for the duplicate may be on the same or different TPM or +/// TPM_RH_NULL. Only the public area of newParentHandle is required to be loaded. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct DuplicateResponse { + /// If the caller provided an encryption key or if symmetricAlg was TPM_ALG_NULL, then + /// this will be the Empty Buffer; otherwise, it shall contain the TPM-generated, + /// symmetric encryption key for the inner wrapper. + pub encryptionKeyOut: Vec, + + /// Private area that may be encrypted by encryptionKeyIn; and may be doubly encrypted + pub duplicate: TPM2B_PRIVATE, + + /// Seed protected by the asymmetric algorithms of new parent (NP) + pub outSymSeed: Vec, +} + +impl DuplicateResponse { +} + +impl TpmStructure for DuplicateResponse { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.encryptionKeyOut, 2); + self.duplicate.toTpm(buf)?; + buf.writeSizedByteBuf(&self.outSymSeed, 2); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.encryptionKeyOut = buf.readSizedByteBuf(2); + self.duplicate.initFromTpm(buf)?; + self.outSymSeed = buf.readSizedByteBuf(2); + Ok(()) + } + +} + +impl TpmMarshaller for DuplicateResponse { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for DuplicateResponse { + fn num_handles(&self) -> u16 { 0 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 2, val_len: 1 } } +} + +impl RespStructure for DuplicateResponse { + fn get_handle(&self) -> TPM_HANDLE { TPM_HANDLE::default() } + + fn set_handle(&mut self, _handle: &TPM_HANDLE) { } +} + +/// This command allows the TPM to serve in the role as a Duplication Authority. If proper +/// authorization for use of the oldParent is provided, then an HMAC key and a symmetric +/// key are recovered from inSymSeed and used to integrity check and decrypt inDuplicate. +/// A new protection seed value is generated according to the methods appropriate for +/// newParent and the blob is re-encrypted and a new integrity value is computed. The +/// re-encrypted blob is returned in outDuplicate and the symmetric key returned in outSymKey. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_Rewrap_REQUEST { + /// Parent of object + /// Auth Index: 1 + /// Auth Role: User + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub oldParent: TPM_HANDLE, + + /// New parent of the object + /// Auth Index: None + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub newParent: TPM_HANDLE, + + /// An object encrypted using symmetric key derived from inSymSeed + pub inDuplicate: TPM2B_PRIVATE, + + /// The Name of the object being rewrapped + pub name: Vec, + + /// The seed for the symmetric key and HMAC key + /// needs oldParent private key to recover the seed and generate the symmetric key + pub inSymSeed: Vec, +} + +impl TPM2_Rewrap_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + oldParent: &TPM_HANDLE, + newParent: &TPM_HANDLE, + inDuplicate: &TPM2B_PRIVATE, + name: &Vec, + inSymSeed: &Vec, + ) -> Self { + Self { + oldParent: oldParent.clone(), + newParent: newParent.clone(), + inDuplicate: inDuplicate.clone(), + name: name.clone(), + inSymSeed: inSymSeed.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_Rewrap_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + self.inDuplicate.toTpm(buf)?; + buf.writeSizedByteBuf(&self.name, 2); + buf.writeSizedByteBuf(&self.inSymSeed, 2); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.inDuplicate.initFromTpm(buf)?; + self.name = buf.readSizedByteBuf(2); + self.inSymSeed = buf.readSizedByteBuf(2); + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_Rewrap_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_Rewrap_REQUEST { + fn num_handles(&self) -> u16 { 2 } + +} + +impl ReqStructure for TPM2_Rewrap_REQUEST { + fn num_auth_handles(&self) -> u16 { 1 } + + fn get_handles(&self) -> Vec { vec![self.oldParent.clone(), self.newParent.clone()] } +} + +/// This command allows the TPM to serve in the role as a Duplication Authority. If proper +/// authorization for use of the oldParent is provided, then an HMAC key and a symmetric +/// key are recovered from inSymSeed and used to integrity check and decrypt inDuplicate. +/// A new protection seed value is generated according to the methods appropriate for +/// newParent and the blob is re-encrypted and a new integrity value is computed. The +/// re-encrypted blob is returned in outDuplicate and the symmetric key returned in outSymKey. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct RewrapResponse { + /// An object encrypted using symmetric key derived from outSymSeed + pub outDuplicate: TPM2B_PRIVATE, + + /// Seed for a symmetric key protected by newParent asymmetric key + pub outSymSeed: Vec, +} + +impl RewrapResponse { +} + +impl TpmStructure for RewrapResponse { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + self.outDuplicate.toTpm(buf)?; + buf.writeSizedByteBuf(&self.outSymSeed, 2); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.outDuplicate.initFromTpm(buf)?; + self.outSymSeed = buf.readSizedByteBuf(2); + Ok(()) + } + +} + +impl TpmMarshaller for RewrapResponse { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for RewrapResponse { + fn num_handles(&self) -> u16 { 0 } + +} + +impl RespStructure for RewrapResponse { + fn get_handle(&self) -> TPM_HANDLE { TPM_HANDLE::default() } + + fn set_handle(&mut self, _handle: &TPM_HANDLE) { } +} + +/// This command allows an object to be encrypted using the symmetric encryption values of +/// a Storage Key. After encryption, the object may be loaded and used in the new +/// hierarchy. The imported object (duplicate) may be singly encrypted, multiply +/// encrypted, or unencrypted. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_Import_REQUEST { + /// The handle of the new parent for the object + /// Auth Index: 1 + /// Auth Role: USER + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub parentHandle: TPM_HANDLE, + + /// The optional symmetric encryption key used as the inner wrapper for duplicate + /// If symmetricAlg is TPM_ALG_NULL, then this parameter shall be the Empty Buffer. + pub encryptionKey: Vec, + + /// The public area of the object to be imported + /// This is provided so that the integrity value for duplicate and the object attributes + /// can be checked. + /// NOTE Even if the integrity value of the object is not checked on input, the object + /// Name is required to create the integrity value for the imported object. + pub objectPublic: TPMT_PUBLIC, + + /// The symmetrically encrypted duplicate object that may contain an inner symmetric wrapper + pub duplicate: TPM2B_PRIVATE, + + /// The seed for the symmetric key and HMAC key + /// inSymSeed is encrypted/encoded using the algorithms of newParent. + pub inSymSeed: Vec, + + /// Definition for the symmetric algorithm to use for the inner wrapper + /// If this algorithm is TPM_ALG_NULL, no inner wrapper is present and encryptionKey shall + /// be the Empty Buffer. + pub symmetricAlg: TPMT_SYM_DEF_OBJECT, +} + +impl TPM2_Import_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + parentHandle: &TPM_HANDLE, + encryptionKey: &Vec, + objectPublic: &TPMT_PUBLIC, + duplicate: &TPM2B_PRIVATE, + inSymSeed: &Vec, + symmetricAlg: &TPMT_SYM_DEF_OBJECT, + ) -> Self { + Self { + parentHandle: parentHandle.clone(), + encryptionKey: encryptionKey.clone(), + objectPublic: objectPublic.clone(), + duplicate: duplicate.clone(), + inSymSeed: inSymSeed.clone(), + symmetricAlg: symmetricAlg.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_Import_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.encryptionKey, 2); + buf.writeSizedObj(&self.objectPublic)?; + self.duplicate.toTpm(buf)?; + buf.writeSizedByteBuf(&self.inSymSeed, 2); + self.symmetricAlg.toTpm(buf)?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.encryptionKey = buf.readSizedByteBuf(2); + buf.readSizedObj(&mut self.objectPublic)?; + self.duplicate.initFromTpm(buf)?; + self.inSymSeed = buf.readSizedByteBuf(2); + self.symmetricAlg.initFromTpm(buf)?; + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_Import_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_Import_REQUEST { + fn num_handles(&self) -> u16 { 1 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 2, val_len: 1 } } +} + +impl ReqStructure for TPM2_Import_REQUEST { + fn num_auth_handles(&self) -> u16 { 1 } + + fn get_handles(&self) -> Vec { vec![self.parentHandle.clone()] } +} + +/// This command allows an object to be encrypted using the symmetric encryption values of +/// a Storage Key. After encryption, the object may be loaded and used in the new +/// hierarchy. The imported object (duplicate) may be singly encrypted, multiply +/// encrypted, or unencrypted. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct ImportResponse { + /// The sensitive area encrypted with the symmetric key of parentHandle + pub outPrivate: TPM2B_PRIVATE, +} + +impl ImportResponse { +} + +impl TpmStructure for ImportResponse { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + self.outPrivate.toTpm(buf)?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.outPrivate.initFromTpm(buf)?; + Ok(()) + } + +} + +impl TpmMarshaller for ImportResponse { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for ImportResponse { + fn num_handles(&self) -> u16 { 0 } + +} + +impl RespStructure for ImportResponse { + fn get_handle(&self) -> TPM_HANDLE { TPM_HANDLE::default() } + + fn set_handle(&mut self, _handle: &TPM_HANDLE) { } +} + +/// This command performs RSA encryption using the indicated padding scheme according to +/// IETF RFC 8017. If the scheme of keyHandle is TPM_ALG_NULL, then the caller may use +/// inScheme to specify the padding scheme. If scheme of keyHandle is not TPM_ALG_NULL, +/// then inScheme shall either be TPM_ALG_NULL or be the same as scheme (TPM_RC_SCHEME). +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_RSA_Encrypt_REQUEST { + /// Reference to public portion of RSA key to use for encryption + /// Auth Index: None + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub keyHandle: TPM_HANDLE, + + /// Message to be encrypted + /// NOTE 1 The data type was chosen because it limits the overall size of the input to no + /// greater than the size of the largest RSA public key. This may be larger than allowed + /// for keyHandle. + pub message: Vec, + + /// Scheme selector + + /// The padding scheme to use if scheme associated with keyHandle is TPM_ALG_NULL + /// One of: TPMS_KEY_SCHEME_ECDH, TPMS_KEY_SCHEME_ECMQV, TPMS_SIG_SCHEME_RSASSA, + /// TPMS_SIG_SCHEME_RSAPSS, TPMS_SIG_SCHEME_ECDSA, TPMS_SIG_SCHEME_ECDAA, + /// TPMS_SIG_SCHEME_SM2, TPMS_SIG_SCHEME_ECSCHNORR, TPMS_ENC_SCHEME_RSAES, + /// TPMS_ENC_SCHEME_OAEP, TPMS_SCHEME_HASH, TPMS_NULL_ASYM_SCHEME. + pub inScheme: Option, + + /// Optional label L to be associated with the message + /// Size of the buffer is zero if no label is present + /// NOTE 2 See description of label above. + pub label: Vec, +} + +impl TPM2_RSA_Encrypt_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + keyHandle: &TPM_HANDLE, + message: &Vec, + inScheme: &Option, + label: &Vec, + ) -> Self { + Self { + keyHandle: keyHandle.clone(), + message: message.clone(), + inScheme: inScheme.clone(), + label: label.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_RSA_Encrypt_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.message, 2); + buf.writeShort(self.inScheme.as_ref().unwrap().GetUnionSelector().into()); + self.inScheme.as_ref().unwrap().toTpm(buf)?; + buf.writeSizedByteBuf(&self.label, 2); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.message = buf.readSizedByteBuf(2); + let r#inSchemeScheme: TPM_ALG_ID = TPM_ALG_ID(buf.readShort() as u16); + self.inScheme = TPMU_ASYM_SCHEME::create(r#inSchemeScheme)?; + self.inScheme.as_mut().unwrap().initFromTpm(buf)?; + self.label = buf.readSizedByteBuf(2); + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_RSA_Encrypt_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_RSA_Encrypt_REQUEST { + fn num_handles(&self) -> u16 { 1 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 2, val_len: 1 } } +} + +impl ReqStructure for TPM2_RSA_Encrypt_REQUEST { + fn num_auth_handles(&self) -> u16 { 0 } + + fn get_handles(&self) -> Vec { vec![self.keyHandle.clone()] } +} + +/// This command performs RSA encryption using the indicated padding scheme according to +/// IETF RFC 8017. If the scheme of keyHandle is TPM_ALG_NULL, then the caller may use +/// inScheme to specify the padding scheme. If scheme of keyHandle is not TPM_ALG_NULL, +/// then inScheme shall either be TPM_ALG_NULL or be the same as scheme (TPM_RC_SCHEME). +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct RSA_EncryptResponse { + /// Encrypted output + pub outData: Vec, +} + +impl RSA_EncryptResponse { +} + +impl TpmStructure for RSA_EncryptResponse { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.outData, 2); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.outData = buf.readSizedByteBuf(2); + Ok(()) + } + +} + +impl TpmMarshaller for RSA_EncryptResponse { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for RSA_EncryptResponse { + fn num_handles(&self) -> u16 { 0 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 2, val_len: 1 } } +} + +impl RespStructure for RSA_EncryptResponse { + fn get_handle(&self) -> TPM_HANDLE { TPM_HANDLE::default() } + + fn set_handle(&mut self, _handle: &TPM_HANDLE) { } +} + +/// This command performs RSA decryption using the indicated padding scheme according to +/// IETF RFC 8017 ((PKCS#1). +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_RSA_Decrypt_REQUEST { + /// RSA key to use for decryption + /// Auth Index: 1 + /// Auth Role: USER + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub keyHandle: TPM_HANDLE, + + /// Cipher text to be decrypted + /// NOTE An encrypted RSA data block is the size of the public modulus. + pub cipherText: Vec, + + /// Scheme selector + + /// The padding scheme to use if scheme associated with keyHandle is TPM_ALG_NULL + /// One of: TPMS_KEY_SCHEME_ECDH, TPMS_KEY_SCHEME_ECMQV, TPMS_SIG_SCHEME_RSASSA, + /// TPMS_SIG_SCHEME_RSAPSS, TPMS_SIG_SCHEME_ECDSA, TPMS_SIG_SCHEME_ECDAA, + /// TPMS_SIG_SCHEME_SM2, TPMS_SIG_SCHEME_ECSCHNORR, TPMS_ENC_SCHEME_RSAES, + /// TPMS_ENC_SCHEME_OAEP, TPMS_SCHEME_HASH, TPMS_NULL_ASYM_SCHEME. + pub inScheme: Option, + + /// Label whose association with the message is to be verified + pub label: Vec, +} + +impl TPM2_RSA_Decrypt_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + keyHandle: &TPM_HANDLE, + cipherText: &Vec, + inScheme: &Option, + label: &Vec, + ) -> Self { + Self { + keyHandle: keyHandle.clone(), + cipherText: cipherText.clone(), + inScheme: inScheme.clone(), + label: label.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_RSA_Decrypt_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.cipherText, 2); + buf.writeShort(self.inScheme.as_ref().unwrap().GetUnionSelector().into()); + self.inScheme.as_ref().unwrap().toTpm(buf)?; + buf.writeSizedByteBuf(&self.label, 2); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.cipherText = buf.readSizedByteBuf(2); + let r#inSchemeScheme: TPM_ALG_ID = TPM_ALG_ID(buf.readShort() as u16); + self.inScheme = TPMU_ASYM_SCHEME::create(r#inSchemeScheme)?; + self.inScheme.as_mut().unwrap().initFromTpm(buf)?; + self.label = buf.readSizedByteBuf(2); + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_RSA_Decrypt_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_RSA_Decrypt_REQUEST { + fn num_handles(&self) -> u16 { 1 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 2, val_len: 1 } } +} + +impl ReqStructure for TPM2_RSA_Decrypt_REQUEST { + fn num_auth_handles(&self) -> u16 { 1 } + + fn get_handles(&self) -> Vec { vec![self.keyHandle.clone()] } +} + +/// This command performs RSA decryption using the indicated padding scheme according to +/// IETF RFC 8017 ((PKCS#1). +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct RSA_DecryptResponse { + /// Decrypted output + pub message: Vec, +} + +impl RSA_DecryptResponse { +} + +impl TpmStructure for RSA_DecryptResponse { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.message, 2); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.message = buf.readSizedByteBuf(2); + Ok(()) + } + +} + +impl TpmMarshaller for RSA_DecryptResponse { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for RSA_DecryptResponse { + fn num_handles(&self) -> u16 { 0 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 2, val_len: 1 } } +} + +impl RespStructure for RSA_DecryptResponse { + fn get_handle(&self) -> TPM_HANDLE { TPM_HANDLE::default() } + + fn set_handle(&mut self, _handle: &TPM_HANDLE) { } +} + +/// This command uses the TPM to generate an ephemeral key pair (de, Qe where Qe [de]G). +/// It uses the private ephemeral key and a loaded public key (QS) to compute the shared +/// secret value (P [hde]QS). +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_ECDH_KeyGen_REQUEST { + /// Handle of a loaded ECC key public area. + /// Auth Index: None + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub keyHandle: TPM_HANDLE, +} + +impl TPM2_ECDH_KeyGen_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + keyHandle: &TPM_HANDLE, + ) -> Self { + Self { + keyHandle: keyHandle.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_ECDH_KeyGen_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_ECDH_KeyGen_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_ECDH_KeyGen_REQUEST { + fn num_handles(&self) -> u16 { 1 } + +} + +impl ReqStructure for TPM2_ECDH_KeyGen_REQUEST { + fn num_auth_handles(&self) -> u16 { 0 } + + fn get_handles(&self) -> Vec { vec![self.keyHandle.clone()] } +} + +/// This command uses the TPM to generate an ephemeral key pair (de, Qe where Qe [de]G). +/// It uses the private ephemeral key and a loaded public key (QS) to compute the shared +/// secret value (P [hde]QS). +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct ECDH_KeyGenResponse { + /// Results of P h[de]Qs + pub zPoint: TPMS_ECC_POINT, + + /// Generated ephemeral public point (Qe) + pub pubPoint: TPMS_ECC_POINT, +} + +impl ECDH_KeyGenResponse { +} + +impl TpmStructure for ECDH_KeyGenResponse { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedObj(&self.zPoint)?; + buf.writeSizedObj(&self.pubPoint)?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + buf.readSizedObj(&mut self.zPoint)?; + buf.readSizedObj(&mut self.pubPoint)?; + Ok(()) + } + +} + +impl TpmMarshaller for ECDH_KeyGenResponse { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for ECDH_KeyGenResponse { + fn num_handles(&self) -> u16 { 0 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 2, val_len: 1 } } +} + +impl RespStructure for ECDH_KeyGenResponse { + fn get_handle(&self) -> TPM_HANDLE { TPM_HANDLE::default() } + + fn set_handle(&mut self, _handle: &TPM_HANDLE) { } +} + +/// This command uses the TPM to recover the Z value from a public point (QB) and a +/// private key (ds). It will perform the multiplication of the provided inPoint (QB) with +/// the private key (ds) and return the coordinates of the resultant point (Z = (xZ , yZ) +/// [hds]QB; where h is the cofactor of the curve). +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_ECDH_ZGen_REQUEST { + /// Handle of a loaded ECC key + /// Auth Index: 1 + /// Auth Role: USER + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub keyHandle: TPM_HANDLE, + + /// A public key + pub inPoint: TPMS_ECC_POINT, +} + +impl TPM2_ECDH_ZGen_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + keyHandle: &TPM_HANDLE, + inPoint: &TPMS_ECC_POINT, + ) -> Self { + Self { + keyHandle: keyHandle.clone(), + inPoint: inPoint.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_ECDH_ZGen_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedObj(&self.inPoint)?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + buf.readSizedObj(&mut self.inPoint)?; + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_ECDH_ZGen_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_ECDH_ZGen_REQUEST { + fn num_handles(&self) -> u16 { 1 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 2, val_len: 1 } } +} + +impl ReqStructure for TPM2_ECDH_ZGen_REQUEST { + fn num_auth_handles(&self) -> u16 { 1 } + + fn get_handles(&self) -> Vec { vec![self.keyHandle.clone()] } +} + +/// This command uses the TPM to recover the Z value from a public point (QB) and a +/// private key (ds). It will perform the multiplication of the provided inPoint (QB) with +/// the private key (ds) and return the coordinates of the resultant point (Z = (xZ , yZ) +/// [hds]QB; where h is the cofactor of the curve). +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct ECDH_ZGenResponse { + /// X and Y coordinates of the product of the multiplication Z = (xZ , yZ) [hdS]QB + pub outPoint: TPMS_ECC_POINT, +} + +impl ECDH_ZGenResponse { +} + +impl TpmStructure for ECDH_ZGenResponse { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedObj(&self.outPoint)?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + buf.readSizedObj(&mut self.outPoint)?; + Ok(()) + } + +} + +impl TpmMarshaller for ECDH_ZGenResponse { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for ECDH_ZGenResponse { + fn num_handles(&self) -> u16 { 0 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 2, val_len: 1 } } +} + +impl RespStructure for ECDH_ZGenResponse { + fn get_handle(&self) -> TPM_HANDLE { TPM_HANDLE::default() } + + fn set_handle(&mut self, _handle: &TPM_HANDLE) { } +} + +/// This command returns the parameters of an ECC curve identified by its TCG-assigned curveID. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_ECC_Parameters_REQUEST { + /// Parameter set selector + pub curveID: TPM_ECC_CURVE, +} + +impl TPM2_ECC_Parameters_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + curveID: TPM_ECC_CURVE, + ) -> Self { + Self { + curveID: curveID.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_ECC_Parameters_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeShort(self.curveID.into()); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.curveID = TPM_ECC_CURVE(buf.readShort() as u16); + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_ECC_Parameters_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_ECC_Parameters_REQUEST { + fn num_handles(&self) -> u16 { 0 } + +} + +impl ReqStructure for TPM2_ECC_Parameters_REQUEST { + fn num_auth_handles(&self) -> u16 { 0 } + + fn get_handles(&self) -> Vec { vec![] } +} + +/// This command returns the parameters of an ECC curve identified by its TCG-assigned curveID. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct ECC_ParametersResponse { + /// ECC parameters for the selected curve + pub parameters: TPMS_ALGORITHM_DETAIL_ECC, +} + +impl ECC_ParametersResponse { +} + +impl TpmStructure for ECC_ParametersResponse { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + self.parameters.toTpm(buf)?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.parameters.initFromTpm(buf)?; + Ok(()) + } + +} + +impl TpmMarshaller for ECC_ParametersResponse { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for ECC_ParametersResponse { + fn num_handles(&self) -> u16 { 0 } + +} + +impl RespStructure for ECC_ParametersResponse { + fn get_handle(&self) -> TPM_HANDLE { TPM_HANDLE::default() } + + fn set_handle(&mut self, _handle: &TPM_HANDLE) { } +} + +/// This command supports two-phase key exchange protocols. The command is used in +/// combination with TPM2_EC_Ephemeral(). TPM2_EC_Ephemeral() generates an ephemeral key +/// and returns the public point of that ephemeral key along with a numeric value that +/// allows the TPM to regenerate the associated private key. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_ZGen_2Phase_REQUEST { + /// Handle of an unrestricted decryption key ECC + /// The private key referenced by this handle is used as dS,A + /// Auth Index: 1 + /// Auth Role: USER + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub keyA: TPM_HANDLE, + + /// Other partys static public key (Qs,B = (Xs,B, Ys,B)) + pub inQsB: TPMS_ECC_POINT, + + /// Other party's ephemeral public key (Qe,B = (Xe,B, Ye,B)) + pub inQeB: TPMS_ECC_POINT, + + /// The key exchange scheme + #[derivative(Default(value="TPM_ALG_ID::NULL"))] + pub inScheme: TPM_ALG_ID, + + /// Value returned by TPM2_EC_Ephemeral() + pub counter: u16, +} + +impl TPM2_ZGen_2Phase_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + keyA: &TPM_HANDLE, + inQsB: &TPMS_ECC_POINT, + inQeB: &TPMS_ECC_POINT, + inScheme: TPM_ALG_ID, + counter: u16, + ) -> Self { + Self { + keyA: keyA.clone(), + inQsB: inQsB.clone(), + inQeB: inQeB.clone(), + inScheme: inScheme.clone(), + counter: counter.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_ZGen_2Phase_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedObj(&self.inQsB)?; + buf.writeSizedObj(&self.inQeB)?; + buf.writeShort(self.inScheme.into()); + buf.writeShort(self.counter as u16); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + buf.readSizedObj(&mut self.inQsB)?; + buf.readSizedObj(&mut self.inQeB)?; + self.inScheme = TPM_ALG_ID(buf.readShort() as u16); + self.counter = buf.readShort() as u16; + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_ZGen_2Phase_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_ZGen_2Phase_REQUEST { + fn num_handles(&self) -> u16 { 1 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 2, val_len: 1 } } +} + +impl ReqStructure for TPM2_ZGen_2Phase_REQUEST { + fn num_auth_handles(&self) -> u16 { 1 } + + fn get_handles(&self) -> Vec { vec![self.keyA.clone()] } +} + +/// This command supports two-phase key exchange protocols. The command is used in +/// combination with TPM2_EC_Ephemeral(). TPM2_EC_Ephemeral() generates an ephemeral key +/// and returns the public point of that ephemeral key along with a numeric value that +/// allows the TPM to regenerate the associated private key. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct ZGen_2PhaseResponse { + /// X and Y coordinates of the computed value (scheme dependent) + pub outZ1: TPMS_ECC_POINT, + + /// X and Y coordinates of the second computed value (scheme dependent) + pub outZ2: TPMS_ECC_POINT, +} + +impl ZGen_2PhaseResponse { +} + +impl TpmStructure for ZGen_2PhaseResponse { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedObj(&self.outZ1)?; + buf.writeSizedObj(&self.outZ2)?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + buf.readSizedObj(&mut self.outZ1)?; + buf.readSizedObj(&mut self.outZ2)?; + Ok(()) + } + +} + +impl TpmMarshaller for ZGen_2PhaseResponse { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for ZGen_2PhaseResponse { + fn num_handles(&self) -> u16 { 0 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 2, val_len: 1 } } +} + +impl RespStructure for ZGen_2PhaseResponse { + fn get_handle(&self) -> TPM_HANDLE { TPM_HANDLE::default() } + + fn set_handle(&mut self, _handle: &TPM_HANDLE) { } +} + +/// This command performs ECC encryption as described in Part 1, Annex D. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_ECC_Encrypt_REQUEST { + /// Reference to public portion of ECC key to use for encryption + /// Auth Index: None + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub keyHandle: TPM_HANDLE, + + /// Plaintext to be encrypted + pub plainText: Vec, + + /// Scheme selector + + /// The KDF to use if scheme associated with keyHandle is TPM_ALG_NULL + /// One of: TPMS_KDF_SCHEME_MGF1, TPMS_KDF_SCHEME_KDF1_SP800_56A, TPMS_KDF_SCHEME_KDF2, + /// TPMS_KDF_SCHEME_KDF1_SP800_108, TPMS_SCHEME_HASH, TPMS_NULL_KDF_SCHEME. + pub inScheme: Option, +} + +impl TPM2_ECC_Encrypt_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + keyHandle: &TPM_HANDLE, + plainText: &Vec, + inScheme: &Option, + ) -> Self { + Self { + keyHandle: keyHandle.clone(), + plainText: plainText.clone(), + inScheme: inScheme.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_ECC_Encrypt_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.plainText, 2); + buf.writeShort(self.inScheme.as_ref().unwrap().GetUnionSelector().into()); + self.inScheme.as_ref().unwrap().toTpm(buf)?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.plainText = buf.readSizedByteBuf(2); + let r#inSchemeScheme: TPM_ALG_ID = TPM_ALG_ID(buf.readShort() as u16); + self.inScheme = TPMU_KDF_SCHEME::create(r#inSchemeScheme)?; + self.inScheme.as_mut().unwrap().initFromTpm(buf)?; + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_ECC_Encrypt_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_ECC_Encrypt_REQUEST { + fn num_handles(&self) -> u16 { 1 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 2, val_len: 1 } } +} + +impl ReqStructure for TPM2_ECC_Encrypt_REQUEST { + fn num_auth_handles(&self) -> u16 { 0 } + + fn get_handles(&self) -> Vec { vec![self.keyHandle.clone()] } +} + +/// This command performs ECC encryption as described in Part 1, Annex D. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct ECC_EncryptResponse { + /// The public ephemeral key used for ECDH + pub C1: TPMS_ECC_POINT, + + /// The data block produced by the XOR process + pub C2: Vec, + + /// The integrity value + pub C3: Vec, +} + +impl ECC_EncryptResponse { +} + +impl TpmStructure for ECC_EncryptResponse { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedObj(&self.C1)?; + buf.writeSizedByteBuf(&self.C2, 2); + buf.writeSizedByteBuf(&self.C3, 2); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + buf.readSizedObj(&mut self.C1)?; + self.C2 = buf.readSizedByteBuf(2); + self.C3 = buf.readSizedByteBuf(2); + Ok(()) + } + +} + +impl TpmMarshaller for ECC_EncryptResponse { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for ECC_EncryptResponse { + fn num_handles(&self) -> u16 { 0 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 2, val_len: 1 } } +} + +impl RespStructure for ECC_EncryptResponse { + fn get_handle(&self) -> TPM_HANDLE { TPM_HANDLE::default() } + + fn set_handle(&mut self, _handle: &TPM_HANDLE) { } +} + +/// This command performs ECC decryption. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_ECC_Decrypt_REQUEST { + /// ECC key to use for decryption + /// Auth Index: 1 + /// Auth Role: USER + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub keyHandle: TPM_HANDLE, + + /// The public ephemeral key used for ECDH + pub C1: TPMS_ECC_POINT, + + /// The data block produced by the XOR process + pub C2: Vec, + + /// The integrity value + pub C3: Vec, + + /// Scheme selector + + /// The KDF to use if scheme associated with keyHandle is TPM_ALG_NULL + /// One of: TPMS_KDF_SCHEME_MGF1, TPMS_KDF_SCHEME_KDF1_SP800_56A, TPMS_KDF_SCHEME_KDF2, + /// TPMS_KDF_SCHEME_KDF1_SP800_108, TPMS_SCHEME_HASH, TPMS_NULL_KDF_SCHEME. + pub inScheme: Option, +} + +impl TPM2_ECC_Decrypt_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + keyHandle: &TPM_HANDLE, + C1: &TPMS_ECC_POINT, + C2: &Vec, + C3: &Vec, + inScheme: &Option, + ) -> Self { + Self { + keyHandle: keyHandle.clone(), + C1: C1.clone(), + C2: C2.clone(), + C3: C3.clone(), + inScheme: inScheme.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_ECC_Decrypt_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedObj(&self.C1)?; + buf.writeSizedByteBuf(&self.C2, 2); + buf.writeSizedByteBuf(&self.C3, 2); + buf.writeShort(self.inScheme.as_ref().unwrap().GetUnionSelector().into()); + self.inScheme.as_ref().unwrap().toTpm(buf)?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + buf.readSizedObj(&mut self.C1)?; + self.C2 = buf.readSizedByteBuf(2); + self.C3 = buf.readSizedByteBuf(2); + let r#inSchemeScheme: TPM_ALG_ID = TPM_ALG_ID(buf.readShort() as u16); + self.inScheme = TPMU_KDF_SCHEME::create(r#inSchemeScheme)?; + self.inScheme.as_mut().unwrap().initFromTpm(buf)?; + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_ECC_Decrypt_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_ECC_Decrypt_REQUEST { + fn num_handles(&self) -> u16 { 1 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 2, val_len: 1 } } +} + +impl ReqStructure for TPM2_ECC_Decrypt_REQUEST { + fn num_auth_handles(&self) -> u16 { 1 } + + fn get_handles(&self) -> Vec { vec![self.keyHandle.clone()] } +} + +/// This command performs ECC decryption. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct ECC_DecryptResponse { + /// Decrypted output + pub plainText: Vec, +} + +impl ECC_DecryptResponse { +} + +impl TpmStructure for ECC_DecryptResponse { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.plainText, 2); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.plainText = buf.readSizedByteBuf(2); + Ok(()) + } + +} + +impl TpmMarshaller for ECC_DecryptResponse { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for ECC_DecryptResponse { + fn num_handles(&self) -> u16 { 0 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 2, val_len: 1 } } +} + +impl RespStructure for ECC_DecryptResponse { + fn get_handle(&self) -> TPM_HANDLE { TPM_HANDLE::default() } + + fn set_handle(&mut self, _handle: &TPM_HANDLE) { } +} + +/// NOTE 1 This command is deprecated, and TPM2_EncryptDecrypt2() is preferred. This +/// should be reflected in platform-specific specifications. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_EncryptDecrypt_REQUEST { + /// The symmetric key used for the operation + /// Auth Index: 1 + /// Auth Role: USER + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub keyHandle: TPM_HANDLE, + + /// If YES, then the operation is decryption; if NO, the operation is encryption + pub decrypt: u8, + + /// Symmetric encryption/decryption mode + /// this field shall match the default mode of the key or be TPM_ALG_NULL. + #[derivative(Default(value="TPM_ALG_ID::NULL"))] + pub mode: TPM_ALG_ID, + + /// An initial value as required by the algorithm + pub ivIn: Vec, + + /// The data to be encrypted/decrypted + pub inData: Vec, +} + +impl TPM2_EncryptDecrypt_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + keyHandle: &TPM_HANDLE, + decrypt: u8, + mode: TPM_ALG_ID, + ivIn: &Vec, + inData: &Vec, + ) -> Self { + Self { + keyHandle: keyHandle.clone(), + decrypt: decrypt.clone(), + mode: mode.clone(), + ivIn: ivIn.clone(), + inData: inData.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_EncryptDecrypt_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeByte(self.decrypt as u8); + buf.writeShort(self.mode.into()); + buf.writeSizedByteBuf(&self.ivIn, 2); + buf.writeSizedByteBuf(&self.inData, 2); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.decrypt = buf.readByte() as u8; + self.mode = TPM_ALG_ID(buf.readShort() as u16); + self.ivIn = buf.readSizedByteBuf(2); + self.inData = buf.readSizedByteBuf(2); + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_EncryptDecrypt_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_EncryptDecrypt_REQUEST { + fn num_handles(&self) -> u16 { 1 } + +} + +impl ReqStructure for TPM2_EncryptDecrypt_REQUEST { + fn num_auth_handles(&self) -> u16 { 1 } + + fn get_handles(&self) -> Vec { vec![self.keyHandle.clone()] } +} + +/// NOTE 1 This command is deprecated, and TPM2_EncryptDecrypt2() is preferred. This +/// should be reflected in platform-specific specifications. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct EncryptDecryptResponse { + /// Encrypted or decrypted output + pub outData: Vec, + + /// Chaining value to use for IV in next round + pub ivOut: Vec, +} + +impl EncryptDecryptResponse { +} + +impl TpmStructure for EncryptDecryptResponse { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.outData, 2); + buf.writeSizedByteBuf(&self.ivOut, 2); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.outData = buf.readSizedByteBuf(2); + self.ivOut = buf.readSizedByteBuf(2); + Ok(()) + } + +} + +impl TpmMarshaller for EncryptDecryptResponse { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for EncryptDecryptResponse { + fn num_handles(&self) -> u16 { 0 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 2, val_len: 1 } } +} + +impl RespStructure for EncryptDecryptResponse { + fn get_handle(&self) -> TPM_HANDLE { TPM_HANDLE::default() } + + fn set_handle(&mut self, _handle: &TPM_HANDLE) { } +} + +/// This command is identical to TPM2_EncryptDecrypt(), except that the inData parameter +/// is the first parameter. This permits inData to be parameter encrypted. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_EncryptDecrypt2_REQUEST { + /// The symmetric key used for the operation + /// Auth Index: 1 + /// Auth Role: USER + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub keyHandle: TPM_HANDLE, + + /// The data to be encrypted/decrypted + pub inData: Vec, + + /// If YES, then the operation is decryption; if NO, the operation is encryption + pub decrypt: u8, + + /// Symmetric mode + /// this field shall match the default mode of the key or be TPM_ALG_NULL. + #[derivative(Default(value="TPM_ALG_ID::NULL"))] + pub mode: TPM_ALG_ID, + + /// An initial value as required by the algorithm + pub ivIn: Vec, +} + +impl TPM2_EncryptDecrypt2_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + keyHandle: &TPM_HANDLE, + inData: &Vec, + decrypt: u8, + mode: TPM_ALG_ID, + ivIn: &Vec, + ) -> Self { + Self { + keyHandle: keyHandle.clone(), + inData: inData.clone(), + decrypt: decrypt.clone(), + mode: mode.clone(), + ivIn: ivIn.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_EncryptDecrypt2_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.inData, 2); + buf.writeByte(self.decrypt as u8); + buf.writeShort(self.mode.into()); + buf.writeSizedByteBuf(&self.ivIn, 2); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.inData = buf.readSizedByteBuf(2); + self.decrypt = buf.readByte() as u8; + self.mode = TPM_ALG_ID(buf.readShort() as u16); + self.ivIn = buf.readSizedByteBuf(2); + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_EncryptDecrypt2_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_EncryptDecrypt2_REQUEST { + fn num_handles(&self) -> u16 { 1 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 2, val_len: 1 } } +} + +impl ReqStructure for TPM2_EncryptDecrypt2_REQUEST { + fn num_auth_handles(&self) -> u16 { 1 } + + fn get_handles(&self) -> Vec { vec![self.keyHandle.clone()] } +} + +/// This command is identical to TPM2_EncryptDecrypt(), except that the inData parameter +/// is the first parameter. This permits inData to be parameter encrypted. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct EncryptDecrypt2Response { + /// Encrypted or decrypted output + pub outData: Vec, + + /// Chaining value to use for IV in next round + pub ivOut: Vec, +} + +impl EncryptDecrypt2Response { +} + +impl TpmStructure for EncryptDecrypt2Response { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.outData, 2); + buf.writeSizedByteBuf(&self.ivOut, 2); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.outData = buf.readSizedByteBuf(2); + self.ivOut = buf.readSizedByteBuf(2); + Ok(()) + } + +} + +impl TpmMarshaller for EncryptDecrypt2Response { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for EncryptDecrypt2Response { + fn num_handles(&self) -> u16 { 0 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 2, val_len: 1 } } +} + +impl RespStructure for EncryptDecrypt2Response { + fn get_handle(&self) -> TPM_HANDLE { TPM_HANDLE::default() } + + fn set_handle(&mut self, _handle: &TPM_HANDLE) { } +} + +/// This command performs a hash operation on a data buffer and returns the results. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_Hash_REQUEST { + /// Data to be hashed + pub data: Vec, + + /// Algorithm for the hash being computed shall not be TPM_ALG_NULL + #[derivative(Default(value="TPM_ALG_ID::NULL"))] + pub hashAlg: TPM_ALG_ID, + + /// Hierarchy to use for the ticket (TPM_RH_NULL allowed) + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub hierarchy: TPM_HANDLE, +} + +impl TPM2_Hash_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + data: &Vec, + hashAlg: TPM_ALG_ID, + hierarchy: &TPM_HANDLE, + ) -> Self { + Self { + data: data.clone(), + hashAlg: hashAlg.clone(), + hierarchy: hierarchy.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_Hash_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.data, 2); + buf.writeShort(self.hashAlg.into()); + self.hierarchy.toTpm(buf)?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.data = buf.readSizedByteBuf(2); + self.hashAlg = TPM_ALG_ID(buf.readShort() as u16); + self.hierarchy.initFromTpm(buf)?; + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_Hash_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_Hash_REQUEST { + fn num_handles(&self) -> u16 { 0 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 2, val_len: 1 } } +} + +impl ReqStructure for TPM2_Hash_REQUEST { + fn num_auth_handles(&self) -> u16 { 0 } + + fn get_handles(&self) -> Vec { vec![] } +} + +/// This command performs a hash operation on a data buffer and returns the results. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct HashResponse { + /// Results + pub outHash: Vec, + + /// Ticket indicating that the sequence of octets used to compute outDigest did not start + /// with TPM_GENERATED_VALUE + /// will be a NULL ticket if the digest may not be signed with a restricted key + pub validation: TPMT_TK_HASHCHECK, +} + +impl HashResponse { +} + +impl TpmStructure for HashResponse { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.outHash, 2); + self.validation.toTpm(buf)?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.outHash = buf.readSizedByteBuf(2); + self.validation.initFromTpm(buf)?; + Ok(()) + } + +} + +impl TpmMarshaller for HashResponse { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for HashResponse { + fn num_handles(&self) -> u16 { 0 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 2, val_len: 1 } } +} + +impl RespStructure for HashResponse { + fn get_handle(&self) -> TPM_HANDLE { TPM_HANDLE::default() } + + fn set_handle(&mut self, _handle: &TPM_HANDLE) { } +} + +/// This command performs an HMAC on the supplied data using the indicated hash algorithm. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_HMAC_REQUEST { + /// Handle for the symmetric signing key providing the HMAC key + /// Auth Index: 1 + /// Auth Role: USER + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub handle: TPM_HANDLE, + + /// HMAC data + pub buffer: Vec, + + /// Algorithm to use for HMAC + #[derivative(Default(value="TPM_ALG_ID::NULL"))] + pub hashAlg: TPM_ALG_ID, +} + +impl TPM2_HMAC_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + handle: &TPM_HANDLE, + buffer: &Vec, + hashAlg: TPM_ALG_ID, + ) -> Self { + Self { + handle: handle.clone(), + buffer: buffer.clone(), + hashAlg: hashAlg.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_HMAC_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.buffer, 2); + buf.writeShort(self.hashAlg.into()); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.buffer = buf.readSizedByteBuf(2); + self.hashAlg = TPM_ALG_ID(buf.readShort() as u16); + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_HMAC_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_HMAC_REQUEST { + fn num_handles(&self) -> u16 { 1 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 2, val_len: 1 } } +} + +impl ReqStructure for TPM2_HMAC_REQUEST { + fn num_auth_handles(&self) -> u16 { 1 } + + fn get_handles(&self) -> Vec { vec![self.handle.clone()] } +} + +/// This command performs an HMAC on the supplied data using the indicated hash algorithm. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct HMACResponse { + /// The returned HMAC in a sized buffer + pub outHMAC: Vec, +} + +impl HMACResponse { +} + +impl TpmStructure for HMACResponse { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.outHMAC, 2); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.outHMAC = buf.readSizedByteBuf(2); + Ok(()) + } + +} + +impl TpmMarshaller for HMACResponse { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for HMACResponse { + fn num_handles(&self) -> u16 { 0 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 2, val_len: 1 } } +} + +impl RespStructure for HMACResponse { + fn get_handle(&self) -> TPM_HANDLE { TPM_HANDLE::default() } + + fn set_handle(&mut self, _handle: &TPM_HANDLE) { } +} + +/// This command performs an HMAC or a block cipher MAC on the supplied data using the +/// indicated algorithm. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_MAC_REQUEST { + /// Handle for the symmetric signing key providing the MAC key + /// Auth Index: 1 + /// Auth Role: USER + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub handle: TPM_HANDLE, + + /// MAC data + pub buffer: Vec, + + /// Algorithm to use for MAC + #[derivative(Default(value="TPM_ALG_ID::NULL"))] + pub inScheme: TPM_ALG_ID, +} + +impl TPM2_MAC_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + handle: &TPM_HANDLE, + buffer: &Vec, + inScheme: TPM_ALG_ID, + ) -> Self { + Self { + handle: handle.clone(), + buffer: buffer.clone(), + inScheme: inScheme.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_MAC_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.buffer, 2); + buf.writeShort(self.inScheme.into()); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.buffer = buf.readSizedByteBuf(2); + self.inScheme = TPM_ALG_ID(buf.readShort() as u16); + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_MAC_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_MAC_REQUEST { + fn num_handles(&self) -> u16 { 1 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 2, val_len: 1 } } +} + +impl ReqStructure for TPM2_MAC_REQUEST { + fn num_auth_handles(&self) -> u16 { 1 } + + fn get_handles(&self) -> Vec { vec![self.handle.clone()] } +} + +/// This command performs an HMAC or a block cipher MAC on the supplied data using the +/// indicated algorithm. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct MACResponse { + /// The returned MAC in a sized buffer + pub outMAC: Vec, +} + +impl MACResponse { +} + +impl TpmStructure for MACResponse { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.outMAC, 2); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.outMAC = buf.readSizedByteBuf(2); + Ok(()) + } + +} + +impl TpmMarshaller for MACResponse { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for MACResponse { + fn num_handles(&self) -> u16 { 0 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 2, val_len: 1 } } +} + +impl RespStructure for MACResponse { + fn get_handle(&self) -> TPM_HANDLE { TPM_HANDLE::default() } + + fn set_handle(&mut self, _handle: &TPM_HANDLE) { } +} + +/// This command returns the next bytesRequested octets from the random number generator (RNG). +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_GetRandom_REQUEST { + /// Number of octets to return + pub bytesRequested: u16, +} + +impl TPM2_GetRandom_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + bytesRequested: u16, + ) -> Self { + Self { + bytesRequested: bytesRequested.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_GetRandom_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeShort(self.bytesRequested as u16); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.bytesRequested = buf.readShort() as u16; + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_GetRandom_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_GetRandom_REQUEST { + fn num_handles(&self) -> u16 { 0 } + +} + +impl ReqStructure for TPM2_GetRandom_REQUEST { + fn num_auth_handles(&self) -> u16 { 0 } + + fn get_handles(&self) -> Vec { vec![] } +} + +/// This command returns the next bytesRequested octets from the random number generator (RNG). +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct GetRandomResponse { + /// The random octets + pub randomBytes: Vec, +} + +impl GetRandomResponse { +} + +impl TpmStructure for GetRandomResponse { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.randomBytes, 2); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.randomBytes = buf.readSizedByteBuf(2); + Ok(()) + } + +} + +impl TpmMarshaller for GetRandomResponse { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for GetRandomResponse { + fn num_handles(&self) -> u16 { 0 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 2, val_len: 1 } } +} + +impl RespStructure for GetRandomResponse { + fn get_handle(&self) -> TPM_HANDLE { TPM_HANDLE::default() } + + fn set_handle(&mut self, _handle: &TPM_HANDLE) { } +} + +/// This command is used to add "additional information" to the RNG state. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_StirRandom_REQUEST { + /// Additional information + pub inData: Vec, +} + +impl TPM2_StirRandom_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + inData: &Vec, + ) -> Self { + Self { + inData: inData.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_StirRandom_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.inData, 2); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.inData = buf.readSizedByteBuf(2); + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_StirRandom_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_StirRandom_REQUEST { + fn num_handles(&self) -> u16 { 0 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 2, val_len: 1 } } +} + +impl ReqStructure for TPM2_StirRandom_REQUEST { + fn num_auth_handles(&self) -> u16 { 0 } + + fn get_handles(&self) -> Vec { vec![] } +} + +/// This command starts an HMAC sequence. The TPM will create and initialize an HMAC +/// sequence structure, assign a handle to the sequence, and set the authValue of the +/// sequence object to the value in auth. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_HMAC_Start_REQUEST { + /// Handle of an HMAC key + /// Auth Index: 1 + /// Auth Role: USER + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub handle: TPM_HANDLE, + + /// Authorization value for subsequent use of the sequence + pub auth: Vec, + + /// The hash algorithm to use for the HMAC + #[derivative(Default(value="TPM_ALG_ID::NULL"))] + pub hashAlg: TPM_ALG_ID, +} + +impl TPM2_HMAC_Start_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + handle: &TPM_HANDLE, + auth: &Vec, + hashAlg: TPM_ALG_ID, + ) -> Self { + Self { + handle: handle.clone(), + auth: auth.clone(), + hashAlg: hashAlg.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_HMAC_Start_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.auth, 2); + buf.writeShort(self.hashAlg.into()); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.auth = buf.readSizedByteBuf(2); + self.hashAlg = TPM_ALG_ID(buf.readShort() as u16); + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_HMAC_Start_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_HMAC_Start_REQUEST { + fn num_handles(&self) -> u16 { 1 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 2, val_len: 1 } } +} + +impl ReqStructure for TPM2_HMAC_Start_REQUEST { + fn num_auth_handles(&self) -> u16 { 1 } + + fn get_handles(&self) -> Vec { vec![self.handle.clone()] } +} + +/// This command starts an HMAC sequence. The TPM will create and initialize an HMAC +/// sequence structure, assign a handle to the sequence, and set the authValue of the +/// sequence object to the value in auth. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct HMAC_StartResponse { + /// A handle to reference the sequence + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub handle: TPM_HANDLE, +} + +impl HMAC_StartResponse { +} + +impl TpmStructure for HMAC_StartResponse { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + Ok(()) + } + +} + +impl TpmMarshaller for HMAC_StartResponse { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for HMAC_StartResponse { + fn num_handles(&self) -> u16 { 1 } + +} + +impl RespStructure for HMAC_StartResponse { + fn get_handle(&self) -> TPM_HANDLE { self.handle.clone() } + + fn set_handle(&mut self, handle: &TPM_HANDLE) { self.handle = handle.clone(); } +} + +/// This command starts a MAC sequence. The TPM will create and initialize a MAC sequence +/// structure, assign a handle to the sequence, and set the authValue of the sequence +/// object to the value in auth. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_MAC_Start_REQUEST { + /// Handle of a MAC key + /// Auth Index: 1 + /// Auth Role: USER + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub handle: TPM_HANDLE, + + /// Authorization value for subsequent use of the sequence + pub auth: Vec, + + /// The algorithm to use for the MAC + #[derivative(Default(value="TPM_ALG_ID::NULL"))] + pub inScheme: TPM_ALG_ID, +} + +impl TPM2_MAC_Start_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + handle: &TPM_HANDLE, + auth: &Vec, + inScheme: TPM_ALG_ID, + ) -> Self { + Self { + handle: handle.clone(), + auth: auth.clone(), + inScheme: inScheme.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_MAC_Start_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.auth, 2); + buf.writeShort(self.inScheme.into()); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.auth = buf.readSizedByteBuf(2); + self.inScheme = TPM_ALG_ID(buf.readShort() as u16); + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_MAC_Start_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_MAC_Start_REQUEST { + fn num_handles(&self) -> u16 { 1 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 2, val_len: 1 } } +} + +impl ReqStructure for TPM2_MAC_Start_REQUEST { + fn num_auth_handles(&self) -> u16 { 1 } + + fn get_handles(&self) -> Vec { vec![self.handle.clone()] } +} + +/// This command starts a MAC sequence. The TPM will create and initialize a MAC sequence +/// structure, assign a handle to the sequence, and set the authValue of the sequence +/// object to the value in auth. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct MAC_StartResponse { + /// A handle to reference the sequence + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub handle: TPM_HANDLE, +} + +impl MAC_StartResponse { +} + +impl TpmStructure for MAC_StartResponse { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + Ok(()) + } + +} + +impl TpmMarshaller for MAC_StartResponse { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for MAC_StartResponse { + fn num_handles(&self) -> u16 { 1 } + +} + +impl RespStructure for MAC_StartResponse { + fn get_handle(&self) -> TPM_HANDLE { self.handle.clone() } + + fn set_handle(&mut self, handle: &TPM_HANDLE) { self.handle = handle.clone(); } +} + +/// This command starts a hash or an Event Sequence. If hashAlg is an implemented hash, +/// then a hash sequence is started. If hashAlg is TPM_ALG_NULL, then an Event Sequence is +/// started. If hashAlg is neither an implemented algorithm nor TPM_ALG_NULL, then the TPM +/// shall return TPM_RC_HASH. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_HashSequenceStart_REQUEST { + /// Authorization value for subsequent use of the sequence + pub auth: Vec, + + /// The hash algorithm to use for the hash sequence + /// An Event Sequence starts if this is TPM_ALG_NULL. + #[derivative(Default(value="TPM_ALG_ID::NULL"))] + pub hashAlg: TPM_ALG_ID, +} + +impl TPM2_HashSequenceStart_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + auth: &Vec, + hashAlg: TPM_ALG_ID, + ) -> Self { + Self { + auth: auth.clone(), + hashAlg: hashAlg.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_HashSequenceStart_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.auth, 2); + buf.writeShort(self.hashAlg.into()); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.auth = buf.readSizedByteBuf(2); + self.hashAlg = TPM_ALG_ID(buf.readShort() as u16); + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_HashSequenceStart_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_HashSequenceStart_REQUEST { + fn num_handles(&self) -> u16 { 0 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 2, val_len: 1 } } +} + +impl ReqStructure for TPM2_HashSequenceStart_REQUEST { + fn num_auth_handles(&self) -> u16 { 0 } + + fn get_handles(&self) -> Vec { vec![] } +} + +/// This command starts a hash or an Event Sequence. If hashAlg is an implemented hash, +/// then a hash sequence is started. If hashAlg is TPM_ALG_NULL, then an Event Sequence is +/// started. If hashAlg is neither an implemented algorithm nor TPM_ALG_NULL, then the TPM +/// shall return TPM_RC_HASH. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct HashSequenceStartResponse { + /// A handle to reference the sequence + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub handle: TPM_HANDLE, +} + +impl HashSequenceStartResponse { +} + +impl TpmStructure for HashSequenceStartResponse { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + Ok(()) + } + +} + +impl TpmMarshaller for HashSequenceStartResponse { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for HashSequenceStartResponse { + fn num_handles(&self) -> u16 { 1 } + +} + +impl RespStructure for HashSequenceStartResponse { + fn get_handle(&self) -> TPM_HANDLE { self.handle.clone() } + + fn set_handle(&mut self, handle: &TPM_HANDLE) { self.handle = handle.clone(); } +} + +/// This command is used to add data to a hash or HMAC sequence. The amount of data in +/// buffer may be any size up to the limits of the TPM. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_SequenceUpdate_REQUEST { + /// Handle for the sequence object + /// Auth Index: 1 + /// Auth Role: USER + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub sequenceHandle: TPM_HANDLE, + + /// Data to be added to hash + pub buffer: Vec, +} + +impl TPM2_SequenceUpdate_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + sequenceHandle: &TPM_HANDLE, + buffer: &Vec, + ) -> Self { + Self { + sequenceHandle: sequenceHandle.clone(), + buffer: buffer.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_SequenceUpdate_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.buffer, 2); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.buffer = buf.readSizedByteBuf(2); + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_SequenceUpdate_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_SequenceUpdate_REQUEST { + fn num_handles(&self) -> u16 { 1 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 2, val_len: 1 } } +} + +impl ReqStructure for TPM2_SequenceUpdate_REQUEST { + fn num_auth_handles(&self) -> u16 { 1 } + + fn get_handles(&self) -> Vec { vec![self.sequenceHandle.clone()] } +} + +/// This command adds the last part of data, if any, to a hash/HMAC sequence and returns +/// the result. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_SequenceComplete_REQUEST { + /// Authorization for the sequence + /// Auth Index: 1 + /// Auth Role: USER + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub sequenceHandle: TPM_HANDLE, + + /// Data to be added to the hash/HMAC + pub buffer: Vec, + + /// Hierarchy of the ticket for a hash + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub hierarchy: TPM_HANDLE, +} + +impl TPM2_SequenceComplete_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + sequenceHandle: &TPM_HANDLE, + buffer: &Vec, + hierarchy: &TPM_HANDLE, + ) -> Self { + Self { + sequenceHandle: sequenceHandle.clone(), + buffer: buffer.clone(), + hierarchy: hierarchy.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_SequenceComplete_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.buffer, 2); + self.hierarchy.toTpm(buf)?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.buffer = buf.readSizedByteBuf(2); + self.hierarchy.initFromTpm(buf)?; + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_SequenceComplete_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_SequenceComplete_REQUEST { + fn num_handles(&self) -> u16 { 1 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 2, val_len: 1 } } +} + +impl ReqStructure for TPM2_SequenceComplete_REQUEST { + fn num_auth_handles(&self) -> u16 { 1 } + + fn get_handles(&self) -> Vec { vec![self.sequenceHandle.clone()] } +} + +/// This command adds the last part of data, if any, to a hash/HMAC sequence and returns +/// the result. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct SequenceCompleteResponse { + /// The returned HMAC or digest in a sized buffer + pub result: Vec, + + /// Ticket indicating that the sequence of octets used to compute outDigest did not start + /// with TPM_GENERATED_VALUE + /// This is a NULL Ticket when the sequence is HMAC. + pub validation: TPMT_TK_HASHCHECK, +} + +impl SequenceCompleteResponse { +} + +impl TpmStructure for SequenceCompleteResponse { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.result, 2); + self.validation.toTpm(buf)?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.result = buf.readSizedByteBuf(2); + self.validation.initFromTpm(buf)?; + Ok(()) + } + +} + +impl TpmMarshaller for SequenceCompleteResponse { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for SequenceCompleteResponse { + fn num_handles(&self) -> u16 { 0 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 2, val_len: 1 } } +} + +impl RespStructure for SequenceCompleteResponse { + fn get_handle(&self) -> TPM_HANDLE { TPM_HANDLE::default() } + + fn set_handle(&mut self, _handle: &TPM_HANDLE) { } +} + +/// This command adds the last part of data, if any, to an Event Sequence and returns the +/// result in a digest list. If pcrHandle references a PCR and not TPM_RH_NULL, then the +/// returned digest list is processed in the same manner as the digest list input +/// parameter to TPM2_PCR_Extend(). That is, if a bank contains a PCR associated with +/// pcrHandle, it is extended with the associated digest value from the list. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_EventSequenceComplete_REQUEST { + /// PCR to be extended with the Event data + /// Auth Index: 1 + /// Auth Role: USER + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub pcrHandle: TPM_HANDLE, + + /// Authorization for the sequence + /// Auth Index: 2 + /// Auth Role: USER + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub sequenceHandle: TPM_HANDLE, + + /// Data to be added to the Event + pub buffer: Vec, +} + +impl TPM2_EventSequenceComplete_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + pcrHandle: &TPM_HANDLE, + sequenceHandle: &TPM_HANDLE, + buffer: &Vec, + ) -> Self { + Self { + pcrHandle: pcrHandle.clone(), + sequenceHandle: sequenceHandle.clone(), + buffer: buffer.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_EventSequenceComplete_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.buffer, 2); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.buffer = buf.readSizedByteBuf(2); + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_EventSequenceComplete_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_EventSequenceComplete_REQUEST { + fn num_handles(&self) -> u16 { 2 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 2, val_len: 1 } } +} + +impl ReqStructure for TPM2_EventSequenceComplete_REQUEST { + fn num_auth_handles(&self) -> u16 { 2 } + + fn get_handles(&self) -> Vec { vec![self.pcrHandle.clone(), self.sequenceHandle.clone()] } +} + +/// This command adds the last part of data, if any, to an Event Sequence and returns the +/// result in a digest list. If pcrHandle references a PCR and not TPM_RH_NULL, then the +/// returned digest list is processed in the same manner as the digest list input +/// parameter to TPM2_PCR_Extend(). That is, if a bank contains a PCR associated with +/// pcrHandle, it is extended with the associated digest value from the list. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct EventSequenceCompleteResponse { + /// List of digests computed for the PCR + pub results: Vec, +} + +impl EventSequenceCompleteResponse { +} + +impl TpmStructure for EventSequenceCompleteResponse { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeObjArr(self.results.as_ref())?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + buf.readObjArr(self.results.as_mut())?; + Ok(()) + } + +} + +impl TpmMarshaller for EventSequenceCompleteResponse { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for EventSequenceCompleteResponse { + fn num_handles(&self) -> u16 { 0 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 4, val_len: 66 } } +} + +impl RespStructure for EventSequenceCompleteResponse { + fn get_handle(&self) -> TPM_HANDLE { TPM_HANDLE::default() } + + fn set_handle(&mut self, _handle: &TPM_HANDLE) { } +} + +/// The purpose of this command is to prove that an object with a specific Name is loaded +/// in the TPM. By certifying that the object is loaded, the TPM warrants that a public +/// area with a given Name is self-consistent and associated with a valid sensitive area. +/// If a relying party has a public area that has the same Name as a Name certified with +/// this command, then the values in that public area are correct. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_Certify_REQUEST { + /// Handle of the object to be certified + /// Auth Index: 1 + /// Auth Role: ADMIN + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub objectHandle: TPM_HANDLE, + + /// Handle of the key used to sign the attestation structure + /// Auth Index: 2 + /// Auth Role: USER + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub signHandle: TPM_HANDLE, + + /// User provided qualifying data + pub qualifyingData: Vec, + + /// Scheme selector + + /// Signing scheme to use if the scheme for signHandle is TPM_ALG_NULL + /// One of: TPMS_SIG_SCHEME_RSASSA, TPMS_SIG_SCHEME_RSAPSS, TPMS_SIG_SCHEME_ECDSA, + /// TPMS_SIG_SCHEME_ECDAA, TPMS_SIG_SCHEME_SM2, TPMS_SIG_SCHEME_ECSCHNORR, + /// TPMS_SCHEME_HMAC, TPMS_SCHEME_HASH, TPMS_NULL_SIG_SCHEME. + pub inScheme: Option, +} + +impl TPM2_Certify_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + objectHandle: &TPM_HANDLE, + signHandle: &TPM_HANDLE, + qualifyingData: &Vec, + inScheme: &Option, + ) -> Self { + Self { + objectHandle: objectHandle.clone(), + signHandle: signHandle.clone(), + qualifyingData: qualifyingData.clone(), + inScheme: inScheme.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_Certify_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.qualifyingData, 2); + buf.writeShort(self.inScheme.as_ref().unwrap().GetUnionSelector().into()); + self.inScheme.as_ref().unwrap().toTpm(buf)?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.qualifyingData = buf.readSizedByteBuf(2); + let r#inSchemeScheme: TPM_ALG_ID = TPM_ALG_ID(buf.readShort() as u16); + self.inScheme = TPMU_SIG_SCHEME::create(r#inSchemeScheme)?; + self.inScheme.as_mut().unwrap().initFromTpm(buf)?; + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_Certify_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_Certify_REQUEST { + fn num_handles(&self) -> u16 { 2 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 2, val_len: 1 } } +} + +impl ReqStructure for TPM2_Certify_REQUEST { + fn num_auth_handles(&self) -> u16 { 2 } + + fn get_handles(&self) -> Vec { vec![self.objectHandle.clone(), self.signHandle.clone()] } +} + +/// The purpose of this command is to prove that an object with a specific Name is loaded +/// in the TPM. By certifying that the object is loaded, the TPM warrants that a public +/// area with a given Name is self-consistent and associated with a valid sensitive area. +/// If a relying party has a public area that has the same Name as a Name certified with +/// this command, then the values in that public area are correct. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct CertifyResponse { + /// The structure that was signed + pub certifyInfo: TPMS_ATTEST, + + /// Selector of the algorithm used to construct the signature + + /// The asymmetric signature over certifyInfo using the key referenced by signHandle + /// One of: TPMS_SIGNATURE_RSASSA, TPMS_SIGNATURE_RSAPSS, TPMS_SIGNATURE_ECDSA, + /// TPMS_SIGNATURE_ECDAA, TPMS_SIGNATURE_SM2, TPMS_SIGNATURE_ECSCHNORR, TPMT_HA, + /// TPMS_SCHEME_HASH, TPMS_NULL_SIGNATURE. + pub signature: Option, +} + +impl CertifyResponse { +} + +impl TpmStructure for CertifyResponse { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedObj(&self.certifyInfo)?; + buf.writeShort(self.signature.as_ref().unwrap().GetUnionSelector().into()); + self.signature.as_ref().unwrap().toTpm(buf)?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + buf.readSizedObj(&mut self.certifyInfo)?; + let r#signatureSigAlg: TPM_ALG_ID = TPM_ALG_ID(buf.readShort() as u16); + self.signature = TPMU_SIGNATURE::create(r#signatureSigAlg)?; + self.signature.as_mut().unwrap().initFromTpm(buf)?; + Ok(()) + } + +} + +impl TpmMarshaller for CertifyResponse { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for CertifyResponse { + fn num_handles(&self) -> u16 { 0 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 2, val_len: 1 } } +} + +impl RespStructure for CertifyResponse { + fn get_handle(&self) -> TPM_HANDLE { TPM_HANDLE::default() } + + fn set_handle(&mut self, _handle: &TPM_HANDLE) { } +} + +/// This command is used to prove the association between an object and its creation data. +/// The TPM will validate that the ticket was produced by the TPM and that the ticket +/// validates the association between a loaded public area and the provided hash of the +/// creation data (creationHash). +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_CertifyCreation_REQUEST { + /// Handle of the key that will sign the attestation block + /// Auth Index: 1 + /// Auth Role: USER + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub signHandle: TPM_HANDLE, + + /// The object associated with the creation data + /// Auth Index: None + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub objectHandle: TPM_HANDLE, + + /// User-provided qualifying data + pub qualifyingData: Vec, + + /// Hash of the creation data produced by TPM2_Create() or TPM2_CreatePrimary() + pub creationHash: Vec, + + /// Scheme selector + + /// Signing scheme to use if the scheme for signHandle is TPM_ALG_NULL + /// One of: TPMS_SIG_SCHEME_RSASSA, TPMS_SIG_SCHEME_RSAPSS, TPMS_SIG_SCHEME_ECDSA, + /// TPMS_SIG_SCHEME_ECDAA, TPMS_SIG_SCHEME_SM2, TPMS_SIG_SCHEME_ECSCHNORR, + /// TPMS_SCHEME_HMAC, TPMS_SCHEME_HASH, TPMS_NULL_SIG_SCHEME. + pub inScheme: Option, + + /// Ticket produced by TPM2_Create() or TPM2_CreatePrimary() + pub creationTicket: TPMT_TK_CREATION, +} + +impl TPM2_CertifyCreation_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + signHandle: &TPM_HANDLE, + objectHandle: &TPM_HANDLE, + qualifyingData: &Vec, + creationHash: &Vec, + inScheme: &Option, + creationTicket: &TPMT_TK_CREATION, + ) -> Self { + Self { + signHandle: signHandle.clone(), + objectHandle: objectHandle.clone(), + qualifyingData: qualifyingData.clone(), + creationHash: creationHash.clone(), + inScheme: inScheme.clone(), + creationTicket: creationTicket.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_CertifyCreation_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.qualifyingData, 2); + buf.writeSizedByteBuf(&self.creationHash, 2); + buf.writeShort(self.inScheme.as_ref().unwrap().GetUnionSelector().into()); + self.inScheme.as_ref().unwrap().toTpm(buf)?; + self.creationTicket.toTpm(buf)?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.qualifyingData = buf.readSizedByteBuf(2); + self.creationHash = buf.readSizedByteBuf(2); + let r#inSchemeScheme: TPM_ALG_ID = TPM_ALG_ID(buf.readShort() as u16); + self.inScheme = TPMU_SIG_SCHEME::create(r#inSchemeScheme)?; + self.inScheme.as_mut().unwrap().initFromTpm(buf)?; + self.creationTicket.initFromTpm(buf)?; + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_CertifyCreation_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_CertifyCreation_REQUEST { + fn num_handles(&self) -> u16 { 2 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 2, val_len: 1 } } +} + +impl ReqStructure for TPM2_CertifyCreation_REQUEST { + fn num_auth_handles(&self) -> u16 { 1 } + + fn get_handles(&self) -> Vec { vec![self.signHandle.clone(), self.objectHandle.clone()] } +} + +/// This command is used to prove the association between an object and its creation data. +/// The TPM will validate that the ticket was produced by the TPM and that the ticket +/// validates the association between a loaded public area and the provided hash of the +/// creation data (creationHash). +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct CertifyCreationResponse { + /// The structure that was signed + pub certifyInfo: TPMS_ATTEST, + + /// Selector of the algorithm used to construct the signature + + /// The signature over certifyInfo + /// One of: TPMS_SIGNATURE_RSASSA, TPMS_SIGNATURE_RSAPSS, TPMS_SIGNATURE_ECDSA, + /// TPMS_SIGNATURE_ECDAA, TPMS_SIGNATURE_SM2, TPMS_SIGNATURE_ECSCHNORR, TPMT_HA, + /// TPMS_SCHEME_HASH, TPMS_NULL_SIGNATURE. + pub signature: Option, +} + +impl CertifyCreationResponse { +} + +impl TpmStructure for CertifyCreationResponse { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedObj(&self.certifyInfo)?; + buf.writeShort(self.signature.as_ref().unwrap().GetUnionSelector().into()); + self.signature.as_ref().unwrap().toTpm(buf)?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + buf.readSizedObj(&mut self.certifyInfo)?; + let r#signatureSigAlg: TPM_ALG_ID = TPM_ALG_ID(buf.readShort() as u16); + self.signature = TPMU_SIGNATURE::create(r#signatureSigAlg)?; + self.signature.as_mut().unwrap().initFromTpm(buf)?; + Ok(()) + } + +} + +impl TpmMarshaller for CertifyCreationResponse { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for CertifyCreationResponse { + fn num_handles(&self) -> u16 { 0 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 2, val_len: 1 } } +} + +impl RespStructure for CertifyCreationResponse { + fn get_handle(&self) -> TPM_HANDLE { TPM_HANDLE::default() } + + fn set_handle(&mut self, _handle: &TPM_HANDLE) { } +} + +/// This command is used to quote PCR values. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_Quote_REQUEST { + /// Handle of key that will perform signature + /// Auth Index: 1 + /// Auth Role: USER + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub signHandle: TPM_HANDLE, + + /// Data supplied by the caller + pub qualifyingData: Vec, + + /// Scheme selector + + /// Signing scheme to use if the scheme for signHandle is TPM_ALG_NULL + /// One of: TPMS_SIG_SCHEME_RSASSA, TPMS_SIG_SCHEME_RSAPSS, TPMS_SIG_SCHEME_ECDSA, + /// TPMS_SIG_SCHEME_ECDAA, TPMS_SIG_SCHEME_SM2, TPMS_SIG_SCHEME_ECSCHNORR, + /// TPMS_SCHEME_HMAC, TPMS_SCHEME_HASH, TPMS_NULL_SIG_SCHEME. + pub inScheme: Option, + + /// PCR set to quote + pub PCRselect: Vec, +} + +impl TPM2_Quote_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + signHandle: &TPM_HANDLE, + qualifyingData: &Vec, + inScheme: &Option, + PCRselect: &Vec, + ) -> Self { + Self { + signHandle: signHandle.clone(), + qualifyingData: qualifyingData.clone(), + inScheme: inScheme.clone(), + PCRselect: PCRselect.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_Quote_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.qualifyingData, 2); + buf.writeShort(self.inScheme.as_ref().unwrap().GetUnionSelector().into()); + self.inScheme.as_ref().unwrap().toTpm(buf)?; + buf.writeObjArr(self.PCRselect.as_ref())?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.qualifyingData = buf.readSizedByteBuf(2); + let r#inSchemeScheme: TPM_ALG_ID = TPM_ALG_ID(buf.readShort() as u16); + self.inScheme = TPMU_SIG_SCHEME::create(r#inSchemeScheme)?; + self.inScheme.as_mut().unwrap().initFromTpm(buf)?; + buf.readObjArr(self.PCRselect.as_mut())?; + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_Quote_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_Quote_REQUEST { + fn num_handles(&self) -> u16 { 1 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 2, val_len: 1 } } +} + +impl ReqStructure for TPM2_Quote_REQUEST { + fn num_auth_handles(&self) -> u16 { 1 } + + fn get_handles(&self) -> Vec { vec![self.signHandle.clone()] } +} + +/// This command is used to quote PCR values. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct QuoteResponse { + /// The quoted information + pub quoted: TPMS_ATTEST, + + /// Selector of the algorithm used to construct the signature + + /// The signature over quoted + /// One of: TPMS_SIGNATURE_RSASSA, TPMS_SIGNATURE_RSAPSS, TPMS_SIGNATURE_ECDSA, + /// TPMS_SIGNATURE_ECDAA, TPMS_SIGNATURE_SM2, TPMS_SIGNATURE_ECSCHNORR, TPMT_HA, + /// TPMS_SCHEME_HASH, TPMS_NULL_SIGNATURE. + pub signature: Option, +} + +impl QuoteResponse { +} + +impl TpmStructure for QuoteResponse { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedObj(&self.quoted)?; + buf.writeShort(self.signature.as_ref().unwrap().GetUnionSelector().into()); + self.signature.as_ref().unwrap().toTpm(buf)?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + buf.readSizedObj(&mut self.quoted)?; + let r#signatureSigAlg: TPM_ALG_ID = TPM_ALG_ID(buf.readShort() as u16); + self.signature = TPMU_SIGNATURE::create(r#signatureSigAlg)?; + self.signature.as_mut().unwrap().initFromTpm(buf)?; + Ok(()) + } + +} + +impl TpmMarshaller for QuoteResponse { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for QuoteResponse { + fn num_handles(&self) -> u16 { 0 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 2, val_len: 1 } } +} + +impl RespStructure for QuoteResponse { + fn get_handle(&self) -> TPM_HANDLE { TPM_HANDLE::default() } + + fn set_handle(&mut self, _handle: &TPM_HANDLE) { } +} + +/// This command returns a digital signature of the audit session digest. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_GetSessionAuditDigest_REQUEST { + /// Handle of the privacy administrator (TPM_RH_ENDORSEMENT) + /// Auth Index: 1 + /// Auth Role: USER + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub privacyAdminHandle: TPM_HANDLE, + + /// Handle of the signing key + /// Auth Index: 2 + /// Auth Role: USER + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub signHandle: TPM_HANDLE, + + /// Handle of the audit session + /// Auth Index: None + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub sessionHandle: TPM_HANDLE, + + /// User-provided qualifying data may be zero-length + pub qualifyingData: Vec, + + /// Scheme selector + + /// Signing scheme to use if the scheme for signHandle is TPM_ALG_NULL + /// One of: TPMS_SIG_SCHEME_RSASSA, TPMS_SIG_SCHEME_RSAPSS, TPMS_SIG_SCHEME_ECDSA, + /// TPMS_SIG_SCHEME_ECDAA, TPMS_SIG_SCHEME_SM2, TPMS_SIG_SCHEME_ECSCHNORR, + /// TPMS_SCHEME_HMAC, TPMS_SCHEME_HASH, TPMS_NULL_SIG_SCHEME. + pub inScheme: Option, +} + +impl TPM2_GetSessionAuditDigest_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + privacyAdminHandle: &TPM_HANDLE, + signHandle: &TPM_HANDLE, + sessionHandle: &TPM_HANDLE, + qualifyingData: &Vec, + inScheme: &Option, + ) -> Self { + Self { + privacyAdminHandle: privacyAdminHandle.clone(), + signHandle: signHandle.clone(), + sessionHandle: sessionHandle.clone(), + qualifyingData: qualifyingData.clone(), + inScheme: inScheme.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_GetSessionAuditDigest_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.qualifyingData, 2); + buf.writeShort(self.inScheme.as_ref().unwrap().GetUnionSelector().into()); + self.inScheme.as_ref().unwrap().toTpm(buf)?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.qualifyingData = buf.readSizedByteBuf(2); + let r#inSchemeScheme: TPM_ALG_ID = TPM_ALG_ID(buf.readShort() as u16); + self.inScheme = TPMU_SIG_SCHEME::create(r#inSchemeScheme)?; + self.inScheme.as_mut().unwrap().initFromTpm(buf)?; + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_GetSessionAuditDigest_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_GetSessionAuditDigest_REQUEST { + fn num_handles(&self) -> u16 { 3 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 2, val_len: 1 } } +} + +impl ReqStructure for TPM2_GetSessionAuditDigest_REQUEST { + fn num_auth_handles(&self) -> u16 { 2 } + + fn get_handles(&self) -> Vec { vec![self.privacyAdminHandle.clone(), self.signHandle.clone(), self.sessionHandle.clone()] } +} + +/// This command returns a digital signature of the audit session digest. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct GetSessionAuditDigestResponse { + /// The audit information that was signed + pub auditInfo: TPMS_ATTEST, + + /// Selector of the algorithm used to construct the signature + + /// The signature over auditInfo + /// One of: TPMS_SIGNATURE_RSASSA, TPMS_SIGNATURE_RSAPSS, TPMS_SIGNATURE_ECDSA, + /// TPMS_SIGNATURE_ECDAA, TPMS_SIGNATURE_SM2, TPMS_SIGNATURE_ECSCHNORR, TPMT_HA, + /// TPMS_SCHEME_HASH, TPMS_NULL_SIGNATURE. + pub signature: Option, +} + +impl GetSessionAuditDigestResponse { +} + +impl TpmStructure for GetSessionAuditDigestResponse { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedObj(&self.auditInfo)?; + buf.writeShort(self.signature.as_ref().unwrap().GetUnionSelector().into()); + self.signature.as_ref().unwrap().toTpm(buf)?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + buf.readSizedObj(&mut self.auditInfo)?; + let r#signatureSigAlg: TPM_ALG_ID = TPM_ALG_ID(buf.readShort() as u16); + self.signature = TPMU_SIGNATURE::create(r#signatureSigAlg)?; + self.signature.as_mut().unwrap().initFromTpm(buf)?; + Ok(()) + } + +} + +impl TpmMarshaller for GetSessionAuditDigestResponse { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for GetSessionAuditDigestResponse { + fn num_handles(&self) -> u16 { 0 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 2, val_len: 1 } } +} + +impl RespStructure for GetSessionAuditDigestResponse { + fn get_handle(&self) -> TPM_HANDLE { TPM_HANDLE::default() } + + fn set_handle(&mut self, _handle: &TPM_HANDLE) { } +} + +/// This command returns the current value of the command audit digest, a digest of the +/// commands being audited, and the audit hash algorithm. These values are placed in an +/// attestation structure and signed with the key referenced by signHandle. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_GetCommandAuditDigest_REQUEST { + /// Handle of the privacy administrator (TPM_RH_ENDORSEMENT) + /// Auth Index: 1 + /// Auth Role: USER + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub privacyHandle: TPM_HANDLE, + + /// The handle of the signing key + /// Auth Index: 2 + /// Auth Role: USER + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub signHandle: TPM_HANDLE, + + /// Other data to associate with this audit digest + pub qualifyingData: Vec, + + /// Scheme selector + + /// Signing scheme to use if the scheme for signHandle is TPM_ALG_NULL + /// One of: TPMS_SIG_SCHEME_RSASSA, TPMS_SIG_SCHEME_RSAPSS, TPMS_SIG_SCHEME_ECDSA, + /// TPMS_SIG_SCHEME_ECDAA, TPMS_SIG_SCHEME_SM2, TPMS_SIG_SCHEME_ECSCHNORR, + /// TPMS_SCHEME_HMAC, TPMS_SCHEME_HASH, TPMS_NULL_SIG_SCHEME. + pub inScheme: Option, +} + +impl TPM2_GetCommandAuditDigest_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + privacyHandle: &TPM_HANDLE, + signHandle: &TPM_HANDLE, + qualifyingData: &Vec, + inScheme: &Option, + ) -> Self { + Self { + privacyHandle: privacyHandle.clone(), + signHandle: signHandle.clone(), + qualifyingData: qualifyingData.clone(), + inScheme: inScheme.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_GetCommandAuditDigest_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.qualifyingData, 2); + buf.writeShort(self.inScheme.as_ref().unwrap().GetUnionSelector().into()); + self.inScheme.as_ref().unwrap().toTpm(buf)?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.qualifyingData = buf.readSizedByteBuf(2); + let r#inSchemeScheme: TPM_ALG_ID = TPM_ALG_ID(buf.readShort() as u16); + self.inScheme = TPMU_SIG_SCHEME::create(r#inSchemeScheme)?; + self.inScheme.as_mut().unwrap().initFromTpm(buf)?; + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_GetCommandAuditDigest_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_GetCommandAuditDigest_REQUEST { + fn num_handles(&self) -> u16 { 2 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 2, val_len: 1 } } +} + +impl ReqStructure for TPM2_GetCommandAuditDigest_REQUEST { + fn num_auth_handles(&self) -> u16 { 2 } + + fn get_handles(&self) -> Vec { vec![self.privacyHandle.clone(), self.signHandle.clone()] } +} + +/// This command returns the current value of the command audit digest, a digest of the +/// commands being audited, and the audit hash algorithm. These values are placed in an +/// attestation structure and signed with the key referenced by signHandle. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct GetCommandAuditDigestResponse { + /// The auditInfo that was signed + pub auditInfo: TPMS_ATTEST, + + /// Selector of the algorithm used to construct the signature + + /// The signature over auditInfo + /// One of: TPMS_SIGNATURE_RSASSA, TPMS_SIGNATURE_RSAPSS, TPMS_SIGNATURE_ECDSA, + /// TPMS_SIGNATURE_ECDAA, TPMS_SIGNATURE_SM2, TPMS_SIGNATURE_ECSCHNORR, TPMT_HA, + /// TPMS_SCHEME_HASH, TPMS_NULL_SIGNATURE. + pub signature: Option, +} + +impl GetCommandAuditDigestResponse { +} + +impl TpmStructure for GetCommandAuditDigestResponse { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedObj(&self.auditInfo)?; + buf.writeShort(self.signature.as_ref().unwrap().GetUnionSelector().into()); + self.signature.as_ref().unwrap().toTpm(buf)?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + buf.readSizedObj(&mut self.auditInfo)?; + let r#signatureSigAlg: TPM_ALG_ID = TPM_ALG_ID(buf.readShort() as u16); + self.signature = TPMU_SIGNATURE::create(r#signatureSigAlg)?; + self.signature.as_mut().unwrap().initFromTpm(buf)?; + Ok(()) + } + +} + +impl TpmMarshaller for GetCommandAuditDigestResponse { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for GetCommandAuditDigestResponse { + fn num_handles(&self) -> u16 { 0 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 2, val_len: 1 } } +} + +impl RespStructure for GetCommandAuditDigestResponse { + fn get_handle(&self) -> TPM_HANDLE { TPM_HANDLE::default() } + + fn set_handle(&mut self, _handle: &TPM_HANDLE) { } +} + +/// This command returns the current values of Time and Clock. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_GetTime_REQUEST { + /// Handle of the privacy administrator (TPM_RH_ENDORSEMENT) + /// Auth Index: 1 + /// Auth Role: USER + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub privacyAdminHandle: TPM_HANDLE, + + /// The keyHandle identifier of a loaded key that can perform digital signatures + /// Auth Index: 2 + /// Auth Role: USER + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub signHandle: TPM_HANDLE, + + /// Data to tick stamp + pub qualifyingData: Vec, + + /// Scheme selector + + /// Signing scheme to use if the scheme for signHandle is TPM_ALG_NULL + /// One of: TPMS_SIG_SCHEME_RSASSA, TPMS_SIG_SCHEME_RSAPSS, TPMS_SIG_SCHEME_ECDSA, + /// TPMS_SIG_SCHEME_ECDAA, TPMS_SIG_SCHEME_SM2, TPMS_SIG_SCHEME_ECSCHNORR, + /// TPMS_SCHEME_HMAC, TPMS_SCHEME_HASH, TPMS_NULL_SIG_SCHEME. + pub inScheme: Option, +} + +impl TPM2_GetTime_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + privacyAdminHandle: &TPM_HANDLE, + signHandle: &TPM_HANDLE, + qualifyingData: &Vec, + inScheme: &Option, + ) -> Self { + Self { + privacyAdminHandle: privacyAdminHandle.clone(), + signHandle: signHandle.clone(), + qualifyingData: qualifyingData.clone(), + inScheme: inScheme.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_GetTime_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.qualifyingData, 2); + buf.writeShort(self.inScheme.as_ref().unwrap().GetUnionSelector().into()); + self.inScheme.as_ref().unwrap().toTpm(buf)?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.qualifyingData = buf.readSizedByteBuf(2); + let r#inSchemeScheme: TPM_ALG_ID = TPM_ALG_ID(buf.readShort() as u16); + self.inScheme = TPMU_SIG_SCHEME::create(r#inSchemeScheme)?; + self.inScheme.as_mut().unwrap().initFromTpm(buf)?; + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_GetTime_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_GetTime_REQUEST { + fn num_handles(&self) -> u16 { 2 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 2, val_len: 1 } } +} + +impl ReqStructure for TPM2_GetTime_REQUEST { + fn num_auth_handles(&self) -> u16 { 2 } + + fn get_handles(&self) -> Vec { vec![self.privacyAdminHandle.clone(), self.signHandle.clone()] } +} + +/// This command returns the current values of Time and Clock. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct GetTimeResponse { + /// Standard TPM-generated attestation block + pub timeInfo: TPMS_ATTEST, + + /// Selector of the algorithm used to construct the signature + + /// The signature over timeInfo + /// One of: TPMS_SIGNATURE_RSASSA, TPMS_SIGNATURE_RSAPSS, TPMS_SIGNATURE_ECDSA, + /// TPMS_SIGNATURE_ECDAA, TPMS_SIGNATURE_SM2, TPMS_SIGNATURE_ECSCHNORR, TPMT_HA, + /// TPMS_SCHEME_HASH, TPMS_NULL_SIGNATURE. + pub signature: Option, +} + +impl GetTimeResponse { +} + +impl TpmStructure for GetTimeResponse { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedObj(&self.timeInfo)?; + buf.writeShort(self.signature.as_ref().unwrap().GetUnionSelector().into()); + self.signature.as_ref().unwrap().toTpm(buf)?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + buf.readSizedObj(&mut self.timeInfo)?; + let r#signatureSigAlg: TPM_ALG_ID = TPM_ALG_ID(buf.readShort() as u16); + self.signature = TPMU_SIGNATURE::create(r#signatureSigAlg)?; + self.signature.as_mut().unwrap().initFromTpm(buf)?; + Ok(()) + } + +} + +impl TpmMarshaller for GetTimeResponse { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for GetTimeResponse { + fn num_handles(&self) -> u16 { 0 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 2, val_len: 1 } } +} + +impl RespStructure for GetTimeResponse { + fn get_handle(&self) -> TPM_HANDLE { TPM_HANDLE::default() } + + fn set_handle(&mut self, _handle: &TPM_HANDLE) { } +} + +/// The purpose of this command is to generate an X.509 certificate that proves an object +/// with a specific public key and attributes is loaded in the TPM. In contrast to +/// TPM2_Certify, which uses a TCG-defined data structure to convey attestation +/// information, TPM2_CertifyX509 encodes the attestation information in a DER-encoded +/// X.509 certificate that is compliant with RFC5280 Internet X.509 Public Key +/// Infrastructure Certificate and Certificate Revocation List (CRL) Profile. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_CertifyX509_REQUEST { + /// Handle of the object to be certified + /// Auth Index: 1 + /// Auth Role: ADMIN + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub objectHandle: TPM_HANDLE, + + /// Handle of the key used to sign the attestation structure + /// Auth Index: 2 + /// Auth Role: USER + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub signHandle: TPM_HANDLE, + + /// Shall be an Empty Buffer + pub reserved: Vec, + + /// Scheme selector + + /// Signing scheme to use if the scheme for signHandle is TPM_ALG_NULL + /// One of: TPMS_SIG_SCHEME_RSASSA, TPMS_SIG_SCHEME_RSAPSS, TPMS_SIG_SCHEME_ECDSA, + /// TPMS_SIG_SCHEME_ECDAA, TPMS_SIG_SCHEME_SM2, TPMS_SIG_SCHEME_ECSCHNORR, + /// TPMS_SCHEME_HMAC, TPMS_SCHEME_HASH, TPMS_NULL_SIG_SCHEME. + pub inScheme: Option, + + /// A DER encoded partial certificate + pub partialCertificate: Vec, +} + +impl TPM2_CertifyX509_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + objectHandle: &TPM_HANDLE, + signHandle: &TPM_HANDLE, + reserved: &Vec, + inScheme: &Option, + partialCertificate: &Vec, + ) -> Self { + Self { + objectHandle: objectHandle.clone(), + signHandle: signHandle.clone(), + reserved: reserved.clone(), + inScheme: inScheme.clone(), + partialCertificate: partialCertificate.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_CertifyX509_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.reserved, 2); + buf.writeShort(self.inScheme.as_ref().unwrap().GetUnionSelector().into()); + self.inScheme.as_ref().unwrap().toTpm(buf)?; + buf.writeSizedByteBuf(&self.partialCertificate, 2); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.reserved = buf.readSizedByteBuf(2); + let r#inSchemeScheme: TPM_ALG_ID = TPM_ALG_ID(buf.readShort() as u16); + self.inScheme = TPMU_SIG_SCHEME::create(r#inSchemeScheme)?; + self.inScheme.as_mut().unwrap().initFromTpm(buf)?; + self.partialCertificate = buf.readSizedByteBuf(2); + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_CertifyX509_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_CertifyX509_REQUEST { + fn num_handles(&self) -> u16 { 2 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 2, val_len: 1 } } +} + +impl ReqStructure for TPM2_CertifyX509_REQUEST { + fn num_auth_handles(&self) -> u16 { 2 } + + fn get_handles(&self) -> Vec { vec![self.objectHandle.clone(), self.signHandle.clone()] } +} + +/// The purpose of this command is to generate an X.509 certificate that proves an object +/// with a specific public key and attributes is loaded in the TPM. In contrast to +/// TPM2_Certify, which uses a TCG-defined data structure to convey attestation +/// information, TPM2_CertifyX509 encodes the attestation information in a DER-encoded +/// X.509 certificate that is compliant with RFC5280 Internet X.509 Public Key +/// Infrastructure Certificate and Certificate Revocation List (CRL) Profile. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct CertifyX509Response { + /// A DER encoded SEQUENCE containing the DER encoded fields added to partialCertificate + /// to make it a complete RFC5280 TBSCertificate. + pub addedToCertificate: Vec, + + /// The digest that was signed + pub tbsDigest: Vec, + + /// Selector of the algorithm used to construct the signature + + /// The signature over tbsDigest + /// One of: TPMS_SIGNATURE_RSASSA, TPMS_SIGNATURE_RSAPSS, TPMS_SIGNATURE_ECDSA, + /// TPMS_SIGNATURE_ECDAA, TPMS_SIGNATURE_SM2, TPMS_SIGNATURE_ECSCHNORR, TPMT_HA, + /// TPMS_SCHEME_HASH, TPMS_NULL_SIGNATURE. + pub signature: Option, +} + +impl CertifyX509Response { +} + +impl TpmStructure for CertifyX509Response { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.addedToCertificate, 2); + buf.writeSizedByteBuf(&self.tbsDigest, 2); + buf.writeShort(self.signature.as_ref().unwrap().GetUnionSelector().into()); + self.signature.as_ref().unwrap().toTpm(buf)?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.addedToCertificate = buf.readSizedByteBuf(2); + self.tbsDigest = buf.readSizedByteBuf(2); + let r#signatureSigAlg: TPM_ALG_ID = TPM_ALG_ID(buf.readShort() as u16); + self.signature = TPMU_SIGNATURE::create(r#signatureSigAlg)?; + self.signature.as_mut().unwrap().initFromTpm(buf)?; + Ok(()) + } + +} + +impl TpmMarshaller for CertifyX509Response { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for CertifyX509Response { + fn num_handles(&self) -> u16 { 0 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 2, val_len: 1 } } +} + +impl RespStructure for CertifyX509Response { + fn get_handle(&self) -> TPM_HANDLE { TPM_HANDLE::default() } + + fn set_handle(&mut self, _handle: &TPM_HANDLE) { } +} + +/// TPM2_Commit() performs the first part of an ECC anonymous signing operation. The TPM +/// will perform the point multiplications on the provided points and return intermediate +/// signing values. The signHandle parameter shall refer to an ECC key and the signing +/// scheme must be anonymous (TPM_RC_SCHEME). +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_Commit_REQUEST { + /// Handle of the key that will be used in the signing operation + /// Auth Index: 1 + /// Auth Role: USER + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub signHandle: TPM_HANDLE, + + /// A point (M) on the curve used by signHandle + pub P1: TPMS_ECC_POINT, + + /// Octet array used to derive x-coordinate of a base point + pub s2: Vec, + + /// Y coordinate of the point associated with s2 + pub y2: Vec, +} + +impl TPM2_Commit_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + signHandle: &TPM_HANDLE, + P1: &TPMS_ECC_POINT, + s2: &Vec, + y2: &Vec, + ) -> Self { + Self { + signHandle: signHandle.clone(), + P1: P1.clone(), + s2: s2.clone(), + y2: y2.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_Commit_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedObj(&self.P1)?; + buf.writeSizedByteBuf(&self.s2, 2); + buf.writeSizedByteBuf(&self.y2, 2); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + buf.readSizedObj(&mut self.P1)?; + self.s2 = buf.readSizedByteBuf(2); + self.y2 = buf.readSizedByteBuf(2); + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_Commit_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_Commit_REQUEST { + fn num_handles(&self) -> u16 { 1 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 2, val_len: 1 } } +} + +impl ReqStructure for TPM2_Commit_REQUEST { + fn num_auth_handles(&self) -> u16 { 1 } + + fn get_handles(&self) -> Vec { vec![self.signHandle.clone()] } +} + +/// TPM2_Commit() performs the first part of an ECC anonymous signing operation. The TPM +/// will perform the point multiplications on the provided points and return intermediate +/// signing values. The signHandle parameter shall refer to an ECC key and the signing +/// scheme must be anonymous (TPM_RC_SCHEME). +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct CommitResponse { + /// ECC point K [ds](x2, y2) + pub K: TPMS_ECC_POINT, + + /// ECC point L [r](x2, y2) + pub L: TPMS_ECC_POINT, + + /// ECC point E [r]P1 + pub E: TPMS_ECC_POINT, + + /// Least-significant 16 bits of commitCount + pub counter: u16, +} + +impl CommitResponse { +} + +impl TpmStructure for CommitResponse { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedObj(&self.K)?; + buf.writeSizedObj(&self.L)?; + buf.writeSizedObj(&self.E)?; + buf.writeShort(self.counter as u16); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + buf.readSizedObj(&mut self.K)?; + buf.readSizedObj(&mut self.L)?; + buf.readSizedObj(&mut self.E)?; + self.counter = buf.readShort() as u16; + Ok(()) + } + +} + +impl TpmMarshaller for CommitResponse { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for CommitResponse { + fn num_handles(&self) -> u16 { 0 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 2, val_len: 1 } } +} + +impl RespStructure for CommitResponse { + fn get_handle(&self) -> TPM_HANDLE { TPM_HANDLE::default() } + + fn set_handle(&mut self, _handle: &TPM_HANDLE) { } +} + +/// TPM2_EC_Ephemeral() creates an ephemeral key for use in a two-phase key exchange protocol. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_EC_Ephemeral_REQUEST { + /// The curve for the computed ephemeral point + pub curveID: TPM_ECC_CURVE, +} + +impl TPM2_EC_Ephemeral_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + curveID: TPM_ECC_CURVE, + ) -> Self { + Self { + curveID: curveID.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_EC_Ephemeral_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeShort(self.curveID.into()); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.curveID = TPM_ECC_CURVE(buf.readShort() as u16); + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_EC_Ephemeral_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_EC_Ephemeral_REQUEST { + fn num_handles(&self) -> u16 { 0 } + +} + +impl ReqStructure for TPM2_EC_Ephemeral_REQUEST { + fn num_auth_handles(&self) -> u16 { 0 } + + fn get_handles(&self) -> Vec { vec![] } +} + +/// TPM2_EC_Ephemeral() creates an ephemeral key for use in a two-phase key exchange protocol. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct EC_EphemeralResponse { + /// Ephemeral public key Q [r]G + pub Q: TPMS_ECC_POINT, + + /// Least-significant 16 bits of commitCount + pub counter: u16, +} + +impl EC_EphemeralResponse { +} + +impl TpmStructure for EC_EphemeralResponse { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedObj(&self.Q)?; + buf.writeShort(self.counter as u16); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + buf.readSizedObj(&mut self.Q)?; + self.counter = buf.readShort() as u16; + Ok(()) + } + +} + +impl TpmMarshaller for EC_EphemeralResponse { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for EC_EphemeralResponse { + fn num_handles(&self) -> u16 { 0 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 2, val_len: 1 } } +} + +impl RespStructure for EC_EphemeralResponse { + fn get_handle(&self) -> TPM_HANDLE { TPM_HANDLE::default() } + + fn set_handle(&mut self, _handle: &TPM_HANDLE) { } +} + +/// This command uses loaded keys to validate a signature on a message with the message +/// digest passed to the TPM. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_VerifySignature_REQUEST { + /// Handle of public key that will be used in the validation + /// Auth Index: None + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub keyHandle: TPM_HANDLE, + + /// Digest of the signed message + pub digest: Vec, + + /// Selector of the algorithm used to construct the signature + + /// Signature to be tested + /// One of: TPMS_SIGNATURE_RSASSA, TPMS_SIGNATURE_RSAPSS, TPMS_SIGNATURE_ECDSA, + /// TPMS_SIGNATURE_ECDAA, TPMS_SIGNATURE_SM2, TPMS_SIGNATURE_ECSCHNORR, TPMT_HA, + /// TPMS_SCHEME_HASH, TPMS_NULL_SIGNATURE. + pub signature: Option, +} + +impl TPM2_VerifySignature_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + keyHandle: &TPM_HANDLE, + digest: &Vec, + signature: &Option, + ) -> Self { + Self { + keyHandle: keyHandle.clone(), + digest: digest.clone(), + signature: signature.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_VerifySignature_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.digest, 2); + buf.writeShort(self.signature.as_ref().unwrap().GetUnionSelector().into()); + self.signature.as_ref().unwrap().toTpm(buf)?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.digest = buf.readSizedByteBuf(2); + let r#signatureSigAlg: TPM_ALG_ID = TPM_ALG_ID(buf.readShort() as u16); + self.signature = TPMU_SIGNATURE::create(r#signatureSigAlg)?; + self.signature.as_mut().unwrap().initFromTpm(buf)?; + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_VerifySignature_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_VerifySignature_REQUEST { + fn num_handles(&self) -> u16 { 1 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 2, val_len: 1 } } +} + +impl ReqStructure for TPM2_VerifySignature_REQUEST { + fn num_auth_handles(&self) -> u16 { 0 } + + fn get_handles(&self) -> Vec { vec![self.keyHandle.clone()] } +} + +/// This command uses loaded keys to validate a signature on a message with the message +/// digest passed to the TPM. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct VerifySignatureResponse { + pub validation: TPMT_TK_VERIFIED, +} + +impl VerifySignatureResponse { +} + +impl TpmStructure for VerifySignatureResponse { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + self.validation.toTpm(buf)?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.validation.initFromTpm(buf)?; + Ok(()) + } + +} + +impl TpmMarshaller for VerifySignatureResponse { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for VerifySignatureResponse { + fn num_handles(&self) -> u16 { 0 } + +} + +impl RespStructure for VerifySignatureResponse { + fn get_handle(&self) -> TPM_HANDLE { TPM_HANDLE::default() } + + fn set_handle(&mut self, _handle: &TPM_HANDLE) { } +} + +/// This command causes the TPM to sign an externally provided hash with the specified +/// symmetric or asymmetric signing key. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_Sign_REQUEST { + /// Handle of key that will perform signing + /// Auth Index: 1 + /// Auth Role: USER + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub keyHandle: TPM_HANDLE, + + /// Digest to be signed + pub digest: Vec, + + /// Scheme selector + + /// Signing scheme to use if the scheme for keyHandle is TPM_ALG_NULL + /// One of: TPMS_SIG_SCHEME_RSASSA, TPMS_SIG_SCHEME_RSAPSS, TPMS_SIG_SCHEME_ECDSA, + /// TPMS_SIG_SCHEME_ECDAA, TPMS_SIG_SCHEME_SM2, TPMS_SIG_SCHEME_ECSCHNORR, + /// TPMS_SCHEME_HMAC, TPMS_SCHEME_HASH, TPMS_NULL_SIG_SCHEME. + pub inScheme: Option, + + /// Proof that digest was created by the TPM + /// If keyHandle is not a restricted signing key, then this may be a NULL Ticket with tag + /// = TPM_ST_CHECKHASH. + pub validation: TPMT_TK_HASHCHECK, +} + +impl TPM2_Sign_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + keyHandle: &TPM_HANDLE, + digest: &Vec, + inScheme: &Option, + validation: &TPMT_TK_HASHCHECK, + ) -> Self { + Self { + keyHandle: keyHandle.clone(), + digest: digest.clone(), + inScheme: inScheme.clone(), + validation: validation.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_Sign_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.digest, 2); + buf.writeShort(self.inScheme.as_ref().unwrap().GetUnionSelector().into()); + self.inScheme.as_ref().unwrap().toTpm(buf)?; + self.validation.toTpm(buf)?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.digest = buf.readSizedByteBuf(2); + let r#inSchemeScheme: TPM_ALG_ID = TPM_ALG_ID(buf.readShort() as u16); + self.inScheme = TPMU_SIG_SCHEME::create(r#inSchemeScheme)?; + self.inScheme.as_mut().unwrap().initFromTpm(buf)?; + self.validation.initFromTpm(buf)?; + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_Sign_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_Sign_REQUEST { + fn num_handles(&self) -> u16 { 1 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 2, val_len: 1 } } +} + +impl ReqStructure for TPM2_Sign_REQUEST { + fn num_auth_handles(&self) -> u16 { 1 } + + fn get_handles(&self) -> Vec { vec![self.keyHandle.clone()] } +} + +/// This command causes the TPM to sign an externally provided hash with the specified +/// symmetric or asymmetric signing key. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct SignResponse { + /// Selector of the algorithm used to construct the signature + + /// The signature + /// One of: TPMS_SIGNATURE_RSASSA, TPMS_SIGNATURE_RSAPSS, TPMS_SIGNATURE_ECDSA, + /// TPMS_SIGNATURE_ECDAA, TPMS_SIGNATURE_SM2, TPMS_SIGNATURE_ECSCHNORR, TPMT_HA, + /// TPMS_SCHEME_HASH, TPMS_NULL_SIGNATURE. + pub signature: Option, +} + +impl SignResponse { +} + +impl TpmStructure for SignResponse { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + if (self.signature.is_none()) { return Ok(()) }; + buf.writeShort(self.signature.as_ref().unwrap().GetUnionSelector().into()); + self.signature.as_ref().unwrap().toTpm(buf)?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + let r#signatureSigAlg: TPM_ALG_ID = TPM_ALG_ID(buf.readShort() as u16); + self.signature = TPMU_SIGNATURE::create(r#signatureSigAlg)?; + self.signature.as_mut().unwrap().initFromTpm(buf)?; + Ok(()) + } + +} + +impl TpmMarshaller for SignResponse { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for SignResponse { + fn num_handles(&self) -> u16 { 0 } + +} + +impl RespStructure for SignResponse { + fn get_handle(&self) -> TPM_HANDLE { TPM_HANDLE::default() } + + fn set_handle(&mut self, _handle: &TPM_HANDLE) { } +} + +/// This command may be used by the Privacy Administrator or platform to change the audit +/// status of a command or to set the hash algorithm used for the audit digest, but not +/// both at the same time. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_SetCommandCodeAuditStatus_REQUEST { + /// TPM_RH_OWNER or TPM_RH_PLATFORM+{PP} + /// Auth Index: 1 + /// Auth Role: USER + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub auth: TPM_HANDLE, + + /// Hash algorithm for the audit digest; if TPM_ALG_NULL, then the hash is not changed + #[derivative(Default(value="TPM_ALG_ID::NULL"))] + pub auditAlg: TPM_ALG_ID, + + /// List of commands that will be added to those that will be audited + pub setList: Vec, + + /// List of commands that will no longer be audited + pub clearList: Vec, +} + +impl TPM2_SetCommandCodeAuditStatus_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + auth: &TPM_HANDLE, + auditAlg: TPM_ALG_ID, + setList: &Vec, + clearList: &Vec, + ) -> Self { + Self { + auth: auth.clone(), + auditAlg: auditAlg.clone(), + setList: setList.clone(), + clearList: clearList.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_SetCommandCodeAuditStatus_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeShort(self.auditAlg.into()); + buf.writeValArr(self.setList.as_ref(), 4); + buf.writeValArr(self.clearList.as_ref(), 4); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.auditAlg = TPM_ALG_ID(buf.readShort() as u16); + buf.readValArr(self.setList.as_mut(), 4)?; + buf.readValArr(self.clearList.as_mut(), 4)?; + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_SetCommandCodeAuditStatus_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_SetCommandCodeAuditStatus_REQUEST { + fn num_handles(&self) -> u16 { 1 } + +} + +impl ReqStructure for TPM2_SetCommandCodeAuditStatus_REQUEST { + fn num_auth_handles(&self) -> u16 { 1 } + + fn get_handles(&self) -> Vec { vec![self.auth.clone()] } +} + +/// This command is used to cause an update to the indicated PCR. The digests parameter +/// contains one or more tagged digest values identified by an algorithm ID. For each +/// digest, the PCR associated with pcrHandle is Extended into the bank identified by the +/// tag (hashAlg). +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_PCR_Extend_REQUEST { + /// Handle of the PCR + /// Auth Handle: 1 + /// Auth Role: USER + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub pcrHandle: TPM_HANDLE, + + /// List of tagged digest values to be extended + pub digests: Vec, +} + +impl TPM2_PCR_Extend_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + pcrHandle: &TPM_HANDLE, + digests: &Vec, + ) -> Self { + Self { + pcrHandle: pcrHandle.clone(), + digests: digests.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_PCR_Extend_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeObjArr(self.digests.as_ref())?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + buf.readObjArr(self.digests.as_mut())?; + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_PCR_Extend_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_PCR_Extend_REQUEST { + fn num_handles(&self) -> u16 { 1 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 4, val_len: 66 } } +} + +impl ReqStructure for TPM2_PCR_Extend_REQUEST { + fn num_auth_handles(&self) -> u16 { 1 } + + fn get_handles(&self) -> Vec { vec![self.pcrHandle.clone()] } +} + +/// This command is used to cause an update to the indicated PCR. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_PCR_Event_REQUEST { + /// Handle of the PCR + /// Auth Handle: 1 + /// Auth Role: USER + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub pcrHandle: TPM_HANDLE, + + /// Event data in sized buffer + pub eventData: Vec, +} + +impl TPM2_PCR_Event_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + pcrHandle: &TPM_HANDLE, + eventData: &Vec, + ) -> Self { + Self { + pcrHandle: pcrHandle.clone(), + eventData: eventData.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_PCR_Event_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.eventData, 2); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.eventData = buf.readSizedByteBuf(2); + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_PCR_Event_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_PCR_Event_REQUEST { + fn num_handles(&self) -> u16 { 1 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 2, val_len: 1 } } +} + +impl ReqStructure for TPM2_PCR_Event_REQUEST { + fn num_auth_handles(&self) -> u16 { 1 } + + fn get_handles(&self) -> Vec { vec![self.pcrHandle.clone()] } +} + +/// This command is used to cause an update to the indicated PCR. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct PCR_EventResponse { + pub digests: Vec, +} + +impl PCR_EventResponse { +} + +impl TpmStructure for PCR_EventResponse { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeObjArr(self.digests.as_ref())?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + buf.readObjArr(self.digests.as_mut())?; + Ok(()) + } + +} + +impl TpmMarshaller for PCR_EventResponse { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for PCR_EventResponse { + fn num_handles(&self) -> u16 { 0 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 4, val_len: 66 } } +} + +impl RespStructure for PCR_EventResponse { + fn get_handle(&self) -> TPM_HANDLE { TPM_HANDLE::default() } + + fn set_handle(&mut self, _handle: &TPM_HANDLE) { } +} + +/// This command returns the values of all PCR specified in pcrSelectionIn. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_PCR_Read_REQUEST { + /// The selection of PCR to read + pub pcrSelectionIn: Vec, +} + +impl TPM2_PCR_Read_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + pcrSelectionIn: &Vec, + ) -> Self { + Self { + pcrSelectionIn: pcrSelectionIn.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_PCR_Read_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeObjArr(self.pcrSelectionIn.as_ref())?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + buf.readObjArr(self.pcrSelectionIn.as_mut())?; + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_PCR_Read_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_PCR_Read_REQUEST { + fn num_handles(&self) -> u16 { 0 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 4, val_len: 3 } } +} + +impl ReqStructure for TPM2_PCR_Read_REQUEST { + fn num_auth_handles(&self) -> u16 { 0 } + + fn get_handles(&self) -> Vec { vec![] } +} + +/// This command returns the values of all PCR specified in pcrSelectionIn. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct PCR_ReadResponse { + /// The current value of the PCR update counter + pub pcrUpdateCounter: u32, + + /// The PCR in the returned list + pub pcrSelectionOut: Vec, + + /// The contents of the PCR indicated in pcrSelectOut-˃ pcrSelection[] as tagged digests + pub pcrValues: Vec, +} + +impl PCR_ReadResponse { +} + +impl TpmStructure for PCR_ReadResponse { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeInt(self.pcrUpdateCounter as u32); + buf.writeObjArr(self.pcrSelectionOut.as_ref())?; + buf.writeObjArr(self.pcrValues.as_ref())?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.pcrUpdateCounter = buf.readInt() as u32; + buf.readObjArr(self.pcrSelectionOut.as_mut())?; + buf.readObjArr(self.pcrValues.as_mut())?; + Ok(()) + } + +} + +impl TpmMarshaller for PCR_ReadResponse { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for PCR_ReadResponse { + fn num_handles(&self) -> u16 { 0 } + +} + +impl RespStructure for PCR_ReadResponse { + fn get_handle(&self) -> TPM_HANDLE { TPM_HANDLE::default() } + + fn set_handle(&mut self, _handle: &TPM_HANDLE) { } +} + +/// This command is used to set the desired PCR allocation of PCR and algorithms. This +/// command requires Platform Authorization. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_PCR_Allocate_REQUEST { + /// TPM_RH_PLATFORM+{PP} + /// Auth Index: 1 + /// Auth Role: USER + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub authHandle: TPM_HANDLE, + + /// The requested allocation + pub pcrAllocation: Vec, +} + +impl TPM2_PCR_Allocate_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + authHandle: &TPM_HANDLE, + pcrAllocation: &Vec, + ) -> Self { + Self { + authHandle: authHandle.clone(), + pcrAllocation: pcrAllocation.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_PCR_Allocate_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeObjArr(self.pcrAllocation.as_ref())?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + buf.readObjArr(self.pcrAllocation.as_mut())?; + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_PCR_Allocate_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_PCR_Allocate_REQUEST { + fn num_handles(&self) -> u16 { 1 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 4, val_len: 3 } } +} + +impl ReqStructure for TPM2_PCR_Allocate_REQUEST { + fn num_auth_handles(&self) -> u16 { 1 } + + fn get_handles(&self) -> Vec { vec![self.authHandle.clone()] } +} + +/// This command is used to set the desired PCR allocation of PCR and algorithms. This +/// command requires Platform Authorization. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct PCR_AllocateResponse { + /// YES if the allocation succeeded + pub allocationSuccess: u8, + + /// Maximum number of PCR that may be in a bank + pub maxPCR: u32, + + /// Number of octets required to satisfy the request + pub sizeNeeded: u32, + + /// Number of octets available. Computed before the allocation. + pub sizeAvailable: u32, +} + +impl PCR_AllocateResponse { +} + +impl TpmStructure for PCR_AllocateResponse { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeByte(self.allocationSuccess as u8); + buf.writeInt(self.maxPCR as u32); + buf.writeInt(self.sizeNeeded as u32); + buf.writeInt(self.sizeAvailable as u32); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.allocationSuccess = buf.readByte() as u8; + self.maxPCR = buf.readInt() as u32; + self.sizeNeeded = buf.readInt() as u32; + self.sizeAvailable = buf.readInt() as u32; + Ok(()) + } + +} + +impl TpmMarshaller for PCR_AllocateResponse { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for PCR_AllocateResponse { + fn num_handles(&self) -> u16 { 0 } + +} + +impl RespStructure for PCR_AllocateResponse { + fn get_handle(&self) -> TPM_HANDLE { TPM_HANDLE::default() } + + fn set_handle(&mut self, _handle: &TPM_HANDLE) { } +} + +/// This command is used to associate a policy with a PCR or group of PCR. The policy +/// determines the conditions under which a PCR may be extended or reset. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_PCR_SetAuthPolicy_REQUEST { + /// TPM_RH_PLATFORM+{PP} + /// Auth Index: 1 + /// Auth Role: USER + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub authHandle: TPM_HANDLE, + + /// The desired authPolicy + pub authPolicy: Vec, + + /// The hash algorithm of the policy + #[derivative(Default(value="TPM_ALG_ID::NULL"))] + pub hashAlg: TPM_ALG_ID, + + /// The PCR for which the policy is to be set + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub pcrNum: TPM_HANDLE, +} + +impl TPM2_PCR_SetAuthPolicy_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + authHandle: &TPM_HANDLE, + authPolicy: &Vec, + hashAlg: TPM_ALG_ID, + pcrNum: &TPM_HANDLE, + ) -> Self { + Self { + authHandle: authHandle.clone(), + authPolicy: authPolicy.clone(), + hashAlg: hashAlg.clone(), + pcrNum: pcrNum.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_PCR_SetAuthPolicy_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.authPolicy, 2); + buf.writeShort(self.hashAlg.into()); + self.pcrNum.toTpm(buf)?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.authPolicy = buf.readSizedByteBuf(2); + self.hashAlg = TPM_ALG_ID(buf.readShort() as u16); + self.pcrNum.initFromTpm(buf)?; + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_PCR_SetAuthPolicy_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_PCR_SetAuthPolicy_REQUEST { + fn num_handles(&self) -> u16 { 1 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 2, val_len: 1 } } +} + +impl ReqStructure for TPM2_PCR_SetAuthPolicy_REQUEST { + fn num_auth_handles(&self) -> u16 { 1 } + + fn get_handles(&self) -> Vec { vec![self.authHandle.clone()] } +} + +/// This command changes the authValue of a PCR or group of PCR. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_PCR_SetAuthValue_REQUEST { + /// Handle for a PCR that may have an authorization value set + /// Auth Index: 1 + /// Auth Role: USER + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub pcrHandle: TPM_HANDLE, + + /// The desired authorization value + pub auth: Vec, +} + +impl TPM2_PCR_SetAuthValue_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + pcrHandle: &TPM_HANDLE, + auth: &Vec, + ) -> Self { + Self { + pcrHandle: pcrHandle.clone(), + auth: auth.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_PCR_SetAuthValue_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.auth, 2); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.auth = buf.readSizedByteBuf(2); + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_PCR_SetAuthValue_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_PCR_SetAuthValue_REQUEST { + fn num_handles(&self) -> u16 { 1 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 2, val_len: 1 } } +} + +impl ReqStructure for TPM2_PCR_SetAuthValue_REQUEST { + fn num_auth_handles(&self) -> u16 { 1 } + + fn get_handles(&self) -> Vec { vec![self.pcrHandle.clone()] } +} + +/// If the attribute of a PCR allows the PCR to be reset and proper authorization is +/// provided, then this command may be used to set the PCR in all banks to zero. The +/// attributes of the PCR may restrict the locality that can perform the reset operation. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_PCR_Reset_REQUEST { + /// The PCR to reset + /// Auth Index: 1 + /// Auth Role: USER + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub pcrHandle: TPM_HANDLE, +} + +impl TPM2_PCR_Reset_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + pcrHandle: &TPM_HANDLE, + ) -> Self { + Self { + pcrHandle: pcrHandle.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_PCR_Reset_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_PCR_Reset_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_PCR_Reset_REQUEST { + fn num_handles(&self) -> u16 { 1 } + +} + +impl ReqStructure for TPM2_PCR_Reset_REQUEST { + fn num_auth_handles(&self) -> u16 { 1 } + + fn get_handles(&self) -> Vec { vec![self.pcrHandle.clone()] } +} + +/// This command includes a signed authorization in a policy. The command ties the policy +/// to a signing key by including the Name of the signing key in the policyDigest +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_PolicySigned_REQUEST { + /// Handle for a key that will validate the signature + /// Auth Index: None + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub authObject: TPM_HANDLE, + + /// Handle for the policy session being extended + /// Auth Index: None + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub policySession: TPM_HANDLE, + + /// The policy nonce for the session + /// This can be the Empty Buffer. + pub nonceTPM: Vec, + + /// Digest of the command parameters to which this authorization is limited + /// This is not the cpHash for this command but the cpHash for the command to which this + /// policy session will be applied. If it is not limited, the parameter will be the Empty Buffer. + pub cpHashA: Vec, + + /// A reference to a policy relating to the authorization may be the Empty Buffer + /// Size is limited to be no larger than the nonce size supported on the TPM. + pub policyRef: Vec, + + /// Time when authorization will expire, measured in seconds from the time that nonceTPM + /// was generated + /// If expiration is non-negative, a NULL Ticket is returned. See 23.2.5. + pub expiration: i32, + + /// Selector of the algorithm used to construct the signature + + /// Signed authorization (not optional) + /// One of: TPMS_SIGNATURE_RSASSA, TPMS_SIGNATURE_RSAPSS, TPMS_SIGNATURE_ECDSA, + /// TPMS_SIGNATURE_ECDAA, TPMS_SIGNATURE_SM2, TPMS_SIGNATURE_ECSCHNORR, TPMT_HA, + /// TPMS_SCHEME_HASH, TPMS_NULL_SIGNATURE. + pub auth: Option, +} + +impl TPM2_PolicySigned_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + authObject: &TPM_HANDLE, + policySession: &TPM_HANDLE, + nonceTPM: &Vec, + cpHashA: &Vec, + policyRef: &Vec, + expiration: i32, + auth: &Option, + ) -> Self { + Self { + authObject: authObject.clone(), + policySession: policySession.clone(), + nonceTPM: nonceTPM.clone(), + cpHashA: cpHashA.clone(), + policyRef: policyRef.clone(), + expiration: expiration.clone(), + auth: auth.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_PolicySigned_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.nonceTPM, 2); + buf.writeSizedByteBuf(&self.cpHashA, 2); + buf.writeSizedByteBuf(&self.policyRef, 2); + buf.writeInt(self.expiration as u32); + buf.writeShort(self.auth.as_ref().unwrap().GetUnionSelector().into()); + self.auth.as_ref().unwrap().toTpm(buf)?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.nonceTPM = buf.readSizedByteBuf(2); + self.cpHashA = buf.readSizedByteBuf(2); + self.policyRef = buf.readSizedByteBuf(2); + self.expiration = buf.readInt() as i32; + let r#authSigAlg: TPM_ALG_ID = TPM_ALG_ID(buf.readShort() as u16); + self.auth = TPMU_SIGNATURE::create(r#authSigAlg)?; + self.auth.as_mut().unwrap().initFromTpm(buf)?; + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_PolicySigned_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_PolicySigned_REQUEST { + fn num_handles(&self) -> u16 { 2 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 2, val_len: 1 } } +} + +impl ReqStructure for TPM2_PolicySigned_REQUEST { + fn num_auth_handles(&self) -> u16 { 0 } + + fn get_handles(&self) -> Vec { vec![self.authObject.clone(), self.policySession.clone()] } +} + +/// This command includes a signed authorization in a policy. The command ties the policy +/// to a signing key by including the Name of the signing key in the policyDigest +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct PolicySignedResponse { + /// Implementation-specific time value, used to indicate to the TPM when the ticket expires + /// NOTE If policyTicket is a NULL Ticket, then this shall be the Empty Buffer. + pub timeout: Vec, + + /// Produced if the command succeeds and expiration in the command was non-zero; this + /// ticket will use the TPMT_ST_AUTH_SIGNED structure tag. See 23.2.5 + pub policyTicket: TPMT_TK_AUTH, +} + +impl PolicySignedResponse { +} + +impl TpmStructure for PolicySignedResponse { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.timeout, 2); + self.policyTicket.toTpm(buf)?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.timeout = buf.readSizedByteBuf(2); + self.policyTicket.initFromTpm(buf)?; + Ok(()) + } + +} + +impl TpmMarshaller for PolicySignedResponse { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for PolicySignedResponse { + fn num_handles(&self) -> u16 { 0 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 2, val_len: 1 } } +} + +impl RespStructure for PolicySignedResponse { + fn get_handle(&self) -> TPM_HANDLE { TPM_HANDLE::default() } + + fn set_handle(&mut self, _handle: &TPM_HANDLE) { } +} + +/// This command includes a secret-based authorization to a policy. The caller proves +/// knowledge of the secret value using an authorization session using the authValue +/// associated with authHandle. A password session, an HMAC session, or a policy session +/// containing TPM2_PolicyAuthValue() or TPM2_PolicyPassword() will satisfy this requirement. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_PolicySecret_REQUEST { + /// Handle for an entity providing the authorization + /// Auth Index: 1 + /// Auth Role: USER + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub authHandle: TPM_HANDLE, + + /// Handle for the policy session being extended + /// Auth Index: None + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub policySession: TPM_HANDLE, + + /// The policy nonce for the session + /// This can be the Empty Buffer. + pub nonceTPM: Vec, + + /// Digest of the command parameters to which this authorization is limited + /// This not the cpHash for this command but the cpHash for the command to which this + /// policy session will be applied. If it is not limited, the parameter will be the Empty Buffer. + pub cpHashA: Vec, + + /// A reference to a policy relating to the authorization may be the Empty Buffer + /// Size is limited to be no larger than the nonce size supported on the TPM. + pub policyRef: Vec, + + /// Time when authorization will expire, measured in seconds from the time that nonceTPM + /// was generated + /// If expiration is non-negative, a NULL Ticket is returned. See 23.2.5. + pub expiration: i32, +} + +impl TPM2_PolicySecret_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + authHandle: &TPM_HANDLE, + policySession: &TPM_HANDLE, + nonceTPM: &Vec, + cpHashA: &Vec, + policyRef: &Vec, + expiration: i32, + ) -> Self { + Self { + authHandle: authHandle.clone(), + policySession: policySession.clone(), + nonceTPM: nonceTPM.clone(), + cpHashA: cpHashA.clone(), + policyRef: policyRef.clone(), + expiration: expiration.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_PolicySecret_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.nonceTPM, 2); + buf.writeSizedByteBuf(&self.cpHashA, 2); + buf.writeSizedByteBuf(&self.policyRef, 2); + buf.writeInt(self.expiration as u32); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.nonceTPM = buf.readSizedByteBuf(2); + self.cpHashA = buf.readSizedByteBuf(2); + self.policyRef = buf.readSizedByteBuf(2); + self.expiration = buf.readInt() as i32; + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_PolicySecret_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_PolicySecret_REQUEST { + fn num_handles(&self) -> u16 { 2 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 2, val_len: 1 } } +} + +impl ReqStructure for TPM2_PolicySecret_REQUEST { + fn num_auth_handles(&self) -> u16 { 1 } + + fn get_handles(&self) -> Vec { vec![self.authHandle.clone(), self.policySession.clone()] } +} + +/// This command includes a secret-based authorization to a policy. The caller proves +/// knowledge of the secret value using an authorization session using the authValue +/// associated with authHandle. A password session, an HMAC session, or a policy session +/// containing TPM2_PolicyAuthValue() or TPM2_PolicyPassword() will satisfy this requirement. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct PolicySecretResponse { + /// Implementation-specific time value used to indicate to the TPM when the ticket expires + pub timeout: Vec, + + /// Produced if the command succeeds and expiration in the command was non-zero ( See + /// 23.2.5). This ticket will use the TPMT_ST_AUTH_SECRET structure tag + pub policyTicket: TPMT_TK_AUTH, +} + +impl PolicySecretResponse { +} + +impl TpmStructure for PolicySecretResponse { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.timeout, 2); + self.policyTicket.toTpm(buf)?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.timeout = buf.readSizedByteBuf(2); + self.policyTicket.initFromTpm(buf)?; + Ok(()) + } + +} + +impl TpmMarshaller for PolicySecretResponse { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for PolicySecretResponse { + fn num_handles(&self) -> u16 { 0 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 2, val_len: 1 } } +} + +impl RespStructure for PolicySecretResponse { + fn get_handle(&self) -> TPM_HANDLE { TPM_HANDLE::default() } + + fn set_handle(&mut self, _handle: &TPM_HANDLE) { } +} + +/// This command is similar to TPM2_PolicySigned() except that it takes a ticket instead +/// of a signed authorization. The ticket represents a validated authorization that had an +/// expiration time associated with it. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_PolicyTicket_REQUEST { + /// Handle for the policy session being extended + /// Auth Index: None + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub policySession: TPM_HANDLE, + + /// Time when authorization will expire + /// The contents are TPM specific. This shall be the value returned when ticket was produced. + pub timeout: Vec, + + /// Digest of the command parameters to which this authorization is limited + /// If it is not limited, the parameter will be the Empty Buffer. + pub cpHashA: Vec, + + /// Reference to a qualifier for the policy may be the Empty Buffer + pub policyRef: Vec, + + /// Name of the object that provided the authorization + pub authName: Vec, + + /// An authorization ticket returned by the TPM in response to a TPM2_PolicySigned() or + /// TPM2_PolicySecret() + pub ticket: TPMT_TK_AUTH, +} + +impl TPM2_PolicyTicket_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + policySession: &TPM_HANDLE, + timeout: &Vec, + cpHashA: &Vec, + policyRef: &Vec, + authName: &Vec, + ticket: &TPMT_TK_AUTH, + ) -> Self { + Self { + policySession: policySession.clone(), + timeout: timeout.clone(), + cpHashA: cpHashA.clone(), + policyRef: policyRef.clone(), + authName: authName.clone(), + ticket: ticket.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_PolicyTicket_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.timeout, 2); + buf.writeSizedByteBuf(&self.cpHashA, 2); + buf.writeSizedByteBuf(&self.policyRef, 2); + buf.writeSizedByteBuf(&self.authName, 2); + self.ticket.toTpm(buf)?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.timeout = buf.readSizedByteBuf(2); + self.cpHashA = buf.readSizedByteBuf(2); + self.policyRef = buf.readSizedByteBuf(2); + self.authName = buf.readSizedByteBuf(2); + self.ticket.initFromTpm(buf)?; + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_PolicyTicket_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_PolicyTicket_REQUEST { + fn num_handles(&self) -> u16 { 1 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 2, val_len: 1 } } +} + +impl ReqStructure for TPM2_PolicyTicket_REQUEST { + fn num_auth_handles(&self) -> u16 { 0 } + + fn get_handles(&self) -> Vec { vec![self.policySession.clone()] } +} + +/// This command allows options in authorizations without requiring that the TPM evaluate +/// all of the options. If a policy may be satisfied by different sets of conditions, the +/// TPM need only evaluate one set that satisfies the policy. This command will indicate +/// that one of the required sets of conditions has been satisfied. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_PolicyOR_REQUEST { + /// Handle for the policy session being extended + /// Auth Index: None + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub policySession: TPM_HANDLE, + + /// The list of hashes to check for a match + pub pHashList: Vec, +} + +impl TPM2_PolicyOR_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + policySession: &TPM_HANDLE, + pHashList: &Vec, + ) -> Self { + Self { + policySession: policySession.clone(), + pHashList: pHashList.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_PolicyOR_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeObjArr(self.pHashList.as_ref())?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + buf.readObjArr(self.pHashList.as_mut())?; + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_PolicyOR_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_PolicyOR_REQUEST { + fn num_handles(&self) -> u16 { 1 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 4, val_len: 2 } } +} + +impl ReqStructure for TPM2_PolicyOR_REQUEST { + fn num_auth_handles(&self) -> u16 { 0 } + + fn get_handles(&self) -> Vec { vec![self.policySession.clone()] } +} + +/// This command is used to cause conditional gating of a policy based on PCR. This +/// command together with TPM2_PolicyOR() allows one group of authorizations to occur when +/// PCR are in one state and a different set of authorizations when the PCR are in a +/// different state. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_PolicyPCR_REQUEST { + /// Handle for the policy session being extended + /// Auth Index: None + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub policySession: TPM_HANDLE, + + /// Expected digest value of the selected PCR using the hash algorithm of the session; may + /// be zero length + pub pcrDigest: Vec, + + /// The PCR to include in the check digest + pub pcrs: Vec, +} + +impl TPM2_PolicyPCR_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + policySession: &TPM_HANDLE, + pcrDigest: &Vec, + pcrs: &Vec, + ) -> Self { + Self { + policySession: policySession.clone(), + pcrDigest: pcrDigest.clone(), + pcrs: pcrs.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_PolicyPCR_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.pcrDigest, 2); + buf.writeObjArr(self.pcrs.as_ref())?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.pcrDigest = buf.readSizedByteBuf(2); + buf.readObjArr(self.pcrs.as_mut())?; + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_PolicyPCR_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_PolicyPCR_REQUEST { + fn num_handles(&self) -> u16 { 1 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 2, val_len: 1 } } +} + +impl ReqStructure for TPM2_PolicyPCR_REQUEST { + fn num_auth_handles(&self) -> u16 { 0 } + + fn get_handles(&self) -> Vec { vec![self.policySession.clone()] } +} + +/// This command indicates that the authorization will be limited to a specific locality. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_PolicyLocality_REQUEST { + /// Handle for the policy session being extended + /// Auth Index: None + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub policySession: TPM_HANDLE, + + /// The allowed localities for the policy + pub locality: TPMA_LOCALITY, +} + +impl TPM2_PolicyLocality_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + policySession: &TPM_HANDLE, + locality: TPMA_LOCALITY, + ) -> Self { + Self { + policySession: policySession.clone(), + locality: locality.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_PolicyLocality_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeByte(self.locality.into()); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.locality = TPMA_LOCALITY(buf.readByte() as u8); + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_PolicyLocality_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_PolicyLocality_REQUEST { + fn num_handles(&self) -> u16 { 1 } + +} + +impl ReqStructure for TPM2_PolicyLocality_REQUEST { + fn num_auth_handles(&self) -> u16 { 0 } + + fn get_handles(&self) -> Vec { vec![self.policySession.clone()] } +} + +/// This command is used to cause conditional gating of a policy based on the contents of +/// an NV Index. It is an immediate assertion. The NV index is validated during the +/// TPM2_PolicyNV() command, not when the session is used for authorization. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_PolicyNV_REQUEST { + /// Handle indicating the source of the authorization value + /// Auth Index: 1 + /// Auth Role: USER + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub authHandle: TPM_HANDLE, + + /// The NV Index of the area to read + /// Auth Index: None + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub nvIndex: TPM_HANDLE, + + /// Handle for the policy session being extended + /// Auth Index: None + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub policySession: TPM_HANDLE, + + /// The second operand + pub operandB: Vec, + + /// The octet offset in the NV Index for the start of operand A + pub offset: u16, + + /// The comparison to make + pub operation: TPM_EO, +} + +impl TPM2_PolicyNV_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + authHandle: &TPM_HANDLE, + nvIndex: &TPM_HANDLE, + policySession: &TPM_HANDLE, + operandB: &Vec, + offset: u16, + operation: TPM_EO, + ) -> Self { + Self { + authHandle: authHandle.clone(), + nvIndex: nvIndex.clone(), + policySession: policySession.clone(), + operandB: operandB.clone(), + offset: offset.clone(), + operation: operation.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_PolicyNV_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.operandB, 2); + buf.writeShort(self.offset as u16); + buf.writeShort(self.operation.into()); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.operandB = buf.readSizedByteBuf(2); + self.offset = buf.readShort() as u16; + self.operation = TPM_EO(buf.readShort() as u16); + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_PolicyNV_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_PolicyNV_REQUEST { + fn num_handles(&self) -> u16 { 3 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 2, val_len: 1 } } +} + +impl ReqStructure for TPM2_PolicyNV_REQUEST { + fn num_auth_handles(&self) -> u16 { 1 } + + fn get_handles(&self) -> Vec { vec![self.authHandle.clone(), self.nvIndex.clone(), self.policySession.clone()] } +} + +/// This command is used to cause conditional gating of a policy based on the contents of +/// the TPMS_TIME_INFO structure. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_PolicyCounterTimer_REQUEST { + /// Handle for the policy session being extended + /// Auth Index: None + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub policySession: TPM_HANDLE, + + /// The second operand + pub operandB: Vec, + + /// The octet offset in the TPMS_TIME_INFO structure for the start of operand A + pub offset: u16, + + /// The comparison to make + pub operation: TPM_EO, +} + +impl TPM2_PolicyCounterTimer_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + policySession: &TPM_HANDLE, + operandB: &Vec, + offset: u16, + operation: TPM_EO, + ) -> Self { + Self { + policySession: policySession.clone(), + operandB: operandB.clone(), + offset: offset.clone(), + operation: operation.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_PolicyCounterTimer_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.operandB, 2); + buf.writeShort(self.offset as u16); + buf.writeShort(self.operation.into()); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.operandB = buf.readSizedByteBuf(2); + self.offset = buf.readShort() as u16; + self.operation = TPM_EO(buf.readShort() as u16); + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_PolicyCounterTimer_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_PolicyCounterTimer_REQUEST { + fn num_handles(&self) -> u16 { 1 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 2, val_len: 1 } } +} + +impl ReqStructure for TPM2_PolicyCounterTimer_REQUEST { + fn num_auth_handles(&self) -> u16 { 0 } + + fn get_handles(&self) -> Vec { vec![self.policySession.clone()] } +} + +/// This command indicates that the authorization will be limited to a specific command code. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_PolicyCommandCode_REQUEST { + /// Handle for the policy session being extended + /// Auth Index: None + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub policySession: TPM_HANDLE, + + /// The allowed commandCode + pub code: TPM_CC, +} + +impl TPM2_PolicyCommandCode_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + policySession: &TPM_HANDLE, + code: TPM_CC, + ) -> Self { + Self { + policySession: policySession.clone(), + code: code.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_PolicyCommandCode_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeInt(self.code.into()); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.code = TPM_CC(buf.readInt() as u32); + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_PolicyCommandCode_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_PolicyCommandCode_REQUEST { + fn num_handles(&self) -> u16 { 1 } + +} + +impl ReqStructure for TPM2_PolicyCommandCode_REQUEST { + fn num_auth_handles(&self) -> u16 { 0 } + + fn get_handles(&self) -> Vec { vec![self.policySession.clone()] } +} + +/// This command indicates that physical presence will need to be asserted at the time the +/// authorization is performed. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_PolicyPhysicalPresence_REQUEST { + /// Handle for the policy session being extended + /// Auth Index: None + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub policySession: TPM_HANDLE, +} + +impl TPM2_PolicyPhysicalPresence_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + policySession: &TPM_HANDLE, + ) -> Self { + Self { + policySession: policySession.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_PolicyPhysicalPresence_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_PolicyPhysicalPresence_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_PolicyPhysicalPresence_REQUEST { + fn num_handles(&self) -> u16 { 1 } + +} + +impl ReqStructure for TPM2_PolicyPhysicalPresence_REQUEST { + fn num_auth_handles(&self) -> u16 { 0 } + + fn get_handles(&self) -> Vec { vec![self.policySession.clone()] } +} + +/// This command is used to allow a policy to be bound to a specific command and command parameters. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_PolicyCpHash_REQUEST { + /// Handle for the policy session being extended + /// Auth Index: None + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub policySession: TPM_HANDLE, + + /// The cpHash added to the policy + pub cpHashA: Vec, +} + +impl TPM2_PolicyCpHash_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + policySession: &TPM_HANDLE, + cpHashA: &Vec, + ) -> Self { + Self { + policySession: policySession.clone(), + cpHashA: cpHashA.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_PolicyCpHash_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.cpHashA, 2); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.cpHashA = buf.readSizedByteBuf(2); + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_PolicyCpHash_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_PolicyCpHash_REQUEST { + fn num_handles(&self) -> u16 { 1 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 2, val_len: 1 } } +} + +impl ReqStructure for TPM2_PolicyCpHash_REQUEST { + fn num_auth_handles(&self) -> u16 { 0 } + + fn get_handles(&self) -> Vec { vec![self.policySession.clone()] } +} + +/// This command allows a policy to be bound to a specific set of TPM entities without +/// being bound to the parameters of the command. This is most useful for commands such as +/// TPM2_Duplicate() and for TPM2_PCR_Event() when the referenced PCR requires a policy. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_PolicyNameHash_REQUEST { + /// Handle for the policy session being extended + /// Auth Index: None + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub policySession: TPM_HANDLE, + + /// The digest to be added to the policy + pub nameHash: Vec, +} + +impl TPM2_PolicyNameHash_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + policySession: &TPM_HANDLE, + nameHash: &Vec, + ) -> Self { + Self { + policySession: policySession.clone(), + nameHash: nameHash.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_PolicyNameHash_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.nameHash, 2); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.nameHash = buf.readSizedByteBuf(2); + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_PolicyNameHash_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_PolicyNameHash_REQUEST { + fn num_handles(&self) -> u16 { 1 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 2, val_len: 1 } } +} + +impl ReqStructure for TPM2_PolicyNameHash_REQUEST { + fn num_auth_handles(&self) -> u16 { 0 } + + fn get_handles(&self) -> Vec { vec![self.policySession.clone()] } +} + +/// This command allows qualification of duplication to allow duplication to a selected +/// new parent. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_PolicyDuplicationSelect_REQUEST { + /// Handle for the policy session being extended + /// Auth Index: None + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub policySession: TPM_HANDLE, + + /// The Name of the object to be duplicated + pub objectName: Vec, + + /// The Name of the new parent + pub newParentName: Vec, + + /// If YES, the objectName will be included in the value in policySessionpolicyDigest + pub includeObject: u8, +} + +impl TPM2_PolicyDuplicationSelect_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + policySession: &TPM_HANDLE, + objectName: &Vec, + newParentName: &Vec, + includeObject: u8, + ) -> Self { + Self { + policySession: policySession.clone(), + objectName: objectName.clone(), + newParentName: newParentName.clone(), + includeObject: includeObject.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_PolicyDuplicationSelect_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.objectName, 2); + buf.writeSizedByteBuf(&self.newParentName, 2); + buf.writeByte(self.includeObject as u8); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.objectName = buf.readSizedByteBuf(2); + self.newParentName = buf.readSizedByteBuf(2); + self.includeObject = buf.readByte() as u8; + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_PolicyDuplicationSelect_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_PolicyDuplicationSelect_REQUEST { + fn num_handles(&self) -> u16 { 1 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 2, val_len: 1 } } +} + +impl ReqStructure for TPM2_PolicyDuplicationSelect_REQUEST { + fn num_auth_handles(&self) -> u16 { 0 } + + fn get_handles(&self) -> Vec { vec![self.policySession.clone()] } +} + +/// This command allows policies to change. If a policy were static, then it would be +/// difficult to add users to a policy. This command lets a policy authority sign a new +/// policy so that it may be used in an existing policy. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_PolicyAuthorize_REQUEST { + /// Handle for the policy session being extended + /// Auth Index: None + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub policySession: TPM_HANDLE, + + /// Digest of the policy being approved + pub approvedPolicy: Vec, + + /// A policy qualifier + pub policyRef: Vec, + + /// Name of a key that can sign a policy addition + pub keySign: Vec, + + /// Ticket validating that approvedPolicy and policyRef were signed by keySign + pub checkTicket: TPMT_TK_VERIFIED, +} + +impl TPM2_PolicyAuthorize_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + policySession: &TPM_HANDLE, + approvedPolicy: &Vec, + policyRef: &Vec, + keySign: &Vec, + checkTicket: &TPMT_TK_VERIFIED, + ) -> Self { + Self { + policySession: policySession.clone(), + approvedPolicy: approvedPolicy.clone(), + policyRef: policyRef.clone(), + keySign: keySign.clone(), + checkTicket: checkTicket.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_PolicyAuthorize_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.approvedPolicy, 2); + buf.writeSizedByteBuf(&self.policyRef, 2); + buf.writeSizedByteBuf(&self.keySign, 2); + self.checkTicket.toTpm(buf)?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.approvedPolicy = buf.readSizedByteBuf(2); + self.policyRef = buf.readSizedByteBuf(2); + self.keySign = buf.readSizedByteBuf(2); + self.checkTicket.initFromTpm(buf)?; + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_PolicyAuthorize_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_PolicyAuthorize_REQUEST { + fn num_handles(&self) -> u16 { 1 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 2, val_len: 1 } } +} + +impl ReqStructure for TPM2_PolicyAuthorize_REQUEST { + fn num_auth_handles(&self) -> u16 { 0 } + + fn get_handles(&self) -> Vec { vec![self.policySession.clone()] } +} + +/// This command allows a policy to be bound to the authorization value of the authorized entity. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_PolicyAuthValue_REQUEST { + /// Handle for the policy session being extended + /// Auth Index: None + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub policySession: TPM_HANDLE, +} + +impl TPM2_PolicyAuthValue_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + policySession: &TPM_HANDLE, + ) -> Self { + Self { + policySession: policySession.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_PolicyAuthValue_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_PolicyAuthValue_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_PolicyAuthValue_REQUEST { + fn num_handles(&self) -> u16 { 1 } + +} + +impl ReqStructure for TPM2_PolicyAuthValue_REQUEST { + fn num_auth_handles(&self) -> u16 { 0 } + + fn get_handles(&self) -> Vec { vec![self.policySession.clone()] } +} + +/// This command allows a policy to be bound to the authorization value of the authorized object. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_PolicyPassword_REQUEST { + /// Handle for the policy session being extended + /// Auth Index: None + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub policySession: TPM_HANDLE, +} + +impl TPM2_PolicyPassword_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + policySession: &TPM_HANDLE, + ) -> Self { + Self { + policySession: policySession.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_PolicyPassword_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_PolicyPassword_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_PolicyPassword_REQUEST { + fn num_handles(&self) -> u16 { 1 } + +} + +impl ReqStructure for TPM2_PolicyPassword_REQUEST { + fn num_auth_handles(&self) -> u16 { 0 } + + fn get_handles(&self) -> Vec { vec![self.policySession.clone()] } +} + +/// This command returns the current policyDigest of the session. This command allows the +/// TPM to be used to perform the actions required to pre-compute the authPolicy for an object. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_PolicyGetDigest_REQUEST { + /// Handle for the policy session + /// Auth Index: None + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub policySession: TPM_HANDLE, +} + +impl TPM2_PolicyGetDigest_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + policySession: &TPM_HANDLE, + ) -> Self { + Self { + policySession: policySession.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_PolicyGetDigest_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_PolicyGetDigest_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_PolicyGetDigest_REQUEST { + fn num_handles(&self) -> u16 { 1 } + +} + +impl ReqStructure for TPM2_PolicyGetDigest_REQUEST { + fn num_auth_handles(&self) -> u16 { 0 } + + fn get_handles(&self) -> Vec { vec![self.policySession.clone()] } +} + +/// This command returns the current policyDigest of the session. This command allows the +/// TPM to be used to perform the actions required to pre-compute the authPolicy for an object. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct PolicyGetDigestResponse { + /// The current value of the policySessionpolicyDigest + pub policyDigest: Vec, +} + +impl PolicyGetDigestResponse { +} + +impl TpmStructure for PolicyGetDigestResponse { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.policyDigest, 2); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.policyDigest = buf.readSizedByteBuf(2); + Ok(()) + } + +} + +impl TpmMarshaller for PolicyGetDigestResponse { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for PolicyGetDigestResponse { + fn num_handles(&self) -> u16 { 0 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 2, val_len: 1 } } +} + +impl RespStructure for PolicyGetDigestResponse { + fn get_handle(&self) -> TPM_HANDLE { TPM_HANDLE::default() } + + fn set_handle(&mut self, _handle: &TPM_HANDLE) { } +} + +/// This command allows a policy to be bound to the TPMA_NV_WRITTEN attributes. This is a +/// deferred assertion. Values are stored in the policy session context and checked when +/// the policy is used for authorization. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_PolicyNvWritten_REQUEST { + /// Handle for the policy session being extended + /// Auth Index: None + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub policySession: TPM_HANDLE, + + /// YES if NV Index is required to have been written + /// NO if NV Index is required not to have been written + pub writtenSet: u8, +} + +impl TPM2_PolicyNvWritten_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + policySession: &TPM_HANDLE, + writtenSet: u8, + ) -> Self { + Self { + policySession: policySession.clone(), + writtenSet: writtenSet.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_PolicyNvWritten_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeByte(self.writtenSet as u8); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.writtenSet = buf.readByte() as u8; + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_PolicyNvWritten_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_PolicyNvWritten_REQUEST { + fn num_handles(&self) -> u16 { 1 } + +} + +impl ReqStructure for TPM2_PolicyNvWritten_REQUEST { + fn num_auth_handles(&self) -> u16 { 0 } + + fn get_handles(&self) -> Vec { vec![self.policySession.clone()] } +} + +/// This command allows a policy to be bound to a specific creation template. This is most +/// useful for an object creation command such as TPM2_Create(), TPM2_CreatePrimary(), or +/// TPM2_CreateLoaded(). +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_PolicyTemplate_REQUEST { + /// Handle for the policy session being extended + /// Auth Index: None + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub policySession: TPM_HANDLE, + + /// The digest to be added to the policy + pub templateHash: Vec, +} + +impl TPM2_PolicyTemplate_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + policySession: &TPM_HANDLE, + templateHash: &Vec, + ) -> Self { + Self { + policySession: policySession.clone(), + templateHash: templateHash.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_PolicyTemplate_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.templateHash, 2); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.templateHash = buf.readSizedByteBuf(2); + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_PolicyTemplate_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_PolicyTemplate_REQUEST { + fn num_handles(&self) -> u16 { 1 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 2, val_len: 1 } } +} + +impl ReqStructure for TPM2_PolicyTemplate_REQUEST { + fn num_auth_handles(&self) -> u16 { 0 } + + fn get_handles(&self) -> Vec { vec![self.policySession.clone()] } +} + +/// This command provides a capability that is the equivalent of a revocable policy. With +/// TPM2_PolicyAuthorize(), the authorization ticket never expires, so the authorization +/// may not be withdrawn. With this command, the approved policy is kept in an NV Index +/// location so that the policy may be changed as needed to render the old policy unusable. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_PolicyAuthorizeNV_REQUEST { + /// Handle indicating the source of the authorization value + /// Auth Index: 1 + /// Auth Role: USER + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub authHandle: TPM_HANDLE, + + /// The NV Index of the area to read + /// Auth Index: None + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub nvIndex: TPM_HANDLE, + + /// Handle for the policy session being extended + /// Auth Index: None + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub policySession: TPM_HANDLE, +} + +impl TPM2_PolicyAuthorizeNV_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + authHandle: &TPM_HANDLE, + nvIndex: &TPM_HANDLE, + policySession: &TPM_HANDLE, + ) -> Self { + Self { + authHandle: authHandle.clone(), + nvIndex: nvIndex.clone(), + policySession: policySession.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_PolicyAuthorizeNV_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_PolicyAuthorizeNV_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_PolicyAuthorizeNV_REQUEST { + fn num_handles(&self) -> u16 { 3 } + +} + +impl ReqStructure for TPM2_PolicyAuthorizeNV_REQUEST { + fn num_auth_handles(&self) -> u16 { 1 } + + fn get_handles(&self) -> Vec { vec![self.authHandle.clone(), self.nvIndex.clone(), self.policySession.clone()] } +} + +/// This command is used to create a Primary Object under one of the Primary Seeds or a +/// Temporary Object under TPM_RH_NULL. The command uses a TPM2B_PUBLIC as a template for +/// the object to be created. The size of the unique field shall not be checked for +/// consistency with the other object parameters. The command will create and load a +/// Primary Object. The sensitive area is not returned. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_CreatePrimary_REQUEST { + /// TPM_RH_ENDORSEMENT, TPM_RH_OWNER, TPM_RH_PLATFORM+{PP}, or TPM_RH_NULL + /// Auth Index: 1 + /// Auth Role: USER + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub primaryHandle: TPM_HANDLE, + + /// The sensitive data, see TPM 2.0 Part 1 Sensitive Values + pub inSensitive: TPMS_SENSITIVE_CREATE, + + /// The public template + pub inPublic: TPMT_PUBLIC, + + /// Data that will be included in the creation data for this object to provide permanent, + /// verifiable linkage between this object and some object owner data + pub outsideInfo: Vec, + + /// PCR that will be used in creation data + pub creationPCR: Vec, +} + +impl TPM2_CreatePrimary_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + primaryHandle: &TPM_HANDLE, + inSensitive: &TPMS_SENSITIVE_CREATE, + inPublic: &TPMT_PUBLIC, + outsideInfo: &Vec, + creationPCR: &Vec, + ) -> Self { + Self { + primaryHandle: primaryHandle.clone(), + inSensitive: inSensitive.clone(), + inPublic: inPublic.clone(), + outsideInfo: outsideInfo.clone(), + creationPCR: creationPCR.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_CreatePrimary_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedObj(&self.inSensitive)?; + buf.writeSizedObj(&self.inPublic)?; + buf.writeSizedByteBuf(&self.outsideInfo, 2); + buf.writeObjArr(self.creationPCR.as_ref())?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + buf.readSizedObj(&mut self.inSensitive)?; + buf.readSizedObj(&mut self.inPublic)?; + self.outsideInfo = buf.readSizedByteBuf(2); + buf.readObjArr(self.creationPCR.as_mut())?; + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_CreatePrimary_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_CreatePrimary_REQUEST { + fn num_handles(&self) -> u16 { 1 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 2, val_len: 1 } } +} + +impl ReqStructure for TPM2_CreatePrimary_REQUEST { + fn num_auth_handles(&self) -> u16 { 1 } + + fn get_handles(&self) -> Vec { vec![self.primaryHandle.clone()] } +} + +/// This command is used to create a Primary Object under one of the Primary Seeds or a +/// Temporary Object under TPM_RH_NULL. The command uses a TPM2B_PUBLIC as a template for +/// the object to be created. The size of the unique field shall not be checked for +/// consistency with the other object parameters. The command will create and load a +/// Primary Object. The sensitive area is not returned. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct CreatePrimaryResponse { + /// Handle of type TPM_HT_TRANSIENT for created Primary Object + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub handle: TPM_HANDLE, + + /// The public portion of the created object + pub outPublic: TPMT_PUBLIC, + + /// Contains a TPMT_CREATION_DATA + pub creationData: TPMS_CREATION_DATA, + + /// Digest of creationData using nameAlg of outPublic + pub creationHash: Vec, + + /// Ticket used by TPM2_CertifyCreation() to validate that the creation data was produced + /// by the TPM + pub creationTicket: TPMT_TK_CREATION, + + /// The name of the created object + pub name: Vec, +} + +impl CreatePrimaryResponse { +} + +impl TpmStructure for CreatePrimaryResponse { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedObj(&self.outPublic)?; + buf.writeSizedObj(&self.creationData)?; + buf.writeSizedByteBuf(&self.creationHash, 2); + self.creationTicket.toTpm(buf)?; + buf.writeSizedByteBuf(&self.name, 2); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + buf.readSizedObj(&mut self.outPublic)?; + buf.readSizedObj(&mut self.creationData)?; + self.creationHash = buf.readSizedByteBuf(2); + self.creationTicket.initFromTpm(buf)?; + self.name = buf.readSizedByteBuf(2); + Ok(()) + } + +} + +impl TpmMarshaller for CreatePrimaryResponse { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for CreatePrimaryResponse { + fn num_handles(&self) -> u16 { 1 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 2, val_len: 1 } } +} + +impl RespStructure for CreatePrimaryResponse { + fn get_handle(&self) -> TPM_HANDLE { self.handle.clone() } + + fn set_handle(&mut self, handle: &TPM_HANDLE) { self.handle = handle.clone(); } + + fn get_resp_name(&self) -> Vec { self.name.clone() } +} + +/// This command enables and disables use of a hierarchy and its associated NV storage. +/// The command allows phEnable, phEnableNV, shEnable, and ehEnable to be changed when the +/// proper authorization is provided. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_HierarchyControl_REQUEST { + /// TPM_RH_ENDORSEMENT, TPM_RH_OWNER or TPM_RH_PLATFORM+{PP} + /// Auth Index: 1 + /// Auth Role: USER + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub authHandle: TPM_HANDLE, + + /// The enable being modified + /// TPM_RH_ENDORSEMENT, TPM_RH_OWNER, TPM_RH_PLATFORM, or TPM_RH_PLATFORM_NV + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub enable: TPM_HANDLE, + + /// YES if the enable should be SET, NO if the enable should be CLEAR + pub state: u8, +} + +impl TPM2_HierarchyControl_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + authHandle: &TPM_HANDLE, + enable: &TPM_HANDLE, + state: u8, + ) -> Self { + Self { + authHandle: authHandle.clone(), + enable: enable.clone(), + state: state.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_HierarchyControl_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + self.enable.toTpm(buf)?; + buf.writeByte(self.state as u8); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.enable.initFromTpm(buf)?; + self.state = buf.readByte() as u8; + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_HierarchyControl_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_HierarchyControl_REQUEST { + fn num_handles(&self) -> u16 { 1 } + +} + +impl ReqStructure for TPM2_HierarchyControl_REQUEST { + fn num_auth_handles(&self) -> u16 { 1 } + + fn get_handles(&self) -> Vec { vec![self.authHandle.clone()] } +} + +/// This command allows setting of the authorization policy for the lockout +/// (lockoutPolicy), the platform hierarchy (platformPolicy), the storage hierarchy +/// (ownerPolicy), and the endorsement hierarchy (endorsementPolicy). On TPMs implementing +/// Authenticated Countdown Timers (ACT), this command may also be used to set the +/// authorization policy for an ACT. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_SetPrimaryPolicy_REQUEST { + /// TPM_RH_LOCKOUT, TPM_RH_ENDORSEMENT, TPM_RH_OWNER, TPMI_RH_ACT or TPM_RH_PLATFORM+{PP} + /// Auth Index: 1 + /// Auth Role: USER + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub authHandle: TPM_HANDLE, + + /// An authorization policy digest; may be the Empty Buffer + /// If hashAlg is TPM_ALG_NULL, then this shall be an Empty Buffer. + pub authPolicy: Vec, + + /// The hash algorithm to use for the policy + /// If the authPolicy is an Empty Buffer, then this field shall be TPM_ALG_NULL. + #[derivative(Default(value="TPM_ALG_ID::NULL"))] + pub hashAlg: TPM_ALG_ID, +} + +impl TPM2_SetPrimaryPolicy_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + authHandle: &TPM_HANDLE, + authPolicy: &Vec, + hashAlg: TPM_ALG_ID, + ) -> Self { + Self { + authHandle: authHandle.clone(), + authPolicy: authPolicy.clone(), + hashAlg: hashAlg.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_SetPrimaryPolicy_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.authPolicy, 2); + buf.writeShort(self.hashAlg.into()); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.authPolicy = buf.readSizedByteBuf(2); + self.hashAlg = TPM_ALG_ID(buf.readShort() as u16); + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_SetPrimaryPolicy_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_SetPrimaryPolicy_REQUEST { + fn num_handles(&self) -> u16 { 1 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 2, val_len: 1 } } +} + +impl ReqStructure for TPM2_SetPrimaryPolicy_REQUEST { + fn num_auth_handles(&self) -> u16 { 1 } + + fn get_handles(&self) -> Vec { vec![self.authHandle.clone()] } +} + +/// This replaces the current platform primary seed (PPS) with a value from the RNG and +/// sets platformPolicy to the default initialization value (the Empty Buffer). +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_ChangePPS_REQUEST { + /// TPM_RH_PLATFORM+{PP} + /// Auth Index: 1 + /// Auth Role: USER + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub authHandle: TPM_HANDLE, +} + +impl TPM2_ChangePPS_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + authHandle: &TPM_HANDLE, + ) -> Self { + Self { + authHandle: authHandle.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_ChangePPS_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_ChangePPS_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_ChangePPS_REQUEST { + fn num_handles(&self) -> u16 { 1 } + +} + +impl ReqStructure for TPM2_ChangePPS_REQUEST { + fn num_auth_handles(&self) -> u16 { 1 } + + fn get_handles(&self) -> Vec { vec![self.authHandle.clone()] } +} + +/// This replaces the current endorsement primary seed (EPS) with a value from the RNG and +/// sets the Endorsement hierarchy controls to their default initialization values: +/// ehEnable is SET, endorsementAuth and endorsementPolicy are both set to the Empty +/// Buffer. It will flush any resident objects (transient or persistent) in the +/// Endorsement hierarchy and not allow objects in the hierarchy associated with the +/// previous EPS to be loaded. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_ChangeEPS_REQUEST { + /// TPM_RH_PLATFORM+{PP} + /// Auth Handle: 1 + /// Auth Role: USER + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub authHandle: TPM_HANDLE, +} + +impl TPM2_ChangeEPS_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + authHandle: &TPM_HANDLE, + ) -> Self { + Self { + authHandle: authHandle.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_ChangeEPS_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_ChangeEPS_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_ChangeEPS_REQUEST { + fn num_handles(&self) -> u16 { 1 } + +} + +impl ReqStructure for TPM2_ChangeEPS_REQUEST { + fn num_auth_handles(&self) -> u16 { 1 } + + fn get_handles(&self) -> Vec { vec![self.authHandle.clone()] } +} + +/// This command removes all TPM context associated with a specific Owner. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_Clear_REQUEST { + /// TPM_RH_LOCKOUT or TPM_RH_PLATFORM+{PP} + /// Auth Handle: 1 + /// Auth Role: USER + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub authHandle: TPM_HANDLE, +} + +impl TPM2_Clear_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + authHandle: &TPM_HANDLE, + ) -> Self { + Self { + authHandle: authHandle.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_Clear_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_Clear_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_Clear_REQUEST { + fn num_handles(&self) -> u16 { 1 } + +} + +impl ReqStructure for TPM2_Clear_REQUEST { + fn num_auth_handles(&self) -> u16 { 1 } + + fn get_handles(&self) -> Vec { vec![self.authHandle.clone()] } +} + +/// TPM2_ClearControl() disables and enables the execution of TPM2_Clear(). +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_ClearControl_REQUEST { + /// TPM_RH_LOCKOUT or TPM_RH_PLATFORM+{PP} + /// Auth Handle: 1 + /// Auth Role: USER + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub auth: TPM_HANDLE, + + /// YES if the disableOwnerClear flag is to be SET, NO if the flag is to be CLEAR. + pub disable: u8, +} + +impl TPM2_ClearControl_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + auth: &TPM_HANDLE, + disable: u8, + ) -> Self { + Self { + auth: auth.clone(), + disable: disable.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_ClearControl_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeByte(self.disable as u8); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.disable = buf.readByte() as u8; + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_ClearControl_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_ClearControl_REQUEST { + fn num_handles(&self) -> u16 { 1 } + +} + +impl ReqStructure for TPM2_ClearControl_REQUEST { + fn num_auth_handles(&self) -> u16 { 1 } + + fn get_handles(&self) -> Vec { vec![self.auth.clone()] } +} + +/// This command allows the authorization secret for a hierarchy or lockout to be changed +/// using the current authorization value as the command authorization. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_HierarchyChangeAuth_REQUEST { + /// TPM_RH_LOCKOUT, TPM_RH_ENDORSEMENT, TPM_RH_OWNER or TPM_RH_PLATFORM+{PP} + /// Auth Index: 1 + /// Auth Role: USER + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub authHandle: TPM_HANDLE, + + /// New authorization value + pub newAuth: Vec, +} + +impl TPM2_HierarchyChangeAuth_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + authHandle: &TPM_HANDLE, + newAuth: &Vec, + ) -> Self { + Self { + authHandle: authHandle.clone(), + newAuth: newAuth.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_HierarchyChangeAuth_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.newAuth, 2); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.newAuth = buf.readSizedByteBuf(2); + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_HierarchyChangeAuth_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_HierarchyChangeAuth_REQUEST { + fn num_handles(&self) -> u16 { 1 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 2, val_len: 1 } } +} + +impl ReqStructure for TPM2_HierarchyChangeAuth_REQUEST { + fn num_auth_handles(&self) -> u16 { 1 } + + fn get_handles(&self) -> Vec { vec![self.authHandle.clone()] } +} + +/// This command cancels the effect of a TPM lockout due to a number of successive +/// authorization failures. If this command is properly authorized, the lockout counter is +/// set to zero. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_DictionaryAttackLockReset_REQUEST { + /// TPM_RH_LOCKOUT + /// Auth Index: 1 + /// Auth Role: USER + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub lockHandle: TPM_HANDLE, +} + +impl TPM2_DictionaryAttackLockReset_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + lockHandle: &TPM_HANDLE, + ) -> Self { + Self { + lockHandle: lockHandle.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_DictionaryAttackLockReset_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_DictionaryAttackLockReset_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_DictionaryAttackLockReset_REQUEST { + fn num_handles(&self) -> u16 { 1 } + +} + +impl ReqStructure for TPM2_DictionaryAttackLockReset_REQUEST { + fn num_auth_handles(&self) -> u16 { 1 } + + fn get_handles(&self) -> Vec { vec![self.lockHandle.clone()] } +} + +/// This command changes the lockout parameters. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_DictionaryAttackParameters_REQUEST { + /// TPM_RH_LOCKOUT + /// Auth Index: 1 + /// Auth Role: USER + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub lockHandle: TPM_HANDLE, + + /// Count of authorization failures before the lockout is imposed + pub newMaxTries: u32, + + /// Time in seconds before the authorization failure count is automatically decremented + /// A value of zero indicates that DA protection is disabled. + pub newRecoveryTime: u32, + + /// Time in seconds after a lockoutAuth failure before use of lockoutAuth is allowed + /// A value of zero indicates that a reboot is required. + pub lockoutRecovery: u32, +} + +impl TPM2_DictionaryAttackParameters_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + lockHandle: &TPM_HANDLE, + newMaxTries: u32, + newRecoveryTime: u32, + lockoutRecovery: u32, + ) -> Self { + Self { + lockHandle: lockHandle.clone(), + newMaxTries: newMaxTries.clone(), + newRecoveryTime: newRecoveryTime.clone(), + lockoutRecovery: lockoutRecovery.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_DictionaryAttackParameters_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeInt(self.newMaxTries as u32); + buf.writeInt(self.newRecoveryTime as u32); + buf.writeInt(self.lockoutRecovery as u32); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.newMaxTries = buf.readInt() as u32; + self.newRecoveryTime = buf.readInt() as u32; + self.lockoutRecovery = buf.readInt() as u32; + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_DictionaryAttackParameters_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_DictionaryAttackParameters_REQUEST { + fn num_handles(&self) -> u16 { 1 } + +} + +impl ReqStructure for TPM2_DictionaryAttackParameters_REQUEST { + fn num_auth_handles(&self) -> u16 { 1 } + + fn get_handles(&self) -> Vec { vec![self.lockHandle.clone()] } +} + +/// This command is used to determine which commands require assertion of Physical +/// Presence (PP) in addition to platformAuth/platformPolicy. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_PP_Commands_REQUEST { + /// TPM_RH_PLATFORM+PP + /// Auth Index: 1 + /// Auth Role: USER + Physical Presence + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub auth: TPM_HANDLE, + + /// List of commands to be added to those that will require that Physical Presence be asserted + pub setList: Vec, + + /// List of commands that will no longer require that Physical Presence be asserted + pub clearList: Vec, +} + +impl TPM2_PP_Commands_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + auth: &TPM_HANDLE, + setList: &Vec, + clearList: &Vec, + ) -> Self { + Self { + auth: auth.clone(), + setList: setList.clone(), + clearList: clearList.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_PP_Commands_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeValArr(self.setList.as_ref(), 4); + buf.writeValArr(self.clearList.as_ref(), 4); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + buf.readValArr(self.setList.as_mut(), 4)?; + buf.readValArr(self.clearList.as_mut(), 4)?; + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_PP_Commands_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_PP_Commands_REQUEST { + fn num_handles(&self) -> u16 { 1 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 4, val_len: 4 } } +} + +impl ReqStructure for TPM2_PP_Commands_REQUEST { + fn num_auth_handles(&self) -> u16 { 1 } + + fn get_handles(&self) -> Vec { vec![self.auth.clone()] } +} + +/// This command allows the platform to change the set of algorithms that are used by the +/// TPM. The algorithmSet setting is a vendor-dependent value. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_SetAlgorithmSet_REQUEST { + /// TPM_RH_PLATFORM + /// Auth Index: 1 + /// Auth Role: USER + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub authHandle: TPM_HANDLE, + + /// A TPM vendor-dependent value indicating the algorithm set selection + pub algorithmSet: u32, +} + +impl TPM2_SetAlgorithmSet_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + authHandle: &TPM_HANDLE, + algorithmSet: u32, + ) -> Self { + Self { + authHandle: authHandle.clone(), + algorithmSet: algorithmSet.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_SetAlgorithmSet_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeInt(self.algorithmSet as u32); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.algorithmSet = buf.readInt() as u32; + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_SetAlgorithmSet_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_SetAlgorithmSet_REQUEST { + fn num_handles(&self) -> u16 { 1 } + +} + +impl ReqStructure for TPM2_SetAlgorithmSet_REQUEST { + fn num_auth_handles(&self) -> u16 { 1 } + + fn get_handles(&self) -> Vec { vec![self.authHandle.clone()] } +} + +/// This command uses platformPolicy and a TPM Vendor Authorization Key to authorize a +/// Field Upgrade Manifest. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_FieldUpgradeStart_REQUEST { + /// TPM_RH_PLATFORM+{PP} + /// Auth Index:1 + /// Auth Role: ADMIN + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub authorization: TPM_HANDLE, + + /// Handle of a public area that contains the TPM Vendor Authorization Key that will be + /// used to validate manifestSignature + /// Auth Index: None + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub keyHandle: TPM_HANDLE, + + /// Digest of the first block in the field upgrade sequence + pub fuDigest: Vec, + + /// Selector of the algorithm used to construct the signature + + /// Signature over fuDigest using the key associated with keyHandle (not optional) + /// One of: TPMS_SIGNATURE_RSASSA, TPMS_SIGNATURE_RSAPSS, TPMS_SIGNATURE_ECDSA, + /// TPMS_SIGNATURE_ECDAA, TPMS_SIGNATURE_SM2, TPMS_SIGNATURE_ECSCHNORR, TPMT_HA, + /// TPMS_SCHEME_HASH, TPMS_NULL_SIGNATURE. + pub manifestSignature: Option, +} + +impl TPM2_FieldUpgradeStart_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + authorization: &TPM_HANDLE, + keyHandle: &TPM_HANDLE, + fuDigest: &Vec, + manifestSignature: &Option, + ) -> Self { + Self { + authorization: authorization.clone(), + keyHandle: keyHandle.clone(), + fuDigest: fuDigest.clone(), + manifestSignature: manifestSignature.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_FieldUpgradeStart_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.fuDigest, 2); + buf.writeShort(self.manifestSignature.as_ref().unwrap().GetUnionSelector().into()); + self.manifestSignature.as_ref().unwrap().toTpm(buf)?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.fuDigest = buf.readSizedByteBuf(2); + let r#manifestSignatureSigAlg: TPM_ALG_ID = TPM_ALG_ID(buf.readShort() as u16); + self.manifestSignature = TPMU_SIGNATURE::create(r#manifestSignatureSigAlg)?; + self.manifestSignature.as_mut().unwrap().initFromTpm(buf)?; + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_FieldUpgradeStart_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_FieldUpgradeStart_REQUEST { + fn num_handles(&self) -> u16 { 2 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 2, val_len: 1 } } +} + +impl ReqStructure for TPM2_FieldUpgradeStart_REQUEST { + fn num_auth_handles(&self) -> u16 { 1 } + + fn get_handles(&self) -> Vec { vec![self.authorization.clone(), self.keyHandle.clone()] } +} + +/// This command will take the actual field upgrade image to be installed on the TPM. The +/// exact format of fuData is vendor-specific. This command is only possible following a +/// successful TPM2_FieldUpgradeStart(). If the TPM has not received a properly authorized +/// TPM2_FieldUpgradeStart(), then the TPM shall return TPM_RC_FIELDUPGRADE. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_FieldUpgradeData_REQUEST { + /// Field upgrade image data + pub fuData: Vec, +} + +impl TPM2_FieldUpgradeData_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + fuData: &Vec, + ) -> Self { + Self { + fuData: fuData.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_FieldUpgradeData_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.fuData, 2); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.fuData = buf.readSizedByteBuf(2); + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_FieldUpgradeData_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_FieldUpgradeData_REQUEST { + fn num_handles(&self) -> u16 { 0 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 2, val_len: 1 } } +} + +impl ReqStructure for TPM2_FieldUpgradeData_REQUEST { + fn num_auth_handles(&self) -> u16 { 0 } + + fn get_handles(&self) -> Vec { vec![] } +} + +/// This command will take the actual field upgrade image to be installed on the TPM. The +/// exact format of fuData is vendor-specific. This command is only possible following a +/// successful TPM2_FieldUpgradeStart(). If the TPM has not received a properly authorized +/// TPM2_FieldUpgradeStart(), then the TPM shall return TPM_RC_FIELDUPGRADE. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct FieldUpgradeDataResponse { + /// Tagged digest of the next block + /// TPM_ALG_NULL if field update is complete + pub nextDigest: TPMT_HA, + + /// Tagged digest of the first block of the sequence + pub firstDigest: TPMT_HA, +} + +impl FieldUpgradeDataResponse { +} + +impl TpmStructure for FieldUpgradeDataResponse { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + self.nextDigest.toTpm(buf)?; + self.firstDigest.toTpm(buf)?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.nextDigest.initFromTpm(buf)?; + self.firstDigest.initFromTpm(buf)?; + Ok(()) + } + +} + +impl TpmMarshaller for FieldUpgradeDataResponse { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for FieldUpgradeDataResponse { + fn num_handles(&self) -> u16 { 0 } + +} + +impl RespStructure for FieldUpgradeDataResponse { + fn get_handle(&self) -> TPM_HANDLE { TPM_HANDLE::default() } + + fn set_handle(&mut self, _handle: &TPM_HANDLE) { } +} + +/// This command is used to read a copy of the current firmware installed in the TPM. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_FirmwareRead_REQUEST { + /// The number of previous calls to this command in this sequence + /// set to 0 on the first call + pub sequenceNumber: u32, +} + +impl TPM2_FirmwareRead_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + sequenceNumber: u32, + ) -> Self { + Self { + sequenceNumber: sequenceNumber.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_FirmwareRead_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeInt(self.sequenceNumber as u32); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.sequenceNumber = buf.readInt() as u32; + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_FirmwareRead_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_FirmwareRead_REQUEST { + fn num_handles(&self) -> u16 { 0 } + +} + +impl ReqStructure for TPM2_FirmwareRead_REQUEST { + fn num_auth_handles(&self) -> u16 { 0 } + + fn get_handles(&self) -> Vec { vec![] } +} + +/// This command is used to read a copy of the current firmware installed in the TPM. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct FirmwareReadResponse { + /// Field upgrade image data + pub fuData: Vec, +} + +impl FirmwareReadResponse { +} + +impl TpmStructure for FirmwareReadResponse { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.fuData, 2); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.fuData = buf.readSizedByteBuf(2); + Ok(()) + } + +} + +impl TpmMarshaller for FirmwareReadResponse { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for FirmwareReadResponse { + fn num_handles(&self) -> u16 { 0 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 2, val_len: 1 } } +} + +impl RespStructure for FirmwareReadResponse { + fn get_handle(&self) -> TPM_HANDLE { TPM_HANDLE::default() } + + fn set_handle(&mut self, _handle: &TPM_HANDLE) { } +} + +/// This command saves a session context, object context, or sequence object context +/// outside the TPM. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_ContextSave_REQUEST { + /// Handle of the resource to save + /// Auth Index: None + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub saveHandle: TPM_HANDLE, +} + +impl TPM2_ContextSave_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + saveHandle: &TPM_HANDLE, + ) -> Self { + Self { + saveHandle: saveHandle.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_ContextSave_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_ContextSave_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_ContextSave_REQUEST { + fn num_handles(&self) -> u16 { 1 } + +} + +impl ReqStructure for TPM2_ContextSave_REQUEST { + fn num_auth_handles(&self) -> u16 { 0 } + + fn get_handles(&self) -> Vec { vec![self.saveHandle.clone()] } +} + +/// This command saves a session context, object context, or sequence object context +/// outside the TPM. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct ContextSaveResponse { + pub context: TPMS_CONTEXT, +} + +impl ContextSaveResponse { +} + +impl TpmStructure for ContextSaveResponse { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + self.context.toTpm(buf)?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.context.initFromTpm(buf)?; + Ok(()) + } + +} + +impl TpmMarshaller for ContextSaveResponse { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for ContextSaveResponse { + fn num_handles(&self) -> u16 { 0 } + +} + +impl RespStructure for ContextSaveResponse { + fn get_handle(&self) -> TPM_HANDLE { TPM_HANDLE::default() } + + fn set_handle(&mut self, _handle: &TPM_HANDLE) { } +} + +/// This command is used to reload a context that has been saved by TPM2_ContextSave(). +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_ContextLoad_REQUEST { + /// The context blob + pub context: TPMS_CONTEXT, +} + +impl TPM2_ContextLoad_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + context: &TPMS_CONTEXT, + ) -> Self { + Self { + context: context.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_ContextLoad_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + self.context.toTpm(buf)?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.context.initFromTpm(buf)?; + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_ContextLoad_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_ContextLoad_REQUEST { + fn num_handles(&self) -> u16 { 0 } + +} + +impl ReqStructure for TPM2_ContextLoad_REQUEST { + fn num_auth_handles(&self) -> u16 { 0 } + + fn get_handles(&self) -> Vec { vec![] } +} + +/// This command is used to reload a context that has been saved by TPM2_ContextSave(). +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct ContextLoadResponse { + /// The handle assigned to the resource after it has been successfully loaded + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub handle: TPM_HANDLE, +} + +impl ContextLoadResponse { +} + +impl TpmStructure for ContextLoadResponse { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + Ok(()) + } + +} + +impl TpmMarshaller for ContextLoadResponse { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for ContextLoadResponse { + fn num_handles(&self) -> u16 { 1 } + +} + +impl RespStructure for ContextLoadResponse { + fn get_handle(&self) -> TPM_HANDLE { self.handle.clone() } + + fn set_handle(&mut self, handle: &TPM_HANDLE) { self.handle = handle.clone(); } +} + +/// This command causes all context associated with a loaded object, sequence object, or +/// session to be removed from TPM memory. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_FlushContext_REQUEST { + /// The handle of the item to flush + /// NOTE This is a use of a handle as a parameter. + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub flushHandle: TPM_HANDLE, +} + +impl TPM2_FlushContext_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + flushHandle: &TPM_HANDLE, + ) -> Self { + Self { + flushHandle: flushHandle.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_FlushContext_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + self.flushHandle.toTpm(buf)?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.flushHandle.initFromTpm(buf)?; + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_FlushContext_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_FlushContext_REQUEST { + fn num_handles(&self) -> u16 { 0 } + +} + +impl ReqStructure for TPM2_FlushContext_REQUEST { + fn num_auth_handles(&self) -> u16 { 0 } + + fn get_handles(&self) -> Vec { vec![] } +} + +/// This command allows certain Transient Objects to be made persistent or a persistent +/// object to be evicted. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_EvictControl_REQUEST { + /// TPM_RH_OWNER or TPM_RH_PLATFORM+{PP} + /// Auth Handle: 1 + /// Auth Role: USER + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub auth: TPM_HANDLE, + + /// The handle of a loaded object + /// Auth Index: None + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub objectHandle: TPM_HANDLE, + + /// If objectHandle is a transient object handle, then this is the persistent handle for + /// the object + /// if objectHandle is a persistent object handle, then it shall be the same value as + /// persistentHandle + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub persistentHandle: TPM_HANDLE, +} + +impl TPM2_EvictControl_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + auth: &TPM_HANDLE, + objectHandle: &TPM_HANDLE, + persistentHandle: &TPM_HANDLE, + ) -> Self { + Self { + auth: auth.clone(), + objectHandle: objectHandle.clone(), + persistentHandle: persistentHandle.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_EvictControl_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + self.persistentHandle.toTpm(buf)?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.persistentHandle.initFromTpm(buf)?; + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_EvictControl_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_EvictControl_REQUEST { + fn num_handles(&self) -> u16 { 2 } + +} + +impl ReqStructure for TPM2_EvictControl_REQUEST { + fn num_auth_handles(&self) -> u16 { 1 } + + fn get_handles(&self) -> Vec { vec![self.auth.clone(), self.objectHandle.clone()] } +} + +/// This command reads the current TPMS_TIME_INFO structure that contains the current +/// setting of Time, Clock, resetCount, and restartCount. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_ReadClock_REQUEST { +} + +impl TPM2_ReadClock_REQUEST { +} + +impl TpmStructure for TPM2_ReadClock_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_ReadClock_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_ReadClock_REQUEST { + fn num_handles(&self) -> u16 { 0 } + +} + +impl ReqStructure for TPM2_ReadClock_REQUEST { + fn num_auth_handles(&self) -> u16 { 0 } + + fn get_handles(&self) -> Vec { vec![] } +} + +/// This command reads the current TPMS_TIME_INFO structure that contains the current +/// setting of Time, Clock, resetCount, and restartCount. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct ReadClockResponse { + pub currentTime: TPMS_TIME_INFO, +} + +impl ReadClockResponse { +} + +impl TpmStructure for ReadClockResponse { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + self.currentTime.toTpm(buf)?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.currentTime.initFromTpm(buf)?; + Ok(()) + } + +} + +impl TpmMarshaller for ReadClockResponse { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for ReadClockResponse { + fn num_handles(&self) -> u16 { 0 } + +} + +impl RespStructure for ReadClockResponse { + fn get_handle(&self) -> TPM_HANDLE { TPM_HANDLE::default() } + + fn set_handle(&mut self, _handle: &TPM_HANDLE) { } +} + +/// This command is used to advance the value of the TPMs Clock. The command will fail if +/// newTime is less than the current value of Clock or if the new time is greater than +/// FFFF00000000000016. If both of these checks succeed, Clock is set to newTime. If +/// either of these checks fails, the TPM shall return TPM_RC_VALUE and make no change to Clock. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_ClockSet_REQUEST { + /// TPM_RH_OWNER or TPM_RH_PLATFORM+{PP} + /// Auth Handle: 1 + /// Auth Role: USER + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub auth: TPM_HANDLE, + + /// New Clock setting in milliseconds + pub newTime: u64, +} + +impl TPM2_ClockSet_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + auth: &TPM_HANDLE, + newTime: u64, + ) -> Self { + Self { + auth: auth.clone(), + newTime: newTime.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_ClockSet_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeInt64(self.newTime as u64); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.newTime = buf.readInt64() as u64; + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_ClockSet_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_ClockSet_REQUEST { + fn num_handles(&self) -> u16 { 1 } + +} + +impl ReqStructure for TPM2_ClockSet_REQUEST { + fn num_auth_handles(&self) -> u16 { 1 } + + fn get_handles(&self) -> Vec { vec![self.auth.clone()] } +} + +/// This command adjusts the rate of advance of Clock and Time to provide a better +/// approximation to real time. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_ClockRateAdjust_REQUEST { + /// TPM_RH_OWNER or TPM_RH_PLATFORM+{PP} + /// Auth Handle: 1 + /// Auth Role: USER + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub auth: TPM_HANDLE, + + /// Adjustment to current Clock update rate + pub rateAdjust: TPM_CLOCK_ADJUST, +} + +impl TPM2_ClockRateAdjust_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + auth: &TPM_HANDLE, + rateAdjust: TPM_CLOCK_ADJUST, + ) -> Self { + Self { + auth: auth.clone(), + rateAdjust: rateAdjust.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_ClockRateAdjust_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeByte(self.rateAdjust.into()); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.rateAdjust = TPM_CLOCK_ADJUST(buf.readByte() as i8); + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_ClockRateAdjust_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_ClockRateAdjust_REQUEST { + fn num_handles(&self) -> u16 { 1 } + +} + +impl ReqStructure for TPM2_ClockRateAdjust_REQUEST { + fn num_auth_handles(&self) -> u16 { 1 } + + fn get_handles(&self) -> Vec { vec![self.auth.clone()] } +} + +/// This command returns various information regarding the TPM and its current state. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_GetCapability_REQUEST { + /// Group selection; determines the format of the response + pub capability: TPM_CAP, + + /// Further definition of information + pub property: u32, + + /// Number of properties of the indicated type to return + pub propertyCount: u32, +} + +impl TPM2_GetCapability_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + capability: TPM_CAP, + property: u32, + propertyCount: u32, + ) -> Self { + Self { + capability: capability.clone(), + property: property.clone(), + propertyCount: propertyCount.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_GetCapability_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeInt(self.capability.into()); + buf.writeInt(self.property as u32); + buf.writeInt(self.propertyCount as u32); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.capability = TPM_CAP(buf.readInt() as u32); + self.property = buf.readInt() as u32; + self.propertyCount = buf.readInt() as u32; + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_GetCapability_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_GetCapability_REQUEST { + fn num_handles(&self) -> u16 { 0 } + +} + +impl ReqStructure for TPM2_GetCapability_REQUEST { + fn num_auth_handles(&self) -> u16 { 0 } + + fn get_handles(&self) -> Vec { vec![] } +} + +/// This command returns various information regarding the TPM and its current state. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct GetCapabilityResponse { + /// Flag to indicate if there are more values of this type + pub moreData: u8, + + /// The capability + + /// The capability data + /// One of: TPML_ALG_PROPERTY, TPML_HANDLE, TPML_CCA, TPML_CC, TPML_PCR_SELECTION, + /// TPML_TAGGED_TPM_PROPERTY, TPML_TAGGED_PCR_PROPERTY, TPML_ECC_CURVE, + /// TPML_TAGGED_POLICY, TPML_ACT_DATA. + pub capabilityData: Option, +} + +impl GetCapabilityResponse { +} + +impl TpmStructure for GetCapabilityResponse { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeByte(self.moreData as u8); + buf.writeInt(self.capabilityData.as_ref().unwrap().GetUnionSelector().into()); + self.capabilityData.as_ref().unwrap().toTpm(buf)?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.moreData = buf.readByte() as u8; + let r#capabilityDataCapability: TPM_CAP = TPM_CAP(buf.readInt() as u32); + self.capabilityData = TPMU_CAPABILITIES::create(r#capabilityDataCapability)?; + self.capabilityData.as_mut().unwrap().initFromTpm(buf)?; + Ok(()) + } + +} + +impl TpmMarshaller for GetCapabilityResponse { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for GetCapabilityResponse { + fn num_handles(&self) -> u16 { 0 } + +} + +impl RespStructure for GetCapabilityResponse { + fn get_handle(&self) -> TPM_HANDLE { TPM_HANDLE::default() } + + fn set_handle(&mut self, _handle: &TPM_HANDLE) { } +} + +/// This command is used to check to see if specific combinations of algorithm parameters +/// are supported. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_TestParms_REQUEST { + /// The algorithm to be tested + + /// Algorithm parameters to be validated + /// One of: TPMS_KEYEDHASH_PARMS, TPMS_SYMCIPHER_PARMS, TPMS_RSA_PARMS, TPMS_ECC_PARMS, + /// TPMS_ASYM_PARMS. + pub parameters: Option, +} + +impl TPM2_TestParms_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + parameters: &Option, + ) -> Self { + Self { + parameters: parameters.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_TestParms_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + if (self.parameters.is_none()) { return Ok(()) }; + buf.writeShort(self.parameters.as_ref().unwrap().GetUnionSelector().into()); + self.parameters.as_ref().unwrap().toTpm(buf)?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + let r#parametersType: TPM_ALG_ID = TPM_ALG_ID(buf.readShort() as u16); + self.parameters = TPMU_PUBLIC_PARMS::create(r#parametersType)?; + self.parameters.as_mut().unwrap().initFromTpm(buf)?; + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_TestParms_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_TestParms_REQUEST { + fn num_handles(&self) -> u16 { 0 } + +} + +impl ReqStructure for TPM2_TestParms_REQUEST { + fn num_auth_handles(&self) -> u16 { 0 } + + fn get_handles(&self) -> Vec { vec![] } +} + +/// This command defines the attributes of an NV Index and causes the TPM to reserve space +/// to hold the data associated with the NV Index. If a definition already exists at the +/// NV Index, the TPM will return TPM_RC_NV_DEFINED. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_NV_DefineSpace_REQUEST { + /// TPM_RH_OWNER or TPM_RH_PLATFORM+{PP} + /// Auth Index: 1 + /// Auth Role: USER + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub authHandle: TPM_HANDLE, + + /// The authorization value + pub auth: Vec, + + /// The public parameters of the NV area + pub publicInfo: TPMS_NV_PUBLIC, +} + +impl TPM2_NV_DefineSpace_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + authHandle: &TPM_HANDLE, + auth: &Vec, + publicInfo: &TPMS_NV_PUBLIC, + ) -> Self { + Self { + authHandle: authHandle.clone(), + auth: auth.clone(), + publicInfo: publicInfo.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_NV_DefineSpace_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.auth, 2); + buf.writeSizedObj(&self.publicInfo)?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.auth = buf.readSizedByteBuf(2); + buf.readSizedObj(&mut self.publicInfo)?; + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_NV_DefineSpace_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_NV_DefineSpace_REQUEST { + fn num_handles(&self) -> u16 { 1 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 2, val_len: 1 } } +} + +impl ReqStructure for TPM2_NV_DefineSpace_REQUEST { + fn num_auth_handles(&self) -> u16 { 1 } + + fn get_handles(&self) -> Vec { vec![self.authHandle.clone()] } +} + +/// This command removes an Index from the TPM. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_NV_UndefineSpace_REQUEST { + /// TPM_RH_OWNER or TPM_RH_PLATFORM+{PP} + /// Auth Index: 1 + /// Auth Role: USER + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub authHandle: TPM_HANDLE, + + /// The NV Index to remove from NV space + /// Auth Index: None + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub nvIndex: TPM_HANDLE, +} + +impl TPM2_NV_UndefineSpace_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + authHandle: &TPM_HANDLE, + nvIndex: &TPM_HANDLE, + ) -> Self { + Self { + authHandle: authHandle.clone(), + nvIndex: nvIndex.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_NV_UndefineSpace_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_NV_UndefineSpace_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_NV_UndefineSpace_REQUEST { + fn num_handles(&self) -> u16 { 2 } + +} + +impl ReqStructure for TPM2_NV_UndefineSpace_REQUEST { + fn num_auth_handles(&self) -> u16 { 1 } + + fn get_handles(&self) -> Vec { vec![self.authHandle.clone(), self.nvIndex.clone()] } +} + +/// This command allows removal of a platform-created NV Index that has +/// TPMA_NV_POLICY_DELETE SET. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_NV_UndefineSpaceSpecial_REQUEST { + /// Index to be deleted + /// Auth Index: 1 + /// Auth Role: ADMIN + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub nvIndex: TPM_HANDLE, + + /// TPM_RH_PLATFORM + {PP} + /// Auth Index: 2 + /// Auth Role: USER + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub platform: TPM_HANDLE, +} + +impl TPM2_NV_UndefineSpaceSpecial_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + nvIndex: &TPM_HANDLE, + platform: &TPM_HANDLE, + ) -> Self { + Self { + nvIndex: nvIndex.clone(), + platform: platform.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_NV_UndefineSpaceSpecial_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_NV_UndefineSpaceSpecial_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_NV_UndefineSpaceSpecial_REQUEST { + fn num_handles(&self) -> u16 { 2 } + +} + +impl ReqStructure for TPM2_NV_UndefineSpaceSpecial_REQUEST { + fn num_auth_handles(&self) -> u16 { 2 } + + fn get_handles(&self) -> Vec { vec![self.nvIndex.clone(), self.platform.clone()] } +} + +/// This command is used to read the public area and Name of an NV Index. The public area +/// of an Index is not privacy-sensitive and no authorization is required to read this data. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_NV_ReadPublic_REQUEST { + /// The NV Index + /// Auth Index: None + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub nvIndex: TPM_HANDLE, +} + +impl TPM2_NV_ReadPublic_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + nvIndex: &TPM_HANDLE, + ) -> Self { + Self { + nvIndex: nvIndex.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_NV_ReadPublic_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_NV_ReadPublic_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_NV_ReadPublic_REQUEST { + fn num_handles(&self) -> u16 { 1 } + +} + +impl ReqStructure for TPM2_NV_ReadPublic_REQUEST { + fn num_auth_handles(&self) -> u16 { 0 } + + fn get_handles(&self) -> Vec { vec![self.nvIndex.clone()] } +} + +/// This command is used to read the public area and Name of an NV Index. The public area +/// of an Index is not privacy-sensitive and no authorization is required to read this data. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct NV_ReadPublicResponse { + /// The public area of the NV Index + pub nvPublic: TPMS_NV_PUBLIC, + + /// The Name of the nvIndex + pub nvName: Vec, +} + +impl NV_ReadPublicResponse { +} + +impl TpmStructure for NV_ReadPublicResponse { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedObj(&self.nvPublic)?; + buf.writeSizedByteBuf(&self.nvName, 2); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + buf.readSizedObj(&mut self.nvPublic)?; + self.nvName = buf.readSizedByteBuf(2); + Ok(()) + } + +} + +impl TpmMarshaller for NV_ReadPublicResponse { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for NV_ReadPublicResponse { + fn num_handles(&self) -> u16 { 0 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 2, val_len: 1 } } +} + +impl RespStructure for NV_ReadPublicResponse { + fn get_handle(&self) -> TPM_HANDLE { TPM_HANDLE::default() } + + fn set_handle(&mut self, _handle: &TPM_HANDLE) { } +} + +/// This command writes a value to an area in NV memory that was previously defined by +/// TPM2_NV_DefineSpace(). +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_NV_Write_REQUEST { + /// Handle indicating the source of the authorization value + /// Auth Index: 1 + /// Auth Role: USER + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub authHandle: TPM_HANDLE, + + /// The NV Index of the area to write + /// Auth Index: None + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub nvIndex: TPM_HANDLE, + + /// The data to write + pub data: Vec, + + /// The octet offset into the NV Area + pub offset: u16, +} + +impl TPM2_NV_Write_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + authHandle: &TPM_HANDLE, + nvIndex: &TPM_HANDLE, + data: &Vec, + offset: u16, + ) -> Self { + Self { + authHandle: authHandle.clone(), + nvIndex: nvIndex.clone(), + data: data.clone(), + offset: offset.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_NV_Write_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.data, 2); + buf.writeShort(self.offset as u16); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.data = buf.readSizedByteBuf(2); + self.offset = buf.readShort() as u16; + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_NV_Write_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_NV_Write_REQUEST { + fn num_handles(&self) -> u16 { 2 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 2, val_len: 1 } } +} + +impl ReqStructure for TPM2_NV_Write_REQUEST { + fn num_auth_handles(&self) -> u16 { 1 } + + fn get_handles(&self) -> Vec { vec![self.authHandle.clone(), self.nvIndex.clone()] } +} + +/// This command is used to increment the value in an NV Index that has the TPM_NT_COUNTER +/// attribute. The data value of the NV Index is incremented by one. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_NV_Increment_REQUEST { + /// Handle indicating the source of the authorization value + /// Auth Index: 1 + /// Auth Role: USER + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub authHandle: TPM_HANDLE, + + /// The NV Index to increment + /// Auth Index: None + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub nvIndex: TPM_HANDLE, +} + +impl TPM2_NV_Increment_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + authHandle: &TPM_HANDLE, + nvIndex: &TPM_HANDLE, + ) -> Self { + Self { + authHandle: authHandle.clone(), + nvIndex: nvIndex.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_NV_Increment_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_NV_Increment_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_NV_Increment_REQUEST { + fn num_handles(&self) -> u16 { 2 } + +} + +impl ReqStructure for TPM2_NV_Increment_REQUEST { + fn num_auth_handles(&self) -> u16 { 1 } + + fn get_handles(&self) -> Vec { vec![self.authHandle.clone(), self.nvIndex.clone()] } +} + +/// This command extends a value to an area in NV memory that was previously defined by +/// TPM2_NV_DefineSpace. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_NV_Extend_REQUEST { + /// Handle indicating the source of the authorization value + /// Auth Index: 1 + /// Auth Role: USER + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub authHandle: TPM_HANDLE, + + /// The NV Index to extend + /// Auth Index: None + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub nvIndex: TPM_HANDLE, + + /// The data to extend + pub data: Vec, +} + +impl TPM2_NV_Extend_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + authHandle: &TPM_HANDLE, + nvIndex: &TPM_HANDLE, + data: &Vec, + ) -> Self { + Self { + authHandle: authHandle.clone(), + nvIndex: nvIndex.clone(), + data: data.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_NV_Extend_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.data, 2); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.data = buf.readSizedByteBuf(2); + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_NV_Extend_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_NV_Extend_REQUEST { + fn num_handles(&self) -> u16 { 2 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 2, val_len: 1 } } +} + +impl ReqStructure for TPM2_NV_Extend_REQUEST { + fn num_auth_handles(&self) -> u16 { 1 } + + fn get_handles(&self) -> Vec { vec![self.authHandle.clone(), self.nvIndex.clone()] } +} + +/// This command is used to SET bits in an NV Index that was created as a bit field. Any +/// number of bits from 0 to 64 may be SET. The contents of bits are ORed with the current +/// contents of the NV Index. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_NV_SetBits_REQUEST { + /// Handle indicating the source of the authorization value + /// Auth Index: 1 + /// Auth Role: USER + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub authHandle: TPM_HANDLE, + + /// NV Index of the area in which the bit is to be set + /// Auth Index: None + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub nvIndex: TPM_HANDLE, + + /// The data to OR with the current contents + pub bits: u64, +} + +impl TPM2_NV_SetBits_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + authHandle: &TPM_HANDLE, + nvIndex: &TPM_HANDLE, + bits: u64, + ) -> Self { + Self { + authHandle: authHandle.clone(), + nvIndex: nvIndex.clone(), + bits: bits.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_NV_SetBits_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeInt64(self.bits as u64); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.bits = buf.readInt64() as u64; + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_NV_SetBits_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_NV_SetBits_REQUEST { + fn num_handles(&self) -> u16 { 2 } + +} + +impl ReqStructure for TPM2_NV_SetBits_REQUEST { + fn num_auth_handles(&self) -> u16 { 1 } + + fn get_handles(&self) -> Vec { vec![self.authHandle.clone(), self.nvIndex.clone()] } +} + +/// If the TPMA_NV_WRITEDEFINE or TPMA_NV_WRITE_STCLEAR attributes of an NV location are +/// SET, then this command may be used to inhibit further writes of the NV Index. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_NV_WriteLock_REQUEST { + /// Handle indicating the source of the authorization value + /// Auth Index: 1 + /// Auth Role: USER + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub authHandle: TPM_HANDLE, + + /// The NV Index of the area to lock + /// Auth Index: None + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub nvIndex: TPM_HANDLE, +} + +impl TPM2_NV_WriteLock_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + authHandle: &TPM_HANDLE, + nvIndex: &TPM_HANDLE, + ) -> Self { + Self { + authHandle: authHandle.clone(), + nvIndex: nvIndex.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_NV_WriteLock_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_NV_WriteLock_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_NV_WriteLock_REQUEST { + fn num_handles(&self) -> u16 { 2 } + +} + +impl ReqStructure for TPM2_NV_WriteLock_REQUEST { + fn num_auth_handles(&self) -> u16 { 1 } + + fn get_handles(&self) -> Vec { vec![self.authHandle.clone(), self.nvIndex.clone()] } +} + +/// The command will SET TPMA_NV_WRITELOCKED for all indexes that have their +/// TPMA_NV_GLOBALLOCK attribute SET. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_NV_GlobalWriteLock_REQUEST { + /// TPM_RH_OWNER or TPM_RH_PLATFORM+{PP} + /// Auth Index: 1 + /// Auth Role: USER + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub authHandle: TPM_HANDLE, +} + +impl TPM2_NV_GlobalWriteLock_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + authHandle: &TPM_HANDLE, + ) -> Self { + Self { + authHandle: authHandle.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_NV_GlobalWriteLock_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_NV_GlobalWriteLock_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_NV_GlobalWriteLock_REQUEST { + fn num_handles(&self) -> u16 { 1 } + +} + +impl ReqStructure for TPM2_NV_GlobalWriteLock_REQUEST { + fn num_auth_handles(&self) -> u16 { 1 } + + fn get_handles(&self) -> Vec { vec![self.authHandle.clone()] } +} + +/// This command reads a value from an area in NV memory previously defined by TPM2_NV_DefineSpace(). +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_NV_Read_REQUEST { + /// The handle indicating the source of the authorization value + /// Auth Index: 1 + /// Auth Role: USER + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub authHandle: TPM_HANDLE, + + /// The NV Index to be read + /// Auth Index: None + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub nvIndex: TPM_HANDLE, + + /// Number of octets to read + pub size: u16, + + /// Octet offset into the NV area + /// This value shall be less than or equal to the size of the nvIndex data. + pub offset: u16, +} + +impl TPM2_NV_Read_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + authHandle: &TPM_HANDLE, + nvIndex: &TPM_HANDLE, + size: u16, + offset: u16, + ) -> Self { + Self { + authHandle: authHandle.clone(), + nvIndex: nvIndex.clone(), + size: size.clone(), + offset: offset.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_NV_Read_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeShort(self.size as u16); + buf.writeShort(self.offset as u16); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.size = buf.readShort() as u16; + self.offset = buf.readShort() as u16; + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_NV_Read_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_NV_Read_REQUEST { + fn num_handles(&self) -> u16 { 2 } + +} + +impl ReqStructure for TPM2_NV_Read_REQUEST { + fn num_auth_handles(&self) -> u16 { 1 } + + fn get_handles(&self) -> Vec { vec![self.authHandle.clone(), self.nvIndex.clone()] } +} + +/// This command reads a value from an area in NV memory previously defined by TPM2_NV_DefineSpace(). +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct NV_ReadResponse { + /// The data read + pub data: Vec, +} + +impl NV_ReadResponse { +} + +impl TpmStructure for NV_ReadResponse { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.data, 2); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.data = buf.readSizedByteBuf(2); + Ok(()) + } + +} + +impl TpmMarshaller for NV_ReadResponse { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for NV_ReadResponse { + fn num_handles(&self) -> u16 { 0 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 2, val_len: 1 } } +} + +impl RespStructure for NV_ReadResponse { + fn get_handle(&self) -> TPM_HANDLE { TPM_HANDLE::default() } + + fn set_handle(&mut self, _handle: &TPM_HANDLE) { } +} + +/// If TPMA_NV_READ_STCLEAR is SET in an Index, then this command may be used to prevent +/// further reads of the NV Index until the next TPM2_Startup (TPM_SU_CLEAR). +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_NV_ReadLock_REQUEST { + /// The handle indicating the source of the authorization value + /// Auth Index: 1 + /// Auth Role: USER + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub authHandle: TPM_HANDLE, + + /// The NV Index to be locked + /// Auth Index: None + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub nvIndex: TPM_HANDLE, +} + +impl TPM2_NV_ReadLock_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + authHandle: &TPM_HANDLE, + nvIndex: &TPM_HANDLE, + ) -> Self { + Self { + authHandle: authHandle.clone(), + nvIndex: nvIndex.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_NV_ReadLock_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_NV_ReadLock_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_NV_ReadLock_REQUEST { + fn num_handles(&self) -> u16 { 2 } + +} + +impl ReqStructure for TPM2_NV_ReadLock_REQUEST { + fn num_auth_handles(&self) -> u16 { 1 } + + fn get_handles(&self) -> Vec { vec![self.authHandle.clone(), self.nvIndex.clone()] } +} + +/// This command allows the authorization secret for an NV Index to be changed. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_NV_ChangeAuth_REQUEST { + /// Handle of the entity + /// Auth Index: 1 + /// Auth Role: ADMIN + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub nvIndex: TPM_HANDLE, + + /// New authorization value + pub newAuth: Vec, +} + +impl TPM2_NV_ChangeAuth_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + nvIndex: &TPM_HANDLE, + newAuth: &Vec, + ) -> Self { + Self { + nvIndex: nvIndex.clone(), + newAuth: newAuth.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_NV_ChangeAuth_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.newAuth, 2); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.newAuth = buf.readSizedByteBuf(2); + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_NV_ChangeAuth_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_NV_ChangeAuth_REQUEST { + fn num_handles(&self) -> u16 { 1 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 2, val_len: 1 } } +} + +impl ReqStructure for TPM2_NV_ChangeAuth_REQUEST { + fn num_auth_handles(&self) -> u16 { 1 } + + fn get_handles(&self) -> Vec { vec![self.nvIndex.clone()] } +} + +/// The purpose of this command is to certify the contents of an NV Index or portion of an +/// NV Index. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_NV_Certify_REQUEST { + /// Handle of the key used to sign the attestation structure + /// Auth Index: 1 + /// Auth Role: USER + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub signHandle: TPM_HANDLE, + + /// Handle indicating the source of the authorization value for the NV Index + /// Auth Index: 2 + /// Auth Role: USER + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub authHandle: TPM_HANDLE, + + /// Index for the area to be certified + /// Auth Index: None + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub nvIndex: TPM_HANDLE, + + /// User-provided qualifying data + pub qualifyingData: Vec, + + /// Scheme selector + + /// Signing scheme to use if the scheme for signHandle is TPM_ALG_NULL + /// One of: TPMS_SIG_SCHEME_RSASSA, TPMS_SIG_SCHEME_RSAPSS, TPMS_SIG_SCHEME_ECDSA, + /// TPMS_SIG_SCHEME_ECDAA, TPMS_SIG_SCHEME_SM2, TPMS_SIG_SCHEME_ECSCHNORR, + /// TPMS_SCHEME_HMAC, TPMS_SCHEME_HASH, TPMS_NULL_SIG_SCHEME. + pub inScheme: Option, + + /// Number of octets to certify + pub size: u16, + + /// Octet offset into the NV area + /// This value shall be less than or equal to the size of the nvIndex data. + pub offset: u16, +} + +impl TPM2_NV_Certify_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + signHandle: &TPM_HANDLE, + authHandle: &TPM_HANDLE, + nvIndex: &TPM_HANDLE, + qualifyingData: &Vec, + inScheme: &Option, + size: u16, + offset: u16, + ) -> Self { + Self { + signHandle: signHandle.clone(), + authHandle: authHandle.clone(), + nvIndex: nvIndex.clone(), + qualifyingData: qualifyingData.clone(), + inScheme: inScheme.clone(), + size: size.clone(), + offset: offset.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_NV_Certify_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.qualifyingData, 2); + buf.writeShort(self.inScheme.as_ref().unwrap().GetUnionSelector().into()); + self.inScheme.as_ref().unwrap().toTpm(buf)?; + buf.writeShort(self.size as u16); + buf.writeShort(self.offset as u16); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.qualifyingData = buf.readSizedByteBuf(2); + let r#inSchemeScheme: TPM_ALG_ID = TPM_ALG_ID(buf.readShort() as u16); + self.inScheme = TPMU_SIG_SCHEME::create(r#inSchemeScheme)?; + self.inScheme.as_mut().unwrap().initFromTpm(buf)?; + self.size = buf.readShort() as u16; + self.offset = buf.readShort() as u16; + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_NV_Certify_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_NV_Certify_REQUEST { + fn num_handles(&self) -> u16 { 3 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 2, val_len: 1 } } +} + +impl ReqStructure for TPM2_NV_Certify_REQUEST { + fn num_auth_handles(&self) -> u16 { 2 } + + fn get_handles(&self) -> Vec { vec![self.signHandle.clone(), self.authHandle.clone(), self.nvIndex.clone()] } +} + +/// The purpose of this command is to certify the contents of an NV Index or portion of an +/// NV Index. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct NV_CertifyResponse { + /// The structure that was signed + pub certifyInfo: TPMS_ATTEST, + + /// Selector of the algorithm used to construct the signature + + /// The asymmetric signature over certifyInfo using the key referenced by signHandle + /// One of: TPMS_SIGNATURE_RSASSA, TPMS_SIGNATURE_RSAPSS, TPMS_SIGNATURE_ECDSA, + /// TPMS_SIGNATURE_ECDAA, TPMS_SIGNATURE_SM2, TPMS_SIGNATURE_ECSCHNORR, TPMT_HA, + /// TPMS_SCHEME_HASH, TPMS_NULL_SIGNATURE. + pub signature: Option, +} + +impl NV_CertifyResponse { +} + +impl TpmStructure for NV_CertifyResponse { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedObj(&self.certifyInfo)?; + buf.writeShort(self.signature.as_ref().unwrap().GetUnionSelector().into()); + self.signature.as_ref().unwrap().toTpm(buf)?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + buf.readSizedObj(&mut self.certifyInfo)?; + let r#signatureSigAlg: TPM_ALG_ID = TPM_ALG_ID(buf.readShort() as u16); + self.signature = TPMU_SIGNATURE::create(r#signatureSigAlg)?; + self.signature.as_mut().unwrap().initFromTpm(buf)?; + Ok(()) + } + +} + +impl TpmMarshaller for NV_CertifyResponse { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for NV_CertifyResponse { + fn num_handles(&self) -> u16 { 0 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 2, val_len: 1 } } +} + +impl RespStructure for NV_CertifyResponse { + fn get_handle(&self) -> TPM_HANDLE { TPM_HANDLE::default() } + + fn set_handle(&mut self, _handle: &TPM_HANDLE) { } +} + +/// The purpose of this command is to obtain information about an Attached Component +/// referenced by an AC handle. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_AC_GetCapability_REQUEST { + /// Handle indicating the Attached Component + /// Auth Index: None + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub ac: TPM_HANDLE, + + /// Starting info type + pub capability: TPM_AT, + + /// Maximum number of values to return + pub count: u32, +} + +impl TPM2_AC_GetCapability_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + ac: &TPM_HANDLE, + capability: TPM_AT, + count: u32, + ) -> Self { + Self { + ac: ac.clone(), + capability: capability.clone(), + count: count.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_AC_GetCapability_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeInt(self.capability.into()); + buf.writeInt(self.count as u32); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.capability = TPM_AT(buf.readInt() as u32); + self.count = buf.readInt() as u32; + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_AC_GetCapability_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_AC_GetCapability_REQUEST { + fn num_handles(&self) -> u16 { 1 } + +} + +impl ReqStructure for TPM2_AC_GetCapability_REQUEST { + fn num_auth_handles(&self) -> u16 { 0 } + + fn get_handles(&self) -> Vec { vec![self.ac.clone()] } +} + +/// The purpose of this command is to obtain information about an Attached Component +/// referenced by an AC handle. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct AC_GetCapabilityResponse { + /// Flag to indicate whether there are more values + pub moreData: u8, + + /// List of capabilities + pub capabilitiesData: Vec, +} + +impl AC_GetCapabilityResponse { +} + +impl TpmStructure for AC_GetCapabilityResponse { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeByte(self.moreData as u8); + buf.writeObjArr(self.capabilitiesData.as_ref())?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.moreData = buf.readByte() as u8; + buf.readObjArr(self.capabilitiesData.as_mut())?; + Ok(()) + } + +} + +impl TpmMarshaller for AC_GetCapabilityResponse { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for AC_GetCapabilityResponse { + fn num_handles(&self) -> u16 { 0 } + +} + +impl RespStructure for AC_GetCapabilityResponse { + fn get_handle(&self) -> TPM_HANDLE { TPM_HANDLE::default() } + + fn set_handle(&mut self, _handle: &TPM_HANDLE) { } +} + +/// The purpose of this command is to send (copy) a loaded object from the TPM to an +/// Attached Component. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_AC_Send_REQUEST { + /// Handle of the object being sent to ac + /// Auth Index: 1 + /// Auth Role: DUP + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub sendObject: TPM_HANDLE, + + /// The handle indicating the source of the authorization value + /// Auth Index: 2 + /// Auth Role: USER + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub authHandle: TPM_HANDLE, + + /// Handle indicating the Attached Component to which the object will be sent + /// Auth Index: None + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub ac: TPM_HANDLE, + + /// Optional non sensitive information related to the object + pub acDataIn: Vec, +} + +impl TPM2_AC_Send_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + sendObject: &TPM_HANDLE, + authHandle: &TPM_HANDLE, + ac: &TPM_HANDLE, + acDataIn: &Vec, + ) -> Self { + Self { + sendObject: sendObject.clone(), + authHandle: authHandle.clone(), + ac: ac.clone(), + acDataIn: acDataIn.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_AC_Send_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.acDataIn, 2); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.acDataIn = buf.readSizedByteBuf(2); + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_AC_Send_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_AC_Send_REQUEST { + fn num_handles(&self) -> u16 { 3 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 2, val_len: 1 } } +} + +impl ReqStructure for TPM2_AC_Send_REQUEST { + fn num_auth_handles(&self) -> u16 { 2 } + + fn get_handles(&self) -> Vec { vec![self.sendObject.clone(), self.authHandle.clone(), self.ac.clone()] } +} + +/// The purpose of this command is to send (copy) a loaded object from the TPM to an +/// Attached Component. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct AC_SendResponse { + /// May include AC specific data or information about an error. + pub acDataOut: TPMS_AC_OUTPUT, +} + +impl AC_SendResponse { +} + +impl TpmStructure for AC_SendResponse { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + self.acDataOut.toTpm(buf)?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.acDataOut.initFromTpm(buf)?; + Ok(()) + } + +} + +impl TpmMarshaller for AC_SendResponse { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for AC_SendResponse { + fn num_handles(&self) -> u16 { 0 } + +} + +impl RespStructure for AC_SendResponse { + fn get_handle(&self) -> TPM_HANDLE { TPM_HANDLE::default() } + + fn set_handle(&mut self, _handle: &TPM_HANDLE) { } +} + +/// This command allows qualification of the sending (copying) of an Object to an Attached +/// Component (AC). Qualification includes selection of the receiving AC and the method of +/// authentication for the AC, and, in certain circumstances, the Object to be sent may be +/// specified. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_Policy_AC_SendSelect_REQUEST { + /// Handle for the policy session being extended + /// Auth Index: None + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub policySession: TPM_HANDLE, + + /// The Name of the Object to be sent + pub objectName: Vec, + + /// The Name associated with authHandle used in the TPM2_AC_Send() command + pub authHandleName: Vec, + + /// The Name of the Attached Component to which the Object will be sent + pub acName: Vec, + + /// If SET, objectName will be included in the value in policySessionpolicyDigest + pub includeObject: u8, +} + +impl TPM2_Policy_AC_SendSelect_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + policySession: &TPM_HANDLE, + objectName: &Vec, + authHandleName: &Vec, + acName: &Vec, + includeObject: u8, + ) -> Self { + Self { + policySession: policySession.clone(), + objectName: objectName.clone(), + authHandleName: authHandleName.clone(), + acName: acName.clone(), + includeObject: includeObject.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_Policy_AC_SendSelect_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.objectName, 2); + buf.writeSizedByteBuf(&self.authHandleName, 2); + buf.writeSizedByteBuf(&self.acName, 2); + buf.writeByte(self.includeObject as u8); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.objectName = buf.readSizedByteBuf(2); + self.authHandleName = buf.readSizedByteBuf(2); + self.acName = buf.readSizedByteBuf(2); + self.includeObject = buf.readByte() as u8; + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_Policy_AC_SendSelect_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_Policy_AC_SendSelect_REQUEST { + fn num_handles(&self) -> u16 { 1 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 2, val_len: 1 } } +} + +impl ReqStructure for TPM2_Policy_AC_SendSelect_REQUEST { + fn num_auth_handles(&self) -> u16 { 0 } + + fn get_handles(&self) -> Vec { vec![self.policySession.clone()] } +} + +/// This command is used to set the time remaining before an Authenticated Countdown Timer +/// (ACT) expires. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_ACT_SetTimeout_REQUEST { + /// Handle of the selected ACT + /// Auth Index: 1 + /// Auth Role: USER + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub actHandle: TPM_HANDLE, + + /// The start timeout value for the ACT in seconds + pub startTimeout: u32, +} + +impl TPM2_ACT_SetTimeout_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + actHandle: &TPM_HANDLE, + startTimeout: u32, + ) -> Self { + Self { + actHandle: actHandle.clone(), + startTimeout: startTimeout.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_ACT_SetTimeout_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeInt(self.startTimeout as u32); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.startTimeout = buf.readInt() as u32; + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_ACT_SetTimeout_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_ACT_SetTimeout_REQUEST { + fn num_handles(&self) -> u16 { 1 } + +} + +impl ReqStructure for TPM2_ACT_SetTimeout_REQUEST { + fn num_auth_handles(&self) -> u16 { 1 } + + fn get_handles(&self) -> Vec { vec![self.actHandle.clone()] } +} + +/// This is a placeholder to allow testing of the dispatch code. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2_Vendor_TCG_Test_REQUEST { + /// Dummy data + pub inputData: Vec, +} + +impl TPM2_Vendor_TCG_Test_REQUEST { + /// Creates a new instance with the specified values + pub fn new( + inputData: &Vec, + ) -> Self { + Self { + inputData: inputData.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TPM2_Vendor_TCG_Test_REQUEST { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.inputData, 2); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.inputData = buf.readSizedByteBuf(2); + Ok(()) + } + +} + +impl TpmMarshaller for TPM2_Vendor_TCG_Test_REQUEST { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for TPM2_Vendor_TCG_Test_REQUEST { + fn num_handles(&self) -> u16 { 0 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 2, val_len: 1 } } +} + +impl ReqStructure for TPM2_Vendor_TCG_Test_REQUEST { + fn num_auth_handles(&self) -> u16 { 0 } + + fn get_handles(&self) -> Vec { vec![] } +} + +/// This is a placeholder to allow testing of the dispatch code. +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct Vendor_TCG_TestResponse { + /// Dummy data + pub outputData: Vec, +} + +impl Vendor_TCG_TestResponse { +} + +impl TpmStructure for Vendor_TCG_TestResponse { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.outputData, 2); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.outputData = buf.readSizedByteBuf(2); + Ok(()) + } + +} + +impl TpmMarshaller for Vendor_TCG_TestResponse { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +impl CmdStructure for Vendor_TCG_TestResponse { + fn num_handles(&self) -> u16 { 0 } + + fn sess_enc_info(&self) -> SessEncInfo { SessEncInfo { size_len: 2, val_len: 1 } } +} + +impl RespStructure for Vendor_TCG_TestResponse { + fn get_handle(&self) -> TPM_HANDLE { TPM_HANDLE::default() } + + fn set_handle(&mut self, _handle: &TPM_HANDLE) { } +} + +/// These are the RSA schemes that only need a hash algorithm as a scheme parameter. +pub type TPMS_SCHEME_RSASSA = TPMS_SIG_SCHEME_RSASSA; + +/// These are the RSA schemes that only need a hash algorithm as a scheme parameter. +pub type TPMS_SCHEME_RSAPSS = TPMS_SIG_SCHEME_RSAPSS; + +/// Most of the ECC signature schemes only require a hash algorithm to complete the +/// definition and can be typed as TPMS_SCHEME_HASH. Anonymous algorithms also require a +/// count value so they are typed to be TPMS_SCHEME_ECDAA. +pub type TPMS_SCHEME_ECDSA = TPMS_SIG_SCHEME_ECDSA; + +/// Most of the ECC signature schemes only require a hash algorithm to complete the +/// definition and can be typed as TPMS_SCHEME_HASH. Anonymous algorithms also require a +/// count value so they are typed to be TPMS_SCHEME_ECDAA. +pub type TPMS_SCHEME_SM2 = TPMS_SIG_SCHEME_SM2; + +/// Most of the ECC signature schemes only require a hash algorithm to complete the +/// definition and can be typed as TPMS_SCHEME_HASH. Anonymous algorithms also require a +/// count value so they are typed to be TPMS_SCHEME_ECDAA. +pub type TPMS_SCHEME_ECSCHNORR = TPMS_SIG_SCHEME_ECSCHNORR; + +/// These are the RSA encryption schemes that only need a hash algorithm as a controlling parameter. +pub type TPMS_SCHEME_OAEP = TPMS_ENC_SCHEME_OAEP; + +/// These are the RSA encryption schemes that only need a hash algorithm as a controlling parameter. +pub type TPMS_SCHEME_RSAES = TPMS_ENC_SCHEME_RSAES; + +/// These are the ECC schemes that only need a hash algorithm as a controlling parameter. +pub type TPMS_SCHEME_ECDH = TPMS_KEY_SCHEME_ECDH; + +/// These are the ECC schemes that only need a hash algorithm as a controlling parameter. +pub type TPMS_SCHEME_ECMQV = TPMS_KEY_SCHEME_ECMQV; + +/// These structures are used to define the key derivation for symmetric secret sharing +/// using asymmetric methods. A secret sharing scheme is required in any asymmetric key +/// with the decrypt attribute SET. +pub type TPMS_SCHEME_MGF1 = TPMS_KDF_SCHEME_MGF1; + +/// These structures are used to define the key derivation for symmetric secret sharing +/// using asymmetric methods. A secret sharing scheme is required in any asymmetric key +/// with the decrypt attribute SET. +pub type TPMS_SCHEME_KDF1_SP800_56A = TPMS_KDF_SCHEME_KDF1_SP800_56A; + +/// These structures are used to define the key derivation for symmetric secret sharing +/// using asymmetric methods. A secret sharing scheme is required in any asymmetric key +/// with the decrypt attribute SET. +pub type TPMS_SCHEME_KDF2 = TPMS_KDF_SCHEME_KDF2; + +/// These structures are used to define the key derivation for symmetric secret sharing +/// using asymmetric methods. A secret sharing scheme is required in any asymmetric key +/// with the decrypt attribute SET. +pub type TPMS_SCHEME_KDF1_SP800_108 = TPMS_KDF_SCHEME_KDF1_SP800_108; + +/// Contains the public and the plaintext-sensitive and/or encrypted private part of a TPM +/// key (or other object) +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TssObject { + /// Public part of key + pub Public: TPMT_PUBLIC, + + /// Sensitive part of key + pub Sensitive: TPMT_SENSITIVE, + + /// Private part is the encrypted sensitive part of key + pub Private: TPM2B_PRIVATE, +} + +impl TssObject { + /// Creates a new instance with the specified values + pub fn new( + Public: &TPMT_PUBLIC, + Sensitive: &TPMT_SENSITIVE, + Private: &TPM2B_PRIVATE, + ) -> Self { + Self { + Public: Public.clone(), + Sensitive: Sensitive.clone(), + Private: Private.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TssObject { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + self.Public.toTpm(buf)?; + self.Sensitive.toTpm(buf)?; + self.Private.toTpm(buf)?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.Public.initFromTpm(buf)?; + self.Sensitive.initFromTpm(buf)?; + self.Private.initFromTpm(buf)?; + Ok(()) + } + +} + +impl TpmMarshaller for TssObject { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// Contains a PCR index and associated hash(pcr-value) [TSS] +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct PcrValue { + /// PCR Index + pub index: u32, + + /// PCR Value + pub value: TPMT_HA, +} + +impl PcrValue { + /// Creates a new instance with the specified values + pub fn new( + index: u32, + value: &TPMT_HA, + ) -> Self { + Self { + index: index.clone(), + value: value.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for PcrValue { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeInt(self.index as u32); + self.value.toTpm(buf)?; + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.index = buf.readInt() as u32; + self.value.initFromTpm(buf)?; + Ok(()) + } + +} + +impl TpmMarshaller for PcrValue { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// Structure representing a session block in a command buffer [TSS] +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct SessionIn { + /// Session handle + #[derivative(Default(value="TPM_HANDLE::default()"))] + pub handle: TPM_HANDLE, + + /// Caller nonce + pub nonceCaller: Vec, + + /// Session attributes + pub attributes: TPMA_SESSION, + + /// AuthValue (or HMAC) + pub auth: Vec, +} + +impl SessionIn { + /// Creates a new instance with the specified values + pub fn new( + handle: &TPM_HANDLE, + nonceCaller: &Vec, + attributes: TPMA_SESSION, + auth: &Vec, + ) -> Self { + Self { + handle: handle.clone(), + nonceCaller: nonceCaller.clone(), + attributes: attributes.clone(), + auth: auth.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for SessionIn { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + self.handle.toTpm(buf)?; + buf.writeSizedByteBuf(&self.nonceCaller, 2); + buf.writeByte(self.attributes.into()); + buf.writeSizedByteBuf(&self.auth, 2); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.handle.initFromTpm(buf)?; + self.nonceCaller = buf.readSizedByteBuf(2); + self.attributes = TPMA_SESSION(buf.readByte() as u8); + self.auth = buf.readSizedByteBuf(2); + Ok(()) + } + +} + +impl TpmMarshaller for SessionIn { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// Structure representing a session block in a response buffer [TSS] +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct SessionOut { + /// TPM nonce + pub nonceTpm: Vec, + + /// Session attributes + pub attributes: TPMA_SESSION, + + /// HMAC value + pub auth: Vec, +} + +impl SessionOut { + /// Creates a new instance with the specified values + pub fn new( + nonceTpm: &Vec, + attributes: TPMA_SESSION, + auth: &Vec, + ) -> Self { + Self { + nonceTpm: nonceTpm.clone(), + attributes: attributes.clone(), + auth: auth.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for SessionOut { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.nonceTpm, 2); + buf.writeByte(self.attributes.into()); + buf.writeSizedByteBuf(&self.auth, 2); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.nonceTpm = buf.readSizedByteBuf(2); + self.attributes = TPMA_SESSION(buf.readByte() as u8); + self.auth = buf.readSizedByteBuf(2); + Ok(()) + } + +} + +impl TpmMarshaller for SessionOut { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// Command header [TSS] +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct CommandHeader { + /// Command tag (sessions, or no sessions) + pub Tag: TPM_ST, + + /// Total command buffer length + pub CommandSize: u32, + + /// Command code + pub CommandCode: TPM_CC, +} + +impl CommandHeader { + /// Creates a new instance with the specified values + pub fn new( + Tag: TPM_ST, + CommandSize: u32, + CommandCode: TPM_CC, + ) -> Self { + Self { + Tag: Tag.clone(), + CommandSize: CommandSize.clone(), + CommandCode: CommandCode.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for CommandHeader { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeShort(self.Tag.into()); + buf.writeInt(self.CommandSize as u32); + buf.writeInt(self.CommandCode.into()); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.Tag = TPM_ST(buf.readShort() as u16); + self.CommandSize = buf.readInt() as u32; + self.CommandCode = TPM_CC(buf.readInt() as u32); + Ok(()) + } + +} + +impl TpmMarshaller for CommandHeader { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// Contains the public and private part of a TPM key +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TSS_KEY { + /// Public part of key + pub publicPart: TPMT_PUBLIC, + + /// Private part is the encrypted sensitive part of key + pub privatePart: Vec, +} + +impl TSS_KEY { + /// Creates a new instance with the specified values + pub fn new( + publicPart: &TPMT_PUBLIC, + privatePart: &Vec, + ) -> Self { + Self { + publicPart: publicPart.clone(), + privatePart: privatePart.clone(), + ..Default::default() + } + } + +} + +impl TpmStructure for TSS_KEY { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + self.publicPart.toTpm(buf)?; + buf.writeSizedByteBuf(&self.privatePart, 2); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.publicPart.initFromTpm(buf)?; + self.privatePart = buf.readSizedByteBuf(2); + Ok(()) + } + +} + +impl TpmMarshaller for TSS_KEY { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// Auto-derived from TPM2B_DIGEST to provide unique GetUnionSelector() implementation +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2B_DIGEST_SYMCIPHER { + /// The buffer area that can be no larger than a digest + pub buffer: Vec, +} + +impl TPM2B_DIGEST_SYMCIPHER { + fn GetUnionSelector() -> TPM_ALG_ID { + TPM_ALG_ID::SYMCIPHER + } +} + +impl TpmStructure for TPM2B_DIGEST_SYMCIPHER { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.buffer, 2); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.buffer = buf.readSizedByteBuf(2); + Ok(()) + } + +} + +impl TpmMarshaller for TPM2B_DIGEST_SYMCIPHER { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +/// Auto-derived from TPM2B_DIGEST +#[derive(Debug, Clone, Derivative)] +#[derivative(Default)] +pub struct TPM2B_DIGEST_KEYEDHASH { + /// The buffer area that can be no larger than a digest + pub buffer: Vec, +} + +impl TPM2B_DIGEST_KEYEDHASH { + fn GetUnionSelector() -> TPM_ALG_ID { + TPM_ALG_ID::KEYEDHASH + } +} + +impl TpmStructure for TPM2B_DIGEST_KEYEDHASH { + fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + buffer.createObj::()?; + Ok(()) + } + + fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> { + let mut tpm_buffer = TpmBuffer::from(buffer); + self.initFromTpm(&mut tpm_buffer) + } + + // Implement serialization/deserialization + fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Serialize fields + buf.writeSizedByteBuf(&self.buffer, 2); + Ok(()) + } + + fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> { + // Deserialize fields + self.buffer = buf.readSizedByteBuf(2); + Ok(()) + } + +} + +impl TpmMarshaller for TPM2B_DIGEST_KEYEDHASH { + /// Serialize this structure to a TPM buffer + fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.serialize(buffer) + } + + /// Deserialize this structure from a TPM buffer + fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> { + self.deserialize(buffer) + } + +} + +lazy_static::lazy_static! { + /// Maps enum type IDs to a map of values to string representations + pub static ref ENUM_TO_STR_MAP: HashMap> = { + let mut map = HashMap::new(); + let mut TPM_ALG_ID_map: HashMap = HashMap::new(); + TPM_ALG_ID_map.insert(0x0, "ERROR"); + TPM_ALG_ID_map.insert(0x1, "FIRST"); + TPM_ALG_ID_map.insert(0x1, "RSA"); + TPM_ALG_ID_map.insert(0x3, "TDES"); + TPM_ALG_ID_map.insert(0x4, "SHA"); + TPM_ALG_ID_map.insert(0x4, "SHA1"); + TPM_ALG_ID_map.insert(0x5, "HMAC"); + TPM_ALG_ID_map.insert(0x6, "AES"); + TPM_ALG_ID_map.insert(0x7, "MGF1"); + TPM_ALG_ID_map.insert(0x8, "KEYEDHASH"); + TPM_ALG_ID_map.insert(0xA, "XOR"); + TPM_ALG_ID_map.insert(0xB, "SHA256"); + TPM_ALG_ID_map.insert(0xC, "SHA384"); + TPM_ALG_ID_map.insert(0xD, "SHA512"); + TPM_ALG_ID_map.insert(0x10, "NULL"); + TPM_ALG_ID_map.insert(0x12, "SM3_256"); + TPM_ALG_ID_map.insert(0x13, "SM4"); + TPM_ALG_ID_map.insert(0x14, "RSASSA"); + TPM_ALG_ID_map.insert(0x15, "RSAES"); + TPM_ALG_ID_map.insert(0x16, "RSAPSS"); + TPM_ALG_ID_map.insert(0x17, "OAEP"); + TPM_ALG_ID_map.insert(0x18, "ECDSA"); + TPM_ALG_ID_map.insert(0x19, "ECDH"); + TPM_ALG_ID_map.insert(0x1A, "ECDAA"); + TPM_ALG_ID_map.insert(0x1B, "SM2"); + TPM_ALG_ID_map.insert(0x1C, "ECSCHNORR"); + TPM_ALG_ID_map.insert(0x1D, "ECMQV"); + TPM_ALG_ID_map.insert(0x20, "KDF1_SP800_56A"); + TPM_ALG_ID_map.insert(0x21, "KDF2"); + TPM_ALG_ID_map.insert(0x22, "KDF1_SP800_108"); + TPM_ALG_ID_map.insert(0x23, "ECC"); + TPM_ALG_ID_map.insert(0x25, "SYMCIPHER"); + TPM_ALG_ID_map.insert(0x26, "CAMELLIA"); + TPM_ALG_ID_map.insert(0x27, "SHA3_256"); + TPM_ALG_ID_map.insert(0x28, "SHA3_384"); + TPM_ALG_ID_map.insert(0x29, "SHA3_512"); + TPM_ALG_ID_map.insert(0x3F, "CMAC"); + TPM_ALG_ID_map.insert(0x40, "CTR"); + TPM_ALG_ID_map.insert(0x41, "OFB"); + TPM_ALG_ID_map.insert(0x42, "CBC"); + TPM_ALG_ID_map.insert(0x43, "CFB"); + TPM_ALG_ID_map.insert(0x44, "ECB"); + TPM_ALG_ID_map.insert(0x44, "LAST"); + TPM_ALG_ID_map.insert(0x7FFF, "ANY"); + TPM_ALG_ID_map.insert(0x7FFE, "ANY2"); + map.insert(std::any::TypeId::of::(), TPM_ALG_ID_map); + + let mut TPM_ECC_CURVE_map: HashMap = HashMap::new(); + TPM_ECC_CURVE_map.insert(0x0, "NONE"); + TPM_ECC_CURVE_map.insert(0x1, "NIST_P192"); + TPM_ECC_CURVE_map.insert(0x2, "NIST_P224"); + TPM_ECC_CURVE_map.insert(0x3, "NIST_P256"); + TPM_ECC_CURVE_map.insert(0x4, "NIST_P384"); + TPM_ECC_CURVE_map.insert(0x5, "NIST_P521"); + TPM_ECC_CURVE_map.insert(0x10, "BN_P256"); + TPM_ECC_CURVE_map.insert(0x11, "BN_P638"); + TPM_ECC_CURVE_map.insert(0x20, "SM2_P256"); + TPM_ECC_CURVE_map.insert(0x21, "TEST_P192"); + map.insert(std::any::TypeId::of::(), TPM_ECC_CURVE_map); + + let mut SHA1_map: HashMap = HashMap::new(); + SHA1_map.insert(0x14, "DIGEST_SIZE"); + SHA1_map.insert(0x40, "BLOCK_SIZE"); + map.insert(std::any::TypeId::of::(), SHA1_map); + + let mut SHA256_map: HashMap = HashMap::new(); + SHA256_map.insert(0x20, "DIGEST_SIZE"); + SHA256_map.insert(0x40, "BLOCK_SIZE"); + map.insert(std::any::TypeId::of::(), SHA256_map); + + let mut SHA384_map: HashMap = HashMap::new(); + SHA384_map.insert(0x30, "DIGEST_SIZE"); + SHA384_map.insert(0x80, "BLOCK_SIZE"); + map.insert(std::any::TypeId::of::(), SHA384_map); + + let mut SHA512_map: HashMap = HashMap::new(); + SHA512_map.insert(0x40, "DIGEST_SIZE"); + SHA512_map.insert(0x80, "BLOCK_SIZE"); + map.insert(std::any::TypeId::of::(), SHA512_map); + + let mut SM3_256_map: HashMap = HashMap::new(); + SM3_256_map.insert(0x20, "DIGEST_SIZE"); + SM3_256_map.insert(0x40, "BLOCK_SIZE"); + map.insert(std::any::TypeId::of::(), SM3_256_map); + + let mut SHA3_256_map: HashMap = HashMap::new(); + SHA3_256_map.insert(0x20, "DIGEST_SIZE"); + SHA3_256_map.insert(0x88, "BLOCK_SIZE"); + map.insert(std::any::TypeId::of::(), SHA3_256_map); + + let mut SHA3_384_map: HashMap = HashMap::new(); + SHA3_384_map.insert(0x30, "DIGEST_SIZE"); + SHA3_384_map.insert(0x68, "BLOCK_SIZE"); + map.insert(std::any::TypeId::of::(), SHA3_384_map); + + let mut SHA3_512_map: HashMap = HashMap::new(); + SHA3_512_map.insert(0x40, "DIGEST_SIZE"); + SHA3_512_map.insert(0x48, "BLOCK_SIZE"); + map.insert(std::any::TypeId::of::(), SHA3_512_map); + + let mut Logic_map: HashMap = HashMap::new(); + Logic_map.insert(0x1, "TRUE"); + Logic_map.insert(0x0, "FALSE"); + Logic_map.insert(0x1, "YES"); + Logic_map.insert(0x0, "NO"); + Logic_map.insert(0x1, "SET"); + Logic_map.insert(0x0, "CLEAR"); + map.insert(std::any::TypeId::of::(), Logic_map); + + let mut TPM_SPEC_map: HashMap = HashMap::new(); + TPM_SPEC_map.insert(0x322E3000, "FAMILY"); + TPM_SPEC_map.insert(0x0, "LEVEL"); + TPM_SPEC_map.insert(0xA2, "VERSION"); + TPM_SPEC_map.insert(0x7E3, "YEAR"); + TPM_SPEC_map.insert(0x168, "DAY_OF_YEAR"); + map.insert(std::any::TypeId::of::(), TPM_SPEC_map); + + let mut TPM_GENERATED_map: HashMap = HashMap::new(); + TPM_GENERATED_map.insert(0xFF544347, "VALUE"); + map.insert(std::any::TypeId::of::(), TPM_GENERATED_map); + + let mut TPM_CC_map: HashMap = HashMap::new(); + TPM_CC_map.insert(0x11F, "FIRST"); + TPM_CC_map.insert(0x11F, "NV_UndefineSpaceSpecial"); + TPM_CC_map.insert(0x120, "EvictControl"); + TPM_CC_map.insert(0x121, "HierarchyControl"); + TPM_CC_map.insert(0x122, "NV_UndefineSpace"); + TPM_CC_map.insert(0x124, "ChangeEPS"); + TPM_CC_map.insert(0x125, "ChangePPS"); + TPM_CC_map.insert(0x126, "Clear"); + TPM_CC_map.insert(0x127, "ClearControl"); + TPM_CC_map.insert(0x128, "ClockSet"); + TPM_CC_map.insert(0x129, "HierarchyChangeAuth"); + TPM_CC_map.insert(0x12A, "NV_DefineSpace"); + TPM_CC_map.insert(0x12B, "PCR_Allocate"); + TPM_CC_map.insert(0x12C, "PCR_SetAuthPolicy"); + TPM_CC_map.insert(0x12D, "PP_Commands"); + TPM_CC_map.insert(0x12E, "SetPrimaryPolicy"); + TPM_CC_map.insert(0x12F, "FieldUpgradeStart"); + TPM_CC_map.insert(0x130, "ClockRateAdjust"); + TPM_CC_map.insert(0x131, "CreatePrimary"); + TPM_CC_map.insert(0x132, "NV_GlobalWriteLock"); + TPM_CC_map.insert(0x133, "GetCommandAuditDigest"); + TPM_CC_map.insert(0x134, "NV_Increment"); + TPM_CC_map.insert(0x135, "NV_SetBits"); + TPM_CC_map.insert(0x136, "NV_Extend"); + TPM_CC_map.insert(0x137, "NV_Write"); + TPM_CC_map.insert(0x138, "NV_WriteLock"); + TPM_CC_map.insert(0x139, "DictionaryAttackLockReset"); + TPM_CC_map.insert(0x13A, "DictionaryAttackParameters"); + TPM_CC_map.insert(0x13B, "NV_ChangeAuth"); + TPM_CC_map.insert(0x13C, "PCR_Event"); + TPM_CC_map.insert(0x13D, "PCR_Reset"); + TPM_CC_map.insert(0x13E, "SequenceComplete"); + TPM_CC_map.insert(0x13F, "SetAlgorithmSet"); + TPM_CC_map.insert(0x140, "SetCommandCodeAuditStatus"); + TPM_CC_map.insert(0x141, "FieldUpgradeData"); + TPM_CC_map.insert(0x142, "IncrementalSelfTest"); + TPM_CC_map.insert(0x143, "SelfTest"); + TPM_CC_map.insert(0x144, "Startup"); + TPM_CC_map.insert(0x145, "Shutdown"); + TPM_CC_map.insert(0x146, "StirRandom"); + TPM_CC_map.insert(0x147, "ActivateCredential"); + TPM_CC_map.insert(0x148, "Certify"); + TPM_CC_map.insert(0x149, "PolicyNV"); + TPM_CC_map.insert(0x14A, "CertifyCreation"); + TPM_CC_map.insert(0x14B, "Duplicate"); + TPM_CC_map.insert(0x14C, "GetTime"); + TPM_CC_map.insert(0x14D, "GetSessionAuditDigest"); + TPM_CC_map.insert(0x14E, "NV_Read"); + TPM_CC_map.insert(0x14F, "NV_ReadLock"); + TPM_CC_map.insert(0x150, "ObjectChangeAuth"); + TPM_CC_map.insert(0x151, "PolicySecret"); + TPM_CC_map.insert(0x152, "Rewrap"); + TPM_CC_map.insert(0x153, "Create"); + TPM_CC_map.insert(0x154, "ECDH_ZGen"); + TPM_CC_map.insert(0x155, "HMAC"); + TPM_CC_map.insert(0x155, "MAC"); + TPM_CC_map.insert(0x156, "Import"); + TPM_CC_map.insert(0x157, "Load"); + TPM_CC_map.insert(0x158, "Quote"); + TPM_CC_map.insert(0x159, "RSA_Decrypt"); + TPM_CC_map.insert(0x15B, "HMAC_Start"); + TPM_CC_map.insert(0x15B, "MAC_Start"); + TPM_CC_map.insert(0x15C, "SequenceUpdate"); + TPM_CC_map.insert(0x15D, "Sign"); + TPM_CC_map.insert(0x15E, "Unseal"); + TPM_CC_map.insert(0x160, "PolicySigned"); + TPM_CC_map.insert(0x161, "ContextLoad"); + TPM_CC_map.insert(0x162, "ContextSave"); + TPM_CC_map.insert(0x163, "ECDH_KeyGen"); + TPM_CC_map.insert(0x164, "EncryptDecrypt"); + TPM_CC_map.insert(0x165, "FlushContext"); + TPM_CC_map.insert(0x167, "LoadExternal"); + TPM_CC_map.insert(0x168, "MakeCredential"); + TPM_CC_map.insert(0x169, "NV_ReadPublic"); + TPM_CC_map.insert(0x16A, "PolicyAuthorize"); + TPM_CC_map.insert(0x16B, "PolicyAuthValue"); + TPM_CC_map.insert(0x16C, "PolicyCommandCode"); + TPM_CC_map.insert(0x16D, "PolicyCounterTimer"); + TPM_CC_map.insert(0x16E, "PolicyCpHash"); + TPM_CC_map.insert(0x16F, "PolicyLocality"); + TPM_CC_map.insert(0x170, "PolicyNameHash"); + TPM_CC_map.insert(0x171, "PolicyOR"); + TPM_CC_map.insert(0x172, "PolicyTicket"); + TPM_CC_map.insert(0x173, "ReadPublic"); + TPM_CC_map.insert(0x174, "RSA_Encrypt"); + TPM_CC_map.insert(0x176, "StartAuthSession"); + TPM_CC_map.insert(0x177, "VerifySignature"); + TPM_CC_map.insert(0x178, "ECC_Parameters"); + TPM_CC_map.insert(0x179, "FirmwareRead"); + TPM_CC_map.insert(0x17A, "GetCapability"); + TPM_CC_map.insert(0x17B, "GetRandom"); + TPM_CC_map.insert(0x17C, "GetTestResult"); + TPM_CC_map.insert(0x17D, "Hash"); + TPM_CC_map.insert(0x17E, "PCR_Read"); + TPM_CC_map.insert(0x17F, "PolicyPCR"); + TPM_CC_map.insert(0x180, "PolicyRestart"); + TPM_CC_map.insert(0x181, "ReadClock"); + TPM_CC_map.insert(0x182, "PCR_Extend"); + TPM_CC_map.insert(0x183, "PCR_SetAuthValue"); + TPM_CC_map.insert(0x184, "NV_Certify"); + TPM_CC_map.insert(0x185, "EventSequenceComplete"); + TPM_CC_map.insert(0x186, "HashSequenceStart"); + TPM_CC_map.insert(0x187, "PolicyPhysicalPresence"); + TPM_CC_map.insert(0x188, "PolicyDuplicationSelect"); + TPM_CC_map.insert(0x189, "PolicyGetDigest"); + TPM_CC_map.insert(0x18A, "TestParms"); + TPM_CC_map.insert(0x18B, "Commit"); + TPM_CC_map.insert(0x18C, "PolicyPassword"); + TPM_CC_map.insert(0x18D, "ZGen_2Phase"); + TPM_CC_map.insert(0x18E, "EC_Ephemeral"); + TPM_CC_map.insert(0x18F, "PolicyNvWritten"); + TPM_CC_map.insert(0x190, "PolicyTemplate"); + TPM_CC_map.insert(0x191, "CreateLoaded"); + TPM_CC_map.insert(0x192, "PolicyAuthorizeNV"); + TPM_CC_map.insert(0x193, "EncryptDecrypt2"); + TPM_CC_map.insert(0x194, "AC_GetCapability"); + TPM_CC_map.insert(0x195, "AC_Send"); + TPM_CC_map.insert(0x196, "Policy_AC_SendSelect"); + TPM_CC_map.insert(0x197, "CertifyX509"); + TPM_CC_map.insert(0x198, "ACT_SetTimeout"); + TPM_CC_map.insert(0x199, "ECC_Encrypt"); + TPM_CC_map.insert(0x19A, "ECC_Decrypt"); + TPM_CC_map.insert(0x19A, "LAST"); + TPM_CC_map.insert(0x20000000, "CC_VEND"); + TPM_CC_map.insert(0x20000000, "Vendor_TCG_Test"); + map.insert(std::any::TypeId::of::(), TPM_CC_map); + + let mut ImplementationConstants_map: HashMap = HashMap::new(); + ImplementationConstants_map.insert(0x1, "Ossl"); + ImplementationConstants_map.insert(0x2, "Ltc"); + ImplementationConstants_map.insert(0x3, "Msbn"); + ImplementationConstants_map.insert(0x4, "Symcrypt"); + ImplementationConstants_map.insert(0x3, "HASH_COUNT"); + ImplementationConstants_map.insert(0x100, "MAX_SYM_KEY_BITS"); + ImplementationConstants_map.insert(0x20, "MAX_SYM_KEY_BYTES"); + ImplementationConstants_map.insert(0x10, "MAX_SYM_BLOCK_SIZE"); + ImplementationConstants_map.insert(0x19A, "MAX_CAP_CC"); + ImplementationConstants_map.insert(0x100, "MAX_RSA_KEY_BYTES"); + ImplementationConstants_map.insert(0x20, "MAX_AES_KEY_BYTES"); + ImplementationConstants_map.insert(0x30, "MAX_ECC_KEY_BYTES"); + ImplementationConstants_map.insert(0x20, "LABEL_MAX_BUFFER"); + ImplementationConstants_map.insert(0x4, "_TPM_CAP_SIZE"); + ImplementationConstants_map.insert(0x3F8, "MAX_CAP_DATA"); + ImplementationConstants_map.insert(0xA9, "MAX_CAP_ALGS"); + ImplementationConstants_map.insert(0xFE, "MAX_CAP_HANDLES"); + ImplementationConstants_map.insert(0x7F, "MAX_TPM_PROPERTIES"); + ImplementationConstants_map.insert(0xCB, "MAX_PCR_PROPERTIES"); + ImplementationConstants_map.insert(0x1FC, "MAX_ECC_CURVES"); + ImplementationConstants_map.insert(0xE, "MAX_TAGGED_POLICIES"); + ImplementationConstants_map.insert(0x7F, "MAX_AC_CAPABILITIES"); + ImplementationConstants_map.insert(0x54, "MAX_ACT_DATA"); + map.insert(std::any::TypeId::of::(), ImplementationConstants_map); + + let mut TPM_RC_map: HashMap = HashMap::new(); + TPM_RC_map.insert(0x0, "SUCCESS"); + TPM_RC_map.insert(0x1E, "BAD_TAG"); + TPM_RC_map.insert(0x100, "RC_VER1"); + TPM_RC_map.insert(0x100, "INITIALIZE"); + TPM_RC_map.insert(0x101, "FAILURE"); + TPM_RC_map.insert(0x103, "SEQUENCE"); + TPM_RC_map.insert(0x10B, "PRIVATE"); + TPM_RC_map.insert(0x119, "HMAC"); + TPM_RC_map.insert(0x120, "DISABLED"); + TPM_RC_map.insert(0x121, "EXCLUSIVE"); + TPM_RC_map.insert(0x124, "AUTH_TYPE"); + TPM_RC_map.insert(0x125, "AUTH_MISSING"); + TPM_RC_map.insert(0x126, "POLICY"); + TPM_RC_map.insert(0x127, "PCR"); + TPM_RC_map.insert(0x128, "PCR_CHANGED"); + TPM_RC_map.insert(0x12D, "UPGRADE"); + TPM_RC_map.insert(0x12E, "TOO_MANY_CONTEXTS"); + TPM_RC_map.insert(0x12F, "AUTH_UNAVAILABLE"); + TPM_RC_map.insert(0x130, "REBOOT"); + TPM_RC_map.insert(0x131, "UNBALANCED"); + TPM_RC_map.insert(0x142, "COMMAND_SIZE"); + TPM_RC_map.insert(0x143, "COMMAND_CODE"); + TPM_RC_map.insert(0x144, "AUTHSIZE"); + TPM_RC_map.insert(0x145, "AUTH_CONTEXT"); + TPM_RC_map.insert(0x146, "NV_RANGE"); + TPM_RC_map.insert(0x147, "NV_SIZE"); + TPM_RC_map.insert(0x148, "NV_LOCKED"); + TPM_RC_map.insert(0x149, "NV_AUTHORIZATION"); + TPM_RC_map.insert(0x14A, "NV_UNINITIALIZED"); + TPM_RC_map.insert(0x14B, "NV_SPACE"); + TPM_RC_map.insert(0x14C, "NV_DEFINED"); + TPM_RC_map.insert(0x150, "BAD_CONTEXT"); + TPM_RC_map.insert(0x151, "CPHASH"); + TPM_RC_map.insert(0x152, "PARENT"); + TPM_RC_map.insert(0x153, "NEEDS_TEST"); + TPM_RC_map.insert(0x154, "NO_RESULT"); + TPM_RC_map.insert(0x155, "SENSITIVE"); + TPM_RC_map.insert(0x17F, "RC_MAX_FM0"); + TPM_RC_map.insert(0x80, "RC_FMT1"); + TPM_RC_map.insert(0x81, "ASYMMETRIC"); + TPM_RC_map.insert(0x82, "ATTRIBUTES"); + TPM_RC_map.insert(0x83, "HASH"); + TPM_RC_map.insert(0x84, "VALUE"); + TPM_RC_map.insert(0x85, "HIERARCHY"); + TPM_RC_map.insert(0x87, "KEY_SIZE"); + TPM_RC_map.insert(0x88, "MGF"); + TPM_RC_map.insert(0x89, "MODE"); + TPM_RC_map.insert(0x8A, "TYPE"); + TPM_RC_map.insert(0x8B, "HANDLE"); + TPM_RC_map.insert(0x8C, "KDF"); + TPM_RC_map.insert(0x8D, "RANGE"); + TPM_RC_map.insert(0x8E, "AUTH_FAIL"); + TPM_RC_map.insert(0x8F, "NONCE"); + TPM_RC_map.insert(0x90, "PP"); + TPM_RC_map.insert(0x92, "SCHEME"); + TPM_RC_map.insert(0x95, "SIZE"); + TPM_RC_map.insert(0x96, "SYMMETRIC"); + TPM_RC_map.insert(0x97, "TAG"); + TPM_RC_map.insert(0x98, "SELECTOR"); + TPM_RC_map.insert(0x9A, "INSUFFICIENT"); + TPM_RC_map.insert(0x9B, "SIGNATURE"); + TPM_RC_map.insert(0x9C, "KEY"); + TPM_RC_map.insert(0x9D, "POLICY_FAIL"); + TPM_RC_map.insert(0x9F, "INTEGRITY"); + TPM_RC_map.insert(0xA0, "TICKET"); + TPM_RC_map.insert(0xA1, "RESERVED_BITS"); + TPM_RC_map.insert(0xA2, "BAD_AUTH"); + TPM_RC_map.insert(0xA3, "EXPIRED"); + TPM_RC_map.insert(0xA4, "POLICY_CC"); + TPM_RC_map.insert(0xA5, "BINDING"); + TPM_RC_map.insert(0xA6, "CURVE"); + TPM_RC_map.insert(0xA7, "ECC_POINT"); + TPM_RC_map.insert(0x900, "RC_WARN"); + TPM_RC_map.insert(0x901, "CONTEXT_GAP"); + TPM_RC_map.insert(0x902, "OBJECT_MEMORY"); + TPM_RC_map.insert(0x903, "SESSION_MEMORY"); + TPM_RC_map.insert(0x904, "MEMORY"); + TPM_RC_map.insert(0x905, "SESSION_HANDLES"); + TPM_RC_map.insert(0x906, "OBJECT_HANDLES"); + TPM_RC_map.insert(0x907, "LOCALITY"); + TPM_RC_map.insert(0x908, "YIELDED"); + TPM_RC_map.insert(0x909, "CANCELED"); + TPM_RC_map.insert(0x90A, "TESTING"); + TPM_RC_map.insert(0x910, "REFERENCE_H0"); + TPM_RC_map.insert(0x911, "REFERENCE_H1"); + TPM_RC_map.insert(0x912, "REFERENCE_H2"); + TPM_RC_map.insert(0x913, "REFERENCE_H3"); + TPM_RC_map.insert(0x914, "REFERENCE_H4"); + TPM_RC_map.insert(0x915, "REFERENCE_H5"); + TPM_RC_map.insert(0x916, "REFERENCE_H6"); + TPM_RC_map.insert(0x918, "REFERENCE_S0"); + TPM_RC_map.insert(0x919, "REFERENCE_S1"); + TPM_RC_map.insert(0x91A, "REFERENCE_S2"); + TPM_RC_map.insert(0x91B, "REFERENCE_S3"); + TPM_RC_map.insert(0x91C, "REFERENCE_S4"); + TPM_RC_map.insert(0x91D, "REFERENCE_S5"); + TPM_RC_map.insert(0x91E, "REFERENCE_S6"); + TPM_RC_map.insert(0x920, "NV_RATE"); + TPM_RC_map.insert(0x921, "LOCKOUT"); + TPM_RC_map.insert(0x922, "RETRY"); + TPM_RC_map.insert(0x923, "NV_UNAVAILABLE"); + TPM_RC_map.insert(0x97F, "NOT_USED"); + TPM_RC_map.insert(0x0, "H"); + TPM_RC_map.insert(0x40, "P"); + TPM_RC_map.insert(0x800, "S"); + TPM_RC_map.insert(0x100, "_1"); + TPM_RC_map.insert(0x200, "_2"); + TPM_RC_map.insert(0x300, "_3"); + TPM_RC_map.insert(0x400, "_4"); + TPM_RC_map.insert(0x500, "_5"); + TPM_RC_map.insert(0x600, "_6"); + TPM_RC_map.insert(0x700, "_7"); + TPM_RC_map.insert(0x800, "_8"); + TPM_RC_map.insert(0x900, "_9"); + TPM_RC_map.insert(0xA00, "A"); + TPM_RC_map.insert(0xB00, "B"); + TPM_RC_map.insert(0xC00, "C"); + TPM_RC_map.insert(0xD00, "D"); + TPM_RC_map.insert(0xE00, "E"); + TPM_RC_map.insert(0xF00, "F"); + TPM_RC_map.insert(0xF00, "N_MASK"); + TPM_RC_map.insert(0x40280001, "TSS_TCP_BAD_HANDSHAKE_RESP"); + TPM_RC_map.insert(0x40280002, "TSS_TCP_SERVER_TOO_OLD"); + TPM_RC_map.insert(0x40280003, "TSS_TCP_BAD_ACK"); + TPM_RC_map.insert(0x40280004, "TSS_TCP_BAD_RESP_LEN"); + TPM_RC_map.insert(0x40280005, "TSS_TCP_UNEXPECTED_STARTUP_RESP"); + TPM_RC_map.insert(0x40280006, "TSS_TCP_INVALID_SIZE_TAG"); + TPM_RC_map.insert(0x40280007, "TSS_TCP_DISCONNECTED"); + TPM_RC_map.insert(0x40280010, "TSS_DISPATCH_FAILED"); + TPM_RC_map.insert(0x40280011, "TSS_SEND_OP_FAILED"); + TPM_RC_map.insert(0x40280021, "TSS_RESP_BUF_TOO_SHORT"); + TPM_RC_map.insert(0x40280022, "TSS_RESP_BUF_INVALID_SESSION_TAG"); + TPM_RC_map.insert(0x40280023, "TSS_RESP_BUF_INVALID_SIZE"); + TPM_RC_map.insert(0x80280400, "TBS_COMMAND_BLOCKED"); + TPM_RC_map.insert(0x80280401, "TBS_INVALID_HANDLE"); + TPM_RC_map.insert(0x80280402, "TBS_DUPLICATE_V_HANDLE"); + TPM_RC_map.insert(0x80280403, "TBS_EMBEDDED_COMMAND_BLOCKED"); + TPM_RC_map.insert(0x80280404, "TBS_EMBEDDED_COMMAND_UNSUPPORTED"); + TPM_RC_map.insert(0x80284000, "TBS_UNKNOWN_ERROR"); + TPM_RC_map.insert(0x80284001, "TBS_INTERNAL_ERROR"); + TPM_RC_map.insert(0x80284002, "TBS_BAD_PARAMETER"); + TPM_RC_map.insert(0x80284003, "TBS_INVALID_OUTPUT_POINTER"); + TPM_RC_map.insert(0x80284004, "TBS_INVALID_CONTEXT"); + TPM_RC_map.insert(0x80284005, "TBS_INSUFFICIENT_BUFFER"); + TPM_RC_map.insert(0x80284006, "TBS_IO_ERROR"); + TPM_RC_map.insert(0x80284007, "TBS_INVALID_CONTEXT_PARAM"); + TPM_RC_map.insert(0x80284008, "TBS_SERVICE_NOT_RUNNING"); + TPM_RC_map.insert(0x80284009, "TBS_TOO_MANY_CONTEXTS"); + TPM_RC_map.insert(0x8028400A, "TBS_TOO_MANY_RESOURCES"); + TPM_RC_map.insert(0x8028400B, "TBS_SERVICE_START_PENDING"); + TPM_RC_map.insert(0x8028400C, "TBS_PPI_NOT_SUPPORTED"); + TPM_RC_map.insert(0x8028400D, "TBS_COMMAND_CANCELED"); + TPM_RC_map.insert(0x8028400E, "TBS_BUFFER_TOO_LARGE"); + TPM_RC_map.insert(0x8028400F, "TBS_TPM_NOT_FOUND"); + TPM_RC_map.insert(0x80284010, "TBS_SERVICE_DISABLED"); + TPM_RC_map.insert(0x80284012, "TBS_ACCESS_DENIED"); + TPM_RC_map.insert(0x80284014, "TBS_PPI_FUNCTION_NOT_SUPPORTED"); + TPM_RC_map.insert(0x80284015, "TBS_OWNER_AUTH_NOT_FOUND"); + map.insert(std::any::TypeId::of::(), TPM_RC_map); + + let mut TPM_CLOCK_ADJUST_map: HashMap = HashMap::new(); + TPM_CLOCK_ADJUST_map.insert(0xFFFFFFFD, "COARSE_SLOWER"); + TPM_CLOCK_ADJUST_map.insert(0xFFFFFFFE, "MEDIUM_SLOWER"); + TPM_CLOCK_ADJUST_map.insert(0xFFFFFFFF, "FINE_SLOWER"); + TPM_CLOCK_ADJUST_map.insert(0x0, "NO_CHANGE"); + TPM_CLOCK_ADJUST_map.insert(0x1, "FINE_FASTER"); + TPM_CLOCK_ADJUST_map.insert(0x2, "MEDIUM_FASTER"); + TPM_CLOCK_ADJUST_map.insert(0x3, "COARSE_FASTER"); + map.insert(std::any::TypeId::of::(), TPM_CLOCK_ADJUST_map); + + let mut TPM_EO_map: HashMap = HashMap::new(); + TPM_EO_map.insert(0x0, "EQ"); + TPM_EO_map.insert(0x1, "NEQ"); + TPM_EO_map.insert(0x2, "SIGNED_GT"); + TPM_EO_map.insert(0x3, "UNSIGNED_GT"); + TPM_EO_map.insert(0x4, "SIGNED_LT"); + TPM_EO_map.insert(0x5, "UNSIGNED_LT"); + TPM_EO_map.insert(0x6, "SIGNED_GE"); + TPM_EO_map.insert(0x7, "UNSIGNED_GE"); + TPM_EO_map.insert(0x8, "SIGNED_LE"); + TPM_EO_map.insert(0x9, "UNSIGNED_LE"); + TPM_EO_map.insert(0xA, "BITSET"); + TPM_EO_map.insert(0xB, "BITCLEAR"); + map.insert(std::any::TypeId::of::(), TPM_EO_map); + + let mut TPM_ST_map: HashMap = HashMap::new(); + TPM_ST_map.insert(0xC4, "RSP_COMMAND"); + TPM_ST_map.insert(0x8000, "NULL"); + TPM_ST_map.insert(0x8001, "NO_SESSIONS"); + TPM_ST_map.insert(0x8002, "SESSIONS"); + TPM_ST_map.insert(0x8014, "ATTEST_NV"); + TPM_ST_map.insert(0x8015, "ATTEST_COMMAND_AUDIT"); + TPM_ST_map.insert(0x8016, "ATTEST_SESSION_AUDIT"); + TPM_ST_map.insert(0x8017, "ATTEST_CERTIFY"); + TPM_ST_map.insert(0x8018, "ATTEST_QUOTE"); + TPM_ST_map.insert(0x8019, "ATTEST_TIME"); + TPM_ST_map.insert(0x801A, "ATTEST_CREATION"); + TPM_ST_map.insert(0x801C, "ATTEST_NV_DIGEST"); + TPM_ST_map.insert(0x8021, "CREATION"); + TPM_ST_map.insert(0x8022, "VERIFIED"); + TPM_ST_map.insert(0x8023, "AUTH_SECRET"); + TPM_ST_map.insert(0x8024, "HASHCHECK"); + TPM_ST_map.insert(0x8025, "AUTH_SIGNED"); + TPM_ST_map.insert(0x8029, "FU_MANIFEST"); + map.insert(std::any::TypeId::of::(), TPM_ST_map); + + let mut TPM_SU_map: HashMap = HashMap::new(); + TPM_SU_map.insert(0x0, "CLEAR"); + TPM_SU_map.insert(0x1, "STATE"); + map.insert(std::any::TypeId::of::(), TPM_SU_map); + + let mut TPM_SE_map: HashMap = HashMap::new(); + TPM_SE_map.insert(0x0, "HMAC"); + TPM_SE_map.insert(0x1, "POLICY"); + TPM_SE_map.insert(0x3, "TRIAL"); + map.insert(std::any::TypeId::of::(), TPM_SE_map); + + let mut TPM_CAP_map: HashMap = HashMap::new(); + TPM_CAP_map.insert(0x0, "FIRST"); + TPM_CAP_map.insert(0x0, "ALGS"); + TPM_CAP_map.insert(0x1, "HANDLES"); + TPM_CAP_map.insert(0x2, "COMMANDS"); + TPM_CAP_map.insert(0x3, "PP_COMMANDS"); + TPM_CAP_map.insert(0x4, "AUDIT_COMMANDS"); + TPM_CAP_map.insert(0x5, "PCRS"); + TPM_CAP_map.insert(0x6, "TPM_PROPERTIES"); + TPM_CAP_map.insert(0x7, "PCR_PROPERTIES"); + TPM_CAP_map.insert(0x8, "ECC_CURVES"); + TPM_CAP_map.insert(0x9, "AUTH_POLICIES"); + TPM_CAP_map.insert(0xA, "ACT"); + TPM_CAP_map.insert(0xA, "LAST"); + TPM_CAP_map.insert(0x100, "VENDOR_PROPERTY"); + map.insert(std::any::TypeId::of::(), TPM_CAP_map); + + let mut TPM_PT_map: HashMap = HashMap::new(); + TPM_PT_map.insert(0x0, "NONE"); + TPM_PT_map.insert(0x100, "PT_GROUP"); + TPM_PT_map.insert(0x100, "PT_FIXED"); + TPM_PT_map.insert(0x100, "FAMILY_INDICATOR"); + TPM_PT_map.insert(0x101, "LEVEL"); + TPM_PT_map.insert(0x102, "REVISION"); + TPM_PT_map.insert(0x103, "DAY_OF_YEAR"); + TPM_PT_map.insert(0x104, "YEAR"); + TPM_PT_map.insert(0x105, "MANUFACTURER"); + TPM_PT_map.insert(0x106, "VENDOR_STRING_1"); + TPM_PT_map.insert(0x107, "VENDOR_STRING_2"); + TPM_PT_map.insert(0x108, "VENDOR_STRING_3"); + TPM_PT_map.insert(0x109, "VENDOR_STRING_4"); + TPM_PT_map.insert(0x10A, "VENDOR_TPM_TYPE"); + TPM_PT_map.insert(0x10B, "FIRMWARE_VERSION_1"); + TPM_PT_map.insert(0x10C, "FIRMWARE_VERSION_2"); + TPM_PT_map.insert(0x10D, "INPUT_BUFFER"); + TPM_PT_map.insert(0x10E, "HR_TRANSIENT_MIN"); + TPM_PT_map.insert(0x10F, "HR_PERSISTENT_MIN"); + TPM_PT_map.insert(0x110, "HR_LOADED_MIN"); + TPM_PT_map.insert(0x111, "ACTIVE_SESSIONS_MAX"); + TPM_PT_map.insert(0x112, "PCR_COUNT"); + TPM_PT_map.insert(0x113, "PCR_SELECT_MIN"); + TPM_PT_map.insert(0x114, "CONTEXT_GAP_MAX"); + TPM_PT_map.insert(0x116, "NV_COUNTERS_MAX"); + TPM_PT_map.insert(0x117, "NV_INDEX_MAX"); + TPM_PT_map.insert(0x118, "MEMORY"); + TPM_PT_map.insert(0x119, "CLOCK_UPDATE"); + TPM_PT_map.insert(0x11A, "CONTEXT_HASH"); + TPM_PT_map.insert(0x11B, "CONTEXT_SYM"); + TPM_PT_map.insert(0x11C, "CONTEXT_SYM_SIZE"); + TPM_PT_map.insert(0x11D, "ORDERLY_COUNT"); + TPM_PT_map.insert(0x11E, "MAX_COMMAND_SIZE"); + TPM_PT_map.insert(0x11F, "MAX_RESPONSE_SIZE"); + TPM_PT_map.insert(0x120, "MAX_DIGEST"); + TPM_PT_map.insert(0x121, "MAX_OBJECT_CONTEXT"); + TPM_PT_map.insert(0x122, "MAX_SESSION_CONTEXT"); + TPM_PT_map.insert(0x123, "PS_FAMILY_INDICATOR"); + TPM_PT_map.insert(0x124, "PS_LEVEL"); + TPM_PT_map.insert(0x125, "PS_REVISION"); + TPM_PT_map.insert(0x126, "PS_DAY_OF_YEAR"); + TPM_PT_map.insert(0x127, "PS_YEAR"); + TPM_PT_map.insert(0x128, "SPLIT_MAX"); + TPM_PT_map.insert(0x129, "TOTAL_COMMANDS"); + TPM_PT_map.insert(0x12A, "LIBRARY_COMMANDS"); + TPM_PT_map.insert(0x12B, "VENDOR_COMMANDS"); + TPM_PT_map.insert(0x12C, "NV_BUFFER_MAX"); + TPM_PT_map.insert(0x12D, "MODES"); + TPM_PT_map.insert(0x12E, "MAX_CAP_BUFFER"); + TPM_PT_map.insert(0x200, "PT_VAR"); + TPM_PT_map.insert(0x200, "PERMANENT"); + TPM_PT_map.insert(0x201, "STARTUP_CLEAR"); + TPM_PT_map.insert(0x202, "HR_NV_INDEX"); + TPM_PT_map.insert(0x203, "HR_LOADED"); + TPM_PT_map.insert(0x204, "HR_LOADED_AVAIL"); + TPM_PT_map.insert(0x205, "HR_ACTIVE"); + TPM_PT_map.insert(0x206, "HR_ACTIVE_AVAIL"); + TPM_PT_map.insert(0x207, "HR_TRANSIENT_AVAIL"); + TPM_PT_map.insert(0x208, "HR_PERSISTENT"); + TPM_PT_map.insert(0x209, "HR_PERSISTENT_AVAIL"); + TPM_PT_map.insert(0x20A, "NV_COUNTERS"); + TPM_PT_map.insert(0x20B, "NV_COUNTERS_AVAIL"); + TPM_PT_map.insert(0x20C, "ALGORITHM_SET"); + TPM_PT_map.insert(0x20D, "LOADED_CURVES"); + TPM_PT_map.insert(0x20E, "LOCKOUT_COUNTER"); + TPM_PT_map.insert(0x20F, "MAX_AUTH_FAIL"); + TPM_PT_map.insert(0x210, "LOCKOUT_INTERVAL"); + TPM_PT_map.insert(0x211, "LOCKOUT_RECOVERY"); + TPM_PT_map.insert(0x212, "NV_WRITE_RECOVERY"); + TPM_PT_map.insert(0x213, "AUDIT_COUNTER_0"); + TPM_PT_map.insert(0x214, "AUDIT_COUNTER_1"); + map.insert(std::any::TypeId::of::(), TPM_PT_map); + + let mut TPM_PT_PCR_map: HashMap = HashMap::new(); + TPM_PT_PCR_map.insert(0x0, "FIRST"); + TPM_PT_PCR_map.insert(0x0, "SAVE"); + TPM_PT_PCR_map.insert(0x1, "EXTEND_L0"); + TPM_PT_PCR_map.insert(0x2, "RESET_L0"); + TPM_PT_PCR_map.insert(0x3, "EXTEND_L1"); + TPM_PT_PCR_map.insert(0x4, "RESET_L1"); + TPM_PT_PCR_map.insert(0x5, "EXTEND_L2"); + TPM_PT_PCR_map.insert(0x6, "RESET_L2"); + TPM_PT_PCR_map.insert(0x7, "EXTEND_L3"); + TPM_PT_PCR_map.insert(0x8, "RESET_L3"); + TPM_PT_PCR_map.insert(0x9, "EXTEND_L4"); + TPM_PT_PCR_map.insert(0xA, "RESET_L4"); + TPM_PT_PCR_map.insert(0x11, "NO_INCREMENT"); + TPM_PT_PCR_map.insert(0x12, "DRTM_RESET"); + TPM_PT_PCR_map.insert(0x13, "POLICY"); + TPM_PT_PCR_map.insert(0x14, "AUTH"); + TPM_PT_PCR_map.insert(0x14, "LAST"); + map.insert(std::any::TypeId::of::(), TPM_PT_PCR_map); + + let mut TPM_PS_map: HashMap = HashMap::new(); + TPM_PS_map.insert(0x0, "MAIN"); + TPM_PS_map.insert(0x1, "PC"); + TPM_PS_map.insert(0x2, "PDA"); + TPM_PS_map.insert(0x3, "CELL_PHONE"); + TPM_PS_map.insert(0x4, "SERVER"); + TPM_PS_map.insert(0x5, "PERIPHERAL"); + TPM_PS_map.insert(0x6, "TSS"); + TPM_PS_map.insert(0x7, "STORAGE"); + TPM_PS_map.insert(0x8, "AUTHENTICATION"); + TPM_PS_map.insert(0x9, "EMBEDDED"); + TPM_PS_map.insert(0xA, "HARDCOPY"); + TPM_PS_map.insert(0xB, "INFRASTRUCTURE"); + TPM_PS_map.insert(0xC, "VIRTUALIZATION"); + TPM_PS_map.insert(0xD, "TNC"); + TPM_PS_map.insert(0xE, "MULTI_TENANT"); + TPM_PS_map.insert(0xF, "TC"); + map.insert(std::any::TypeId::of::(), TPM_PS_map); + + let mut TPM_HT_map: HashMap = HashMap::new(); + TPM_HT_map.insert(0x0, "PCR"); + TPM_HT_map.insert(0x1, "NV_INDEX"); + TPM_HT_map.insert(0x2, "HMAC_SESSION"); + TPM_HT_map.insert(0x2, "LOADED_SESSION"); + TPM_HT_map.insert(0x3, "POLICY_SESSION"); + TPM_HT_map.insert(0x3, "SAVED_SESSION"); + TPM_HT_map.insert(0x40, "PERMANENT"); + TPM_HT_map.insert(0x80, "TRANSIENT"); + TPM_HT_map.insert(0x81, "PERSISTENT"); + TPM_HT_map.insert(0x90, "AC"); + map.insert(std::any::TypeId::of::(), TPM_HT_map); + + let mut TPM_RH_map: HashMap = HashMap::new(); + TPM_RH_map.insert(0x40000000, "FIRST"); + TPM_RH_map.insert(0x40000000, "SRK"); + TPM_RH_map.insert(0x40000001, "OWNER"); + TPM_RH_map.insert(0x40000002, "REVOKE"); + TPM_RH_map.insert(0x40000003, "TRANSPORT"); + TPM_RH_map.insert(0x40000004, "OPERATOR"); + TPM_RH_map.insert(0x40000005, "ADMIN"); + TPM_RH_map.insert(0x40000006, "EK"); + TPM_RH_map.insert(0x40000007, "NULL"); + TPM_RH_map.insert(0x40000008, "UNASSIGNED"); + TPM_RH_map.insert(0x40000009, "PW"); + TPM_RH_map.insert(0x4000000A, "LOCKOUT"); + TPM_RH_map.insert(0x4000000B, "ENDORSEMENT"); + TPM_RH_map.insert(0x4000000C, "PLATFORM"); + TPM_RH_map.insert(0x4000000D, "PLATFORM_NV"); + TPM_RH_map.insert(0x40000010, "AUTH_00"); + TPM_RH_map.insert(0x4000010F, "AUTH_FF"); + TPM_RH_map.insert(0x40000110, "ACT_0"); + TPM_RH_map.insert(0x4000011F, "ACT_F"); + TPM_RH_map.insert(0x4000011F, "LAST"); + map.insert(std::any::TypeId::of::(), TPM_RH_map); + + let mut TPM_NT_map: HashMap = HashMap::new(); + TPM_NT_map.insert(0x0, "ORDINARY"); + TPM_NT_map.insert(0x1, "COUNTER"); + TPM_NT_map.insert(0x2, "BITS"); + TPM_NT_map.insert(0x4, "EXTEND"); + TPM_NT_map.insert(0x8, "PIN_FAIL"); + TPM_NT_map.insert(0x9, "PIN_PASS"); + map.insert(std::any::TypeId::of::(), TPM_NT_map); + + let mut TPM_AT_map: HashMap = HashMap::new(); + TPM_AT_map.insert(0x0, "ANY"); + TPM_AT_map.insert(0x1, "ERROR"); + TPM_AT_map.insert(0x2, "PV1"); + TPM_AT_map.insert(0x80000000, "VEND"); + map.insert(std::any::TypeId::of::(), TPM_AT_map); + + let mut TPM_AE_map: HashMap = HashMap::new(); + TPM_AE_map.insert(0x0, "NONE"); + map.insert(std::any::TypeId::of::(), TPM_AE_map); + + let mut PLATFORM_map: HashMap = HashMap::new(); + PLATFORM_map.insert(0x322E3000, "FAMILY"); + PLATFORM_map.insert(0x0, "LEVEL"); + PLATFORM_map.insert(0xA2, "VERSION"); + PLATFORM_map.insert(0x7E3, "YEAR"); + PLATFORM_map.insert(0x168, "DAY_OF_YEAR"); + map.insert(std::any::TypeId::of::(), PLATFORM_map); + + let mut Implementation_map: HashMap = HashMap::new(); + Implementation_map.insert(0x0, "FIELD_UPGRADE_IMPLEMENTED"); + Implementation_map.insert(0x1, "HASH_LIB"); + Implementation_map.insert(0x1, "SYM_LIB"); + Implementation_map.insert(0x1, "MATH_LIB"); + Implementation_map.insert(0x18, "IMPLEMENTATION_PCR"); + Implementation_map.insert(0x3, "PCR_SELECT_MAX"); + Implementation_map.insert(0x18, "PLATFORM_PCR"); + Implementation_map.insert(0x3, "PCR_SELECT_MIN"); + Implementation_map.insert(0x11, "DRTM_PCR"); + Implementation_map.insert(0x0, "HCRTM_PCR"); + Implementation_map.insert(0x5, "NUM_LOCALITIES"); + Implementation_map.insert(0x3, "MAX_HANDLE_NUM"); + Implementation_map.insert(0x40, "MAX_ACTIVE_SESSIONS"); + Implementation_map.insert(0x3, "MAX_LOADED_SESSIONS"); + Implementation_map.insert(0x3, "MAX_SESSION_NUM"); + Implementation_map.insert(0x3, "MAX_LOADED_OBJECTS"); + Implementation_map.insert(0x2, "MIN_EVICT_OBJECTS"); + Implementation_map.insert(0x1, "NUM_POLICY_PCR_GROUP"); + Implementation_map.insert(0x1, "NUM_AUTHVALUE_PCR_GROUP"); + Implementation_map.insert(0x4F0, "MAX_CONTEXT_SIZE"); + Implementation_map.insert(0x400, "MAX_DIGEST_BUFFER"); + Implementation_map.insert(0x800, "MAX_NV_INDEX_SIZE"); + Implementation_map.insert(0x400, "MAX_NV_BUFFER_SIZE"); + Implementation_map.insert(0x400, "MAX_CAP_BUFFER"); + Implementation_map.insert(0x4000, "NV_MEMORY_SIZE"); + Implementation_map.insert(0x8, "MIN_COUNTER_INDICES"); + Implementation_map.insert(0x10, "NUM_STATIC_PCR"); + Implementation_map.insert(0x40, "MAX_ALG_LIST_SIZE"); + Implementation_map.insert(0x20, "PRIMARY_SEED_SIZE"); + Implementation_map.insert(0x6, "CONTEXT_ENCRYPT_ALGORITHM"); + Implementation_map.insert(0xC, "NV_CLOCK_UPDATE_INTERVAL"); + Implementation_map.insert(0x1, "NUM_POLICY_PCR"); + Implementation_map.insert(0x1000, "MAX_COMMAND_SIZE"); + Implementation_map.insert(0x1000, "MAX_RESPONSE_SIZE"); + Implementation_map.insert(0x8, "ORDERLY_BITS"); + Implementation_map.insert(0x80, "MAX_SYM_DATA"); + Implementation_map.insert(0x40, "MAX_RNG_ENTROPY_SIZE"); + Implementation_map.insert(0x200, "RAM_INDEX_SPACE"); + Implementation_map.insert(0x10001, "RSA_DEFAULT_PUBLIC_EXPONENT"); + Implementation_map.insert(0x1, "ENABLE_PCR_NO_INCREMENT"); + Implementation_map.insert(0x1, "CRT_FORMAT_RSA"); + Implementation_map.insert(0x0, "VENDOR_COMMAND_COUNT"); + Implementation_map.insert(0x400, "MAX_VENDOR_BUFFER_SIZE"); + Implementation_map.insert(0x2000, "MAX_DERIVATION_BITS"); + Implementation_map.insert(0x80, "RSA_MAX_PRIME"); + Implementation_map.insert(0x280, "RSA_PRIVATE_SIZE"); + Implementation_map.insert(0x14, "SIZE_OF_X509_SERIAL_NUMBER"); + Implementation_map.insert(0x280, "PRIVATE_VENDOR_SPECIFIC_BYTES"); + map.insert(std::any::TypeId::of::(), Implementation_map); + + let mut TPM_HC_map: HashMap = HashMap::new(); + TPM_HC_map.insert(0xFFFFFF, "HR_HANDLE_MASK"); + TPM_HC_map.insert(0xFF000000, "HR_RANGE_MASK"); + TPM_HC_map.insert(0x18, "HR_SHIFT"); + TPM_HC_map.insert(0x0, "HR_PCR"); + TPM_HC_map.insert(0x2000000, "HR_HMAC_SESSION"); + TPM_HC_map.insert(0x3000000, "HR_POLICY_SESSION"); + TPM_HC_map.insert(0x80000000, "HR_TRANSIENT"); + TPM_HC_map.insert(0x81000000, "HR_PERSISTENT"); + TPM_HC_map.insert(0x1000000, "HR_NV_INDEX"); + TPM_HC_map.insert(0x40000000, "HR_PERMANENT"); + TPM_HC_map.insert(0x0, "PCR_FIRST"); + TPM_HC_map.insert(0x17, "PCR_LAST"); + TPM_HC_map.insert(0x2000000, "HMAC_SESSION_FIRST"); + TPM_HC_map.insert(0x200003F, "HMAC_SESSION_LAST"); + TPM_HC_map.insert(0x2000000, "LOADED_SESSION_FIRST"); + TPM_HC_map.insert(0x200003F, "LOADED_SESSION_LAST"); + TPM_HC_map.insert(0x3000000, "POLICY_SESSION_FIRST"); + TPM_HC_map.insert(0x300003F, "POLICY_SESSION_LAST"); + TPM_HC_map.insert(0x80000000, "TRANSIENT_FIRST"); + TPM_HC_map.insert(0x3000000, "ACTIVE_SESSION_FIRST"); + TPM_HC_map.insert(0x300003F, "ACTIVE_SESSION_LAST"); + TPM_HC_map.insert(0x80000002, "TRANSIENT_LAST"); + TPM_HC_map.insert(0x81000000, "PERSISTENT_FIRST"); + TPM_HC_map.insert(0x81FFFFFF, "PERSISTENT_LAST"); + TPM_HC_map.insert(0x81800000, "PLATFORM_PERSISTENT"); + TPM_HC_map.insert(0x1000000, "NV_INDEX_FIRST"); + TPM_HC_map.insert(0x1FFFFFF, "NV_INDEX_LAST"); + TPM_HC_map.insert(0x40000000, "PERMANENT_FIRST"); + TPM_HC_map.insert(0x4000011F, "PERMANENT_LAST"); + TPM_HC_map.insert(0x1D00000, "HR_NV_AC"); + TPM_HC_map.insert(0x1D00000, "NV_AC_FIRST"); + TPM_HC_map.insert(0x1D0FFFF, "NV_AC_LAST"); + TPM_HC_map.insert(0x90000000, "HR_AC"); + TPM_HC_map.insert(0x90000000, "AC_FIRST"); + TPM_HC_map.insert(0x9000FFFF, "AC_LAST"); + map.insert(std::any::TypeId::of::(), TPM_HC_map); + + let mut TPMA_ALGORITHM_map: HashMap = HashMap::new(); + TPMA_ALGORITHM_map.insert(0x1, "asymmetric"); + TPMA_ALGORITHM_map.insert(0x2, "symmetric"); + TPMA_ALGORITHM_map.insert(0x4, "hash"); + TPMA_ALGORITHM_map.insert(0x8, "object"); + TPMA_ALGORITHM_map.insert(0x100, "signing"); + TPMA_ALGORITHM_map.insert(0x200, "encrypting"); + TPMA_ALGORITHM_map.insert(0x400, "method"); + map.insert(std::any::TypeId::of::(), TPMA_ALGORITHM_map); + + let mut TPMA_OBJECT_map: HashMap = HashMap::new(); + TPMA_OBJECT_map.insert(0x2, "fixedTPM"); + TPMA_OBJECT_map.insert(0x4, "stClear"); + TPMA_OBJECT_map.insert(0x10, "fixedParent"); + TPMA_OBJECT_map.insert(0x20, "sensitiveDataOrigin"); + TPMA_OBJECT_map.insert(0x40, "userWithAuth"); + TPMA_OBJECT_map.insert(0x80, "adminWithPolicy"); + TPMA_OBJECT_map.insert(0x400, "noDA"); + TPMA_OBJECT_map.insert(0x800, "encryptedDuplication"); + TPMA_OBJECT_map.insert(0x10000, "restricted"); + TPMA_OBJECT_map.insert(0x20000, "decrypt"); + TPMA_OBJECT_map.insert(0x40000, "sign"); + TPMA_OBJECT_map.insert(0x40000, "encrypt"); + TPMA_OBJECT_map.insert(0x80000, "x509sign"); + map.insert(std::any::TypeId::of::(), TPMA_OBJECT_map); + + let mut TPMA_SESSION_map: HashMap = HashMap::new(); + TPMA_SESSION_map.insert(0x1, "continueSession"); + TPMA_SESSION_map.insert(0x2, "auditExclusive"); + TPMA_SESSION_map.insert(0x4, "auditReset"); + TPMA_SESSION_map.insert(0x20, "decrypt"); + TPMA_SESSION_map.insert(0x40, "encrypt"); + TPMA_SESSION_map.insert(0x80, "audit"); + map.insert(std::any::TypeId::of::(), TPMA_SESSION_map); + + let mut TPMA_LOCALITY_map: HashMap = HashMap::new(); + TPMA_LOCALITY_map.insert(0x1, "LOC_ZERO"); + TPMA_LOCALITY_map.insert(0x2, "LOC_ONE"); + TPMA_LOCALITY_map.insert(0x4, "LOC_TWO"); + TPMA_LOCALITY_map.insert(0x8, "LOC_THREE"); + TPMA_LOCALITY_map.insert(0x10, "LOC_FOUR"); + map.insert(std::any::TypeId::of::(), TPMA_LOCALITY_map); + + let mut TPMA_PERMANENT_map: HashMap = HashMap::new(); + TPMA_PERMANENT_map.insert(0x1, "ownerAuthSet"); + TPMA_PERMANENT_map.insert(0x2, "endorsementAuthSet"); + TPMA_PERMANENT_map.insert(0x4, "lockoutAuthSet"); + TPMA_PERMANENT_map.insert(0x100, "disableClear"); + TPMA_PERMANENT_map.insert(0x200, "inLockout"); + TPMA_PERMANENT_map.insert(0x400, "tpmGeneratedEPS"); + map.insert(std::any::TypeId::of::(), TPMA_PERMANENT_map); + + let mut TPMA_STARTUP_CLEAR_map: HashMap = HashMap::new(); + TPMA_STARTUP_CLEAR_map.insert(0x1, "phEnable"); + TPMA_STARTUP_CLEAR_map.insert(0x2, "shEnable"); + TPMA_STARTUP_CLEAR_map.insert(0x4, "ehEnable"); + TPMA_STARTUP_CLEAR_map.insert(0x8, "phEnableNV"); + TPMA_STARTUP_CLEAR_map.insert(0x80000000, "orderly"); + map.insert(std::any::TypeId::of::(), TPMA_STARTUP_CLEAR_map); + + let mut TPMA_MEMORY_map: HashMap = HashMap::new(); + TPMA_MEMORY_map.insert(0x1, "sharedRAM"); + TPMA_MEMORY_map.insert(0x2, "sharedNV"); + TPMA_MEMORY_map.insert(0x4, "objectCopiedToRam"); + map.insert(std::any::TypeId::of::(), TPMA_MEMORY_map); + + let mut TPMA_CC_map: HashMap = HashMap::new(); + TPMA_CC_map.insert(0x400000, "nv"); + TPMA_CC_map.insert(0x800000, "extensive"); + TPMA_CC_map.insert(0x1000000, "flushed"); + TPMA_CC_map.insert(0x10000000, "rHandle"); + TPMA_CC_map.insert(0x20000000, "V"); + map.insert(std::any::TypeId::of::(), TPMA_CC_map); + + let mut TPMA_MODES_map: HashMap = HashMap::new(); + TPMA_MODES_map.insert(0x1, "FIPS_140_2"); + map.insert(std::any::TypeId::of::(), TPMA_MODES_map); + + let mut TPMA_X509_KEY_USAGE_map: HashMap = HashMap::new(); + TPMA_X509_KEY_USAGE_map.insert(0x800000, "decipherOnly"); + TPMA_X509_KEY_USAGE_map.insert(0x1000000, "encipherOnly"); + TPMA_X509_KEY_USAGE_map.insert(0x2000000, "cRLSign"); + TPMA_X509_KEY_USAGE_map.insert(0x4000000, "keyCertSign"); + TPMA_X509_KEY_USAGE_map.insert(0x8000000, "keyAgreement"); + TPMA_X509_KEY_USAGE_map.insert(0x10000000, "dataEncipherment"); + TPMA_X509_KEY_USAGE_map.insert(0x20000000, "keyEncipherment"); + TPMA_X509_KEY_USAGE_map.insert(0x40000000, "nonrepudiation"); + TPMA_X509_KEY_USAGE_map.insert(0x40000000, "contentCommitment"); + TPMA_X509_KEY_USAGE_map.insert(0x80000000, "digitalSignature"); + map.insert(std::any::TypeId::of::(), TPMA_X509_KEY_USAGE_map); + + let mut TPMA_ACT_map: HashMap = HashMap::new(); + TPMA_ACT_map.insert(0x1, "signaled"); + TPMA_ACT_map.insert(0x2, "preserveSignaled"); + map.insert(std::any::TypeId::of::(), TPMA_ACT_map); + + let TPM_NV_INDEX_map: HashMap = HashMap::new(); + map.insert(std::any::TypeId::of::(), TPM_NV_INDEX_map); + + let mut TPMA_NV_map: HashMap = HashMap::new(); + TPMA_NV_map.insert(0x1, "PPWRITE"); + TPMA_NV_map.insert(0x2, "OWNERWRITE"); + TPMA_NV_map.insert(0x4, "AUTHWRITE"); + TPMA_NV_map.insert(0x8, "POLICYWRITE"); + TPMA_NV_map.insert(0x0, "ORDINARY"); + TPMA_NV_map.insert(0x10, "COUNTER"); + TPMA_NV_map.insert(0x20, "BITS"); + TPMA_NV_map.insert(0x40, "EXTEND"); + TPMA_NV_map.insert(0x80, "PIN_FAIL"); + TPMA_NV_map.insert(0x90, "PIN_PASS"); + TPMA_NV_map.insert(0x400, "POLICY_DELETE"); + TPMA_NV_map.insert(0x800, "WRITELOCKED"); + TPMA_NV_map.insert(0x1000, "WRITEALL"); + TPMA_NV_map.insert(0x2000, "WRITEDEFINE"); + TPMA_NV_map.insert(0x4000, "WRITE_STCLEAR"); + TPMA_NV_map.insert(0x8000, "GLOBALLOCK"); + TPMA_NV_map.insert(0x10000, "PPREAD"); + TPMA_NV_map.insert(0x20000, "OWNERREAD"); + TPMA_NV_map.insert(0x40000, "AUTHREAD"); + TPMA_NV_map.insert(0x80000, "POLICYREAD"); + TPMA_NV_map.insert(0x2000000, "NO_DA"); + TPMA_NV_map.insert(0x4000000, "ORDERLY"); + TPMA_NV_map.insert(0x8000000, "CLEAR_STCLEAR"); + TPMA_NV_map.insert(0x10000000, "READLOCKED"); + TPMA_NV_map.insert(0x20000000, "WRITTEN"); + TPMA_NV_map.insert(0x40000000, "PLATFORMCREATE"); + TPMA_NV_map.insert(0x80000000, "READ_STCLEAR"); + map.insert(std::any::TypeId::of::(), TPMA_NV_map); + + map + }; + + /// Maps enum type IDs to a map of string representations to values + static ref STR_TO_ENUM_MAP: HashMap> = { + let mut map = HashMap::new(); + let mut TPM_ALG_ID_map: HashMap<&'static str, u64> = HashMap::new(); + TPM_ALG_ID_map.insert("ERROR", 0x0); + TPM_ALG_ID_map.insert("FIRST", 0x1); + TPM_ALG_ID_map.insert("RSA", 0x1); + TPM_ALG_ID_map.insert("TDES", 0x3); + TPM_ALG_ID_map.insert("SHA", 0x4); + TPM_ALG_ID_map.insert("SHA1", 0x4); + TPM_ALG_ID_map.insert("HMAC", 0x5); + TPM_ALG_ID_map.insert("AES", 0x6); + TPM_ALG_ID_map.insert("MGF1", 0x7); + TPM_ALG_ID_map.insert("KEYEDHASH", 0x8); + TPM_ALG_ID_map.insert("XOR", 0xA); + TPM_ALG_ID_map.insert("SHA256", 0xB); + TPM_ALG_ID_map.insert("SHA384", 0xC); + TPM_ALG_ID_map.insert("SHA512", 0xD); + TPM_ALG_ID_map.insert("NULL", 0x10); + TPM_ALG_ID_map.insert("SM3_256", 0x12); + TPM_ALG_ID_map.insert("SM4", 0x13); + TPM_ALG_ID_map.insert("RSASSA", 0x14); + TPM_ALG_ID_map.insert("RSAES", 0x15); + TPM_ALG_ID_map.insert("RSAPSS", 0x16); + TPM_ALG_ID_map.insert("OAEP", 0x17); + TPM_ALG_ID_map.insert("ECDSA", 0x18); + TPM_ALG_ID_map.insert("ECDH", 0x19); + TPM_ALG_ID_map.insert("ECDAA", 0x1A); + TPM_ALG_ID_map.insert("SM2", 0x1B); + TPM_ALG_ID_map.insert("ECSCHNORR", 0x1C); + TPM_ALG_ID_map.insert("ECMQV", 0x1D); + TPM_ALG_ID_map.insert("KDF1_SP800_56A", 0x20); + TPM_ALG_ID_map.insert("KDF2", 0x21); + TPM_ALG_ID_map.insert("KDF1_SP800_108", 0x22); + TPM_ALG_ID_map.insert("ECC", 0x23); + TPM_ALG_ID_map.insert("SYMCIPHER", 0x25); + TPM_ALG_ID_map.insert("CAMELLIA", 0x26); + TPM_ALG_ID_map.insert("SHA3_256", 0x27); + TPM_ALG_ID_map.insert("SHA3_384", 0x28); + TPM_ALG_ID_map.insert("SHA3_512", 0x29); + TPM_ALG_ID_map.insert("CMAC", 0x3F); + TPM_ALG_ID_map.insert("CTR", 0x40); + TPM_ALG_ID_map.insert("OFB", 0x41); + TPM_ALG_ID_map.insert("CBC", 0x42); + TPM_ALG_ID_map.insert("CFB", 0x43); + TPM_ALG_ID_map.insert("ECB", 0x44); + TPM_ALG_ID_map.insert("LAST", 0x44); + TPM_ALG_ID_map.insert("ANY", 0x7FFF); + TPM_ALG_ID_map.insert("ANY2", 0x7FFE); + map.insert(std::any::TypeId::of::(), TPM_ALG_ID_map); + + let mut TPM_ECC_CURVE_map: HashMap<&'static str, u64> = HashMap::new(); + TPM_ECC_CURVE_map.insert("NONE", 0x0); + TPM_ECC_CURVE_map.insert("NIST_P192", 0x1); + TPM_ECC_CURVE_map.insert("NIST_P224", 0x2); + TPM_ECC_CURVE_map.insert("NIST_P256", 0x3); + TPM_ECC_CURVE_map.insert("NIST_P384", 0x4); + TPM_ECC_CURVE_map.insert("NIST_P521", 0x5); + TPM_ECC_CURVE_map.insert("BN_P256", 0x10); + TPM_ECC_CURVE_map.insert("BN_P638", 0x11); + TPM_ECC_CURVE_map.insert("SM2_P256", 0x20); + TPM_ECC_CURVE_map.insert("TEST_P192", 0x21); + map.insert(std::any::TypeId::of::(), TPM_ECC_CURVE_map); + + let mut SHA1_map: HashMap<&'static str, u64> = HashMap::new(); + SHA1_map.insert("DIGEST_SIZE", 0x14); + SHA1_map.insert("BLOCK_SIZE", 0x40); + map.insert(std::any::TypeId::of::(), SHA1_map); + + let mut SHA256_map: HashMap<&'static str, u64> = HashMap::new(); + SHA256_map.insert("DIGEST_SIZE", 0x20); + SHA256_map.insert("BLOCK_SIZE", 0x40); + map.insert(std::any::TypeId::of::(), SHA256_map); + + let mut SHA384_map: HashMap<&'static str, u64> = HashMap::new(); + SHA384_map.insert("DIGEST_SIZE", 0x30); + SHA384_map.insert("BLOCK_SIZE", 0x80); + map.insert(std::any::TypeId::of::(), SHA384_map); + + let mut SHA512_map: HashMap<&'static str, u64> = HashMap::new(); + SHA512_map.insert("DIGEST_SIZE", 0x40); + SHA512_map.insert("BLOCK_SIZE", 0x80); + map.insert(std::any::TypeId::of::(), SHA512_map); + + let mut SM3_256_map: HashMap<&'static str, u64> = HashMap::new(); + SM3_256_map.insert("DIGEST_SIZE", 0x20); + SM3_256_map.insert("BLOCK_SIZE", 0x40); + map.insert(std::any::TypeId::of::(), SM3_256_map); + + let mut SHA3_256_map: HashMap<&'static str, u64> = HashMap::new(); + SHA3_256_map.insert("DIGEST_SIZE", 0x20); + SHA3_256_map.insert("BLOCK_SIZE", 0x88); + map.insert(std::any::TypeId::of::(), SHA3_256_map); + + let mut SHA3_384_map: HashMap<&'static str, u64> = HashMap::new(); + SHA3_384_map.insert("DIGEST_SIZE", 0x30); + SHA3_384_map.insert("BLOCK_SIZE", 0x68); + map.insert(std::any::TypeId::of::(), SHA3_384_map); + + let mut SHA3_512_map: HashMap<&'static str, u64> = HashMap::new(); + SHA3_512_map.insert("DIGEST_SIZE", 0x40); + SHA3_512_map.insert("BLOCK_SIZE", 0x48); + map.insert(std::any::TypeId::of::(), SHA3_512_map); + + let mut Logic_map: HashMap<&'static str, u64> = HashMap::new(); + Logic_map.insert("TRUE", 0x1); + Logic_map.insert("FALSE", 0x0); + Logic_map.insert("YES", 0x1); + Logic_map.insert("NO", 0x0); + Logic_map.insert("SET", 0x1); + Logic_map.insert("CLEAR", 0x0); + map.insert(std::any::TypeId::of::(), Logic_map); + + let mut TPM_SPEC_map: HashMap<&'static str, u64> = HashMap::new(); + TPM_SPEC_map.insert("FAMILY", 0x322E3000); + TPM_SPEC_map.insert("LEVEL", 0x0); + TPM_SPEC_map.insert("VERSION", 0xA2); + TPM_SPEC_map.insert("YEAR", 0x7E3); + TPM_SPEC_map.insert("DAY_OF_YEAR", 0x168); + map.insert(std::any::TypeId::of::(), TPM_SPEC_map); + + let mut TPM_GENERATED_map: HashMap<&'static str, u64> = HashMap::new(); + TPM_GENERATED_map.insert("VALUE", 0xFF544347); + map.insert(std::any::TypeId::of::(), TPM_GENERATED_map); + + let mut TPM_CC_map: HashMap<&'static str, u64> = HashMap::new(); + TPM_CC_map.insert("FIRST", 0x11F); + TPM_CC_map.insert("NV_UndefineSpaceSpecial", 0x11F); + TPM_CC_map.insert("EvictControl", 0x120); + TPM_CC_map.insert("HierarchyControl", 0x121); + TPM_CC_map.insert("NV_UndefineSpace", 0x122); + TPM_CC_map.insert("ChangeEPS", 0x124); + TPM_CC_map.insert("ChangePPS", 0x125); + TPM_CC_map.insert("Clear", 0x126); + TPM_CC_map.insert("ClearControl", 0x127); + TPM_CC_map.insert("ClockSet", 0x128); + TPM_CC_map.insert("HierarchyChangeAuth", 0x129); + TPM_CC_map.insert("NV_DefineSpace", 0x12A); + TPM_CC_map.insert("PCR_Allocate", 0x12B); + TPM_CC_map.insert("PCR_SetAuthPolicy", 0x12C); + TPM_CC_map.insert("PP_Commands", 0x12D); + TPM_CC_map.insert("SetPrimaryPolicy", 0x12E); + TPM_CC_map.insert("FieldUpgradeStart", 0x12F); + TPM_CC_map.insert("ClockRateAdjust", 0x130); + TPM_CC_map.insert("CreatePrimary", 0x131); + TPM_CC_map.insert("NV_GlobalWriteLock", 0x132); + TPM_CC_map.insert("GetCommandAuditDigest", 0x133); + TPM_CC_map.insert("NV_Increment", 0x134); + TPM_CC_map.insert("NV_SetBits", 0x135); + TPM_CC_map.insert("NV_Extend", 0x136); + TPM_CC_map.insert("NV_Write", 0x137); + TPM_CC_map.insert("NV_WriteLock", 0x138); + TPM_CC_map.insert("DictionaryAttackLockReset", 0x139); + TPM_CC_map.insert("DictionaryAttackParameters", 0x13A); + TPM_CC_map.insert("NV_ChangeAuth", 0x13B); + TPM_CC_map.insert("PCR_Event", 0x13C); + TPM_CC_map.insert("PCR_Reset", 0x13D); + TPM_CC_map.insert("SequenceComplete", 0x13E); + TPM_CC_map.insert("SetAlgorithmSet", 0x13F); + TPM_CC_map.insert("SetCommandCodeAuditStatus", 0x140); + TPM_CC_map.insert("FieldUpgradeData", 0x141); + TPM_CC_map.insert("IncrementalSelfTest", 0x142); + TPM_CC_map.insert("SelfTest", 0x143); + TPM_CC_map.insert("Startup", 0x144); + TPM_CC_map.insert("Shutdown", 0x145); + TPM_CC_map.insert("StirRandom", 0x146); + TPM_CC_map.insert("ActivateCredential", 0x147); + TPM_CC_map.insert("Certify", 0x148); + TPM_CC_map.insert("PolicyNV", 0x149); + TPM_CC_map.insert("CertifyCreation", 0x14A); + TPM_CC_map.insert("Duplicate", 0x14B); + TPM_CC_map.insert("GetTime", 0x14C); + TPM_CC_map.insert("GetSessionAuditDigest", 0x14D); + TPM_CC_map.insert("NV_Read", 0x14E); + TPM_CC_map.insert("NV_ReadLock", 0x14F); + TPM_CC_map.insert("ObjectChangeAuth", 0x150); + TPM_CC_map.insert("PolicySecret", 0x151); + TPM_CC_map.insert("Rewrap", 0x152); + TPM_CC_map.insert("Create", 0x153); + TPM_CC_map.insert("ECDH_ZGen", 0x154); + TPM_CC_map.insert("HMAC", 0x155); + TPM_CC_map.insert("MAC", 0x155); + TPM_CC_map.insert("Import", 0x156); + TPM_CC_map.insert("Load", 0x157); + TPM_CC_map.insert("Quote", 0x158); + TPM_CC_map.insert("RSA_Decrypt", 0x159); + TPM_CC_map.insert("HMAC_Start", 0x15B); + TPM_CC_map.insert("MAC_Start", 0x15B); + TPM_CC_map.insert("SequenceUpdate", 0x15C); + TPM_CC_map.insert("Sign", 0x15D); + TPM_CC_map.insert("Unseal", 0x15E); + TPM_CC_map.insert("PolicySigned", 0x160); + TPM_CC_map.insert("ContextLoad", 0x161); + TPM_CC_map.insert("ContextSave", 0x162); + TPM_CC_map.insert("ECDH_KeyGen", 0x163); + TPM_CC_map.insert("EncryptDecrypt", 0x164); + TPM_CC_map.insert("FlushContext", 0x165); + TPM_CC_map.insert("LoadExternal", 0x167); + TPM_CC_map.insert("MakeCredential", 0x168); + TPM_CC_map.insert("NV_ReadPublic", 0x169); + TPM_CC_map.insert("PolicyAuthorize", 0x16A); + TPM_CC_map.insert("PolicyAuthValue", 0x16B); + TPM_CC_map.insert("PolicyCommandCode", 0x16C); + TPM_CC_map.insert("PolicyCounterTimer", 0x16D); + TPM_CC_map.insert("PolicyCpHash", 0x16E); + TPM_CC_map.insert("PolicyLocality", 0x16F); + TPM_CC_map.insert("PolicyNameHash", 0x170); + TPM_CC_map.insert("PolicyOR", 0x171); + TPM_CC_map.insert("PolicyTicket", 0x172); + TPM_CC_map.insert("ReadPublic", 0x173); + TPM_CC_map.insert("RSA_Encrypt", 0x174); + TPM_CC_map.insert("StartAuthSession", 0x176); + TPM_CC_map.insert("VerifySignature", 0x177); + TPM_CC_map.insert("ECC_Parameters", 0x178); + TPM_CC_map.insert("FirmwareRead", 0x179); + TPM_CC_map.insert("GetCapability", 0x17A); + TPM_CC_map.insert("GetRandom", 0x17B); + TPM_CC_map.insert("GetTestResult", 0x17C); + TPM_CC_map.insert("Hash", 0x17D); + TPM_CC_map.insert("PCR_Read", 0x17E); + TPM_CC_map.insert("PolicyPCR", 0x17F); + TPM_CC_map.insert("PolicyRestart", 0x180); + TPM_CC_map.insert("ReadClock", 0x181); + TPM_CC_map.insert("PCR_Extend", 0x182); + TPM_CC_map.insert("PCR_SetAuthValue", 0x183); + TPM_CC_map.insert("NV_Certify", 0x184); + TPM_CC_map.insert("EventSequenceComplete", 0x185); + TPM_CC_map.insert("HashSequenceStart", 0x186); + TPM_CC_map.insert("PolicyPhysicalPresence", 0x187); + TPM_CC_map.insert("PolicyDuplicationSelect", 0x188); + TPM_CC_map.insert("PolicyGetDigest", 0x189); + TPM_CC_map.insert("TestParms", 0x18A); + TPM_CC_map.insert("Commit", 0x18B); + TPM_CC_map.insert("PolicyPassword", 0x18C); + TPM_CC_map.insert("ZGen_2Phase", 0x18D); + TPM_CC_map.insert("EC_Ephemeral", 0x18E); + TPM_CC_map.insert("PolicyNvWritten", 0x18F); + TPM_CC_map.insert("PolicyTemplate", 0x190); + TPM_CC_map.insert("CreateLoaded", 0x191); + TPM_CC_map.insert("PolicyAuthorizeNV", 0x192); + TPM_CC_map.insert("EncryptDecrypt2", 0x193); + TPM_CC_map.insert("AC_GetCapability", 0x194); + TPM_CC_map.insert("AC_Send", 0x195); + TPM_CC_map.insert("Policy_AC_SendSelect", 0x196); + TPM_CC_map.insert("CertifyX509", 0x197); + TPM_CC_map.insert("ACT_SetTimeout", 0x198); + TPM_CC_map.insert("ECC_Encrypt", 0x199); + TPM_CC_map.insert("ECC_Decrypt", 0x19A); + TPM_CC_map.insert("LAST", 0x19A); + TPM_CC_map.insert("CC_VEND", 0x20000000); + TPM_CC_map.insert("Vendor_TCG_Test", 0x20000000); + map.insert(std::any::TypeId::of::(), TPM_CC_map); + + let mut ImplementationConstants_map: HashMap<&'static str, u64> = HashMap::new(); + ImplementationConstants_map.insert("Ossl", 0x1); + ImplementationConstants_map.insert("Ltc", 0x2); + ImplementationConstants_map.insert("Msbn", 0x3); + ImplementationConstants_map.insert("Symcrypt", 0x4); + ImplementationConstants_map.insert("HASH_COUNT", 0x3); + ImplementationConstants_map.insert("MAX_SYM_KEY_BITS", 0x100); + ImplementationConstants_map.insert("MAX_SYM_KEY_BYTES", 0x20); + ImplementationConstants_map.insert("MAX_SYM_BLOCK_SIZE", 0x10); + ImplementationConstants_map.insert("MAX_CAP_CC", 0x19A); + ImplementationConstants_map.insert("MAX_RSA_KEY_BYTES", 0x100); + ImplementationConstants_map.insert("MAX_AES_KEY_BYTES", 0x20); + ImplementationConstants_map.insert("MAX_ECC_KEY_BYTES", 0x30); + ImplementationConstants_map.insert("LABEL_MAX_BUFFER", 0x20); + ImplementationConstants_map.insert("_TPM_CAP_SIZE", 0x4); + ImplementationConstants_map.insert("MAX_CAP_DATA", 0x3F8); + ImplementationConstants_map.insert("MAX_CAP_ALGS", 0xA9); + ImplementationConstants_map.insert("MAX_CAP_HANDLES", 0xFE); + ImplementationConstants_map.insert("MAX_TPM_PROPERTIES", 0x7F); + ImplementationConstants_map.insert("MAX_PCR_PROPERTIES", 0xCB); + ImplementationConstants_map.insert("MAX_ECC_CURVES", 0x1FC); + ImplementationConstants_map.insert("MAX_TAGGED_POLICIES", 0xE); + ImplementationConstants_map.insert("MAX_AC_CAPABILITIES", 0x7F); + ImplementationConstants_map.insert("MAX_ACT_DATA", 0x54); + map.insert(std::any::TypeId::of::(), ImplementationConstants_map); + + let mut TPM_RC_map: HashMap<&'static str, u64> = HashMap::new(); + TPM_RC_map.insert("SUCCESS", 0x0); + TPM_RC_map.insert("BAD_TAG", 0x1E); + TPM_RC_map.insert("RC_VER1", 0x100); + TPM_RC_map.insert("INITIALIZE", 0x100); + TPM_RC_map.insert("FAILURE", 0x101); + TPM_RC_map.insert("SEQUENCE", 0x103); + TPM_RC_map.insert("PRIVATE", 0x10B); + TPM_RC_map.insert("HMAC", 0x119); + TPM_RC_map.insert("DISABLED", 0x120); + TPM_RC_map.insert("EXCLUSIVE", 0x121); + TPM_RC_map.insert("AUTH_TYPE", 0x124); + TPM_RC_map.insert("AUTH_MISSING", 0x125); + TPM_RC_map.insert("POLICY", 0x126); + TPM_RC_map.insert("PCR", 0x127); + TPM_RC_map.insert("PCR_CHANGED", 0x128); + TPM_RC_map.insert("UPGRADE", 0x12D); + TPM_RC_map.insert("TOO_MANY_CONTEXTS", 0x12E); + TPM_RC_map.insert("AUTH_UNAVAILABLE", 0x12F); + TPM_RC_map.insert("REBOOT", 0x130); + TPM_RC_map.insert("UNBALANCED", 0x131); + TPM_RC_map.insert("COMMAND_SIZE", 0x142); + TPM_RC_map.insert("COMMAND_CODE", 0x143); + TPM_RC_map.insert("AUTHSIZE", 0x144); + TPM_RC_map.insert("AUTH_CONTEXT", 0x145); + TPM_RC_map.insert("NV_RANGE", 0x146); + TPM_RC_map.insert("NV_SIZE", 0x147); + TPM_RC_map.insert("NV_LOCKED", 0x148); + TPM_RC_map.insert("NV_AUTHORIZATION", 0x149); + TPM_RC_map.insert("NV_UNINITIALIZED", 0x14A); + TPM_RC_map.insert("NV_SPACE", 0x14B); + TPM_RC_map.insert("NV_DEFINED", 0x14C); + TPM_RC_map.insert("BAD_CONTEXT", 0x150); + TPM_RC_map.insert("CPHASH", 0x151); + TPM_RC_map.insert("PARENT", 0x152); + TPM_RC_map.insert("NEEDS_TEST", 0x153); + TPM_RC_map.insert("NO_RESULT", 0x154); + TPM_RC_map.insert("SENSITIVE", 0x155); + TPM_RC_map.insert("RC_MAX_FM0", 0x17F); + TPM_RC_map.insert("RC_FMT1", 0x80); + TPM_RC_map.insert("ASYMMETRIC", 0x81); + TPM_RC_map.insert("ATTRIBUTES", 0x82); + TPM_RC_map.insert("HASH", 0x83); + TPM_RC_map.insert("VALUE", 0x84); + TPM_RC_map.insert("HIERARCHY", 0x85); + TPM_RC_map.insert("KEY_SIZE", 0x87); + TPM_RC_map.insert("MGF", 0x88); + TPM_RC_map.insert("MODE", 0x89); + TPM_RC_map.insert("TYPE", 0x8A); + TPM_RC_map.insert("HANDLE", 0x8B); + TPM_RC_map.insert("KDF", 0x8C); + TPM_RC_map.insert("RANGE", 0x8D); + TPM_RC_map.insert("AUTH_FAIL", 0x8E); + TPM_RC_map.insert("NONCE", 0x8F); + TPM_RC_map.insert("PP", 0x90); + TPM_RC_map.insert("SCHEME", 0x92); + TPM_RC_map.insert("SIZE", 0x95); + TPM_RC_map.insert("SYMMETRIC", 0x96); + TPM_RC_map.insert("TAG", 0x97); + TPM_RC_map.insert("SELECTOR", 0x98); + TPM_RC_map.insert("INSUFFICIENT", 0x9A); + TPM_RC_map.insert("SIGNATURE", 0x9B); + TPM_RC_map.insert("KEY", 0x9C); + TPM_RC_map.insert("POLICY_FAIL", 0x9D); + TPM_RC_map.insert("INTEGRITY", 0x9F); + TPM_RC_map.insert("TICKET", 0xA0); + TPM_RC_map.insert("RESERVED_BITS", 0xA1); + TPM_RC_map.insert("BAD_AUTH", 0xA2); + TPM_RC_map.insert("EXPIRED", 0xA3); + TPM_RC_map.insert("POLICY_CC", 0xA4); + TPM_RC_map.insert("BINDING", 0xA5); + TPM_RC_map.insert("CURVE", 0xA6); + TPM_RC_map.insert("ECC_POINT", 0xA7); + TPM_RC_map.insert("RC_WARN", 0x900); + TPM_RC_map.insert("CONTEXT_GAP", 0x901); + TPM_RC_map.insert("OBJECT_MEMORY", 0x902); + TPM_RC_map.insert("SESSION_MEMORY", 0x903); + TPM_RC_map.insert("MEMORY", 0x904); + TPM_RC_map.insert("SESSION_HANDLES", 0x905); + TPM_RC_map.insert("OBJECT_HANDLES", 0x906); + TPM_RC_map.insert("LOCALITY", 0x907); + TPM_RC_map.insert("YIELDED", 0x908); + TPM_RC_map.insert("CANCELED", 0x909); + TPM_RC_map.insert("TESTING", 0x90A); + TPM_RC_map.insert("REFERENCE_H0", 0x910); + TPM_RC_map.insert("REFERENCE_H1", 0x911); + TPM_RC_map.insert("REFERENCE_H2", 0x912); + TPM_RC_map.insert("REFERENCE_H3", 0x913); + TPM_RC_map.insert("REFERENCE_H4", 0x914); + TPM_RC_map.insert("REFERENCE_H5", 0x915); + TPM_RC_map.insert("REFERENCE_H6", 0x916); + TPM_RC_map.insert("REFERENCE_S0", 0x918); + TPM_RC_map.insert("REFERENCE_S1", 0x919); + TPM_RC_map.insert("REFERENCE_S2", 0x91A); + TPM_RC_map.insert("REFERENCE_S3", 0x91B); + TPM_RC_map.insert("REFERENCE_S4", 0x91C); + TPM_RC_map.insert("REFERENCE_S5", 0x91D); + TPM_RC_map.insert("REFERENCE_S6", 0x91E); + TPM_RC_map.insert("NV_RATE", 0x920); + TPM_RC_map.insert("LOCKOUT", 0x921); + TPM_RC_map.insert("RETRY", 0x922); + TPM_RC_map.insert("NV_UNAVAILABLE", 0x923); + TPM_RC_map.insert("NOT_USED", 0x97F); + TPM_RC_map.insert("H", 0x0); + TPM_RC_map.insert("P", 0x40); + TPM_RC_map.insert("S", 0x800); + TPM_RC_map.insert("_1", 0x100); + TPM_RC_map.insert("_2", 0x200); + TPM_RC_map.insert("_3", 0x300); + TPM_RC_map.insert("_4", 0x400); + TPM_RC_map.insert("_5", 0x500); + TPM_RC_map.insert("_6", 0x600); + TPM_RC_map.insert("_7", 0x700); + TPM_RC_map.insert("_8", 0x800); + TPM_RC_map.insert("_9", 0x900); + TPM_RC_map.insert("A", 0xA00); + TPM_RC_map.insert("B", 0xB00); + TPM_RC_map.insert("C", 0xC00); + TPM_RC_map.insert("D", 0xD00); + TPM_RC_map.insert("E", 0xE00); + TPM_RC_map.insert("F", 0xF00); + TPM_RC_map.insert("N_MASK", 0xF00); + TPM_RC_map.insert("TSS_TCP_BAD_HANDSHAKE_RESP", 0x40280001); + TPM_RC_map.insert("TSS_TCP_SERVER_TOO_OLD", 0x40280002); + TPM_RC_map.insert("TSS_TCP_BAD_ACK", 0x40280003); + TPM_RC_map.insert("TSS_TCP_BAD_RESP_LEN", 0x40280004); + TPM_RC_map.insert("TSS_TCP_UNEXPECTED_STARTUP_RESP", 0x40280005); + TPM_RC_map.insert("TSS_TCP_INVALID_SIZE_TAG", 0x40280006); + TPM_RC_map.insert("TSS_TCP_DISCONNECTED", 0x40280007); + TPM_RC_map.insert("TSS_DISPATCH_FAILED", 0x40280010); + TPM_RC_map.insert("TSS_SEND_OP_FAILED", 0x40280011); + TPM_RC_map.insert("TSS_RESP_BUF_TOO_SHORT", 0x40280021); + TPM_RC_map.insert("TSS_RESP_BUF_INVALID_SESSION_TAG", 0x40280022); + TPM_RC_map.insert("TSS_RESP_BUF_INVALID_SIZE", 0x40280023); + TPM_RC_map.insert("TBS_COMMAND_BLOCKED", 0x80280400); + TPM_RC_map.insert("TBS_INVALID_HANDLE", 0x80280401); + TPM_RC_map.insert("TBS_DUPLICATE_V_HANDLE", 0x80280402); + TPM_RC_map.insert("TBS_EMBEDDED_COMMAND_BLOCKED", 0x80280403); + TPM_RC_map.insert("TBS_EMBEDDED_COMMAND_UNSUPPORTED", 0x80280404); + TPM_RC_map.insert("TBS_UNKNOWN_ERROR", 0x80284000); + TPM_RC_map.insert("TBS_INTERNAL_ERROR", 0x80284001); + TPM_RC_map.insert("TBS_BAD_PARAMETER", 0x80284002); + TPM_RC_map.insert("TBS_INVALID_OUTPUT_POINTER", 0x80284003); + TPM_RC_map.insert("TBS_INVALID_CONTEXT", 0x80284004); + TPM_RC_map.insert("TBS_INSUFFICIENT_BUFFER", 0x80284005); + TPM_RC_map.insert("TBS_IO_ERROR", 0x80284006); + TPM_RC_map.insert("TBS_INVALID_CONTEXT_PARAM", 0x80284007); + TPM_RC_map.insert("TBS_SERVICE_NOT_RUNNING", 0x80284008); + TPM_RC_map.insert("TBS_TOO_MANY_CONTEXTS", 0x80284009); + TPM_RC_map.insert("TBS_TOO_MANY_RESOURCES", 0x8028400A); + TPM_RC_map.insert("TBS_SERVICE_START_PENDING", 0x8028400B); + TPM_RC_map.insert("TBS_PPI_NOT_SUPPORTED", 0x8028400C); + TPM_RC_map.insert("TBS_COMMAND_CANCELED", 0x8028400D); + TPM_RC_map.insert("TBS_BUFFER_TOO_LARGE", 0x8028400E); + TPM_RC_map.insert("TBS_TPM_NOT_FOUND", 0x8028400F); + TPM_RC_map.insert("TBS_SERVICE_DISABLED", 0x80284010); + TPM_RC_map.insert("TBS_ACCESS_DENIED", 0x80284012); + TPM_RC_map.insert("TBS_PPI_FUNCTION_NOT_SUPPORTED", 0x80284014); + TPM_RC_map.insert("TBS_OWNER_AUTH_NOT_FOUND", 0x80284015); + map.insert(std::any::TypeId::of::(), TPM_RC_map); + + let mut TPM_CLOCK_ADJUST_map: HashMap<&'static str, u64> = HashMap::new(); + TPM_CLOCK_ADJUST_map.insert("COARSE_SLOWER", 0xFFFFFFFD); + TPM_CLOCK_ADJUST_map.insert("MEDIUM_SLOWER", 0xFFFFFFFE); + TPM_CLOCK_ADJUST_map.insert("FINE_SLOWER", 0xFFFFFFFF); + TPM_CLOCK_ADJUST_map.insert("NO_CHANGE", 0x0); + TPM_CLOCK_ADJUST_map.insert("FINE_FASTER", 0x1); + TPM_CLOCK_ADJUST_map.insert("MEDIUM_FASTER", 0x2); + TPM_CLOCK_ADJUST_map.insert("COARSE_FASTER", 0x3); + map.insert(std::any::TypeId::of::(), TPM_CLOCK_ADJUST_map); + + let mut TPM_EO_map: HashMap<&'static str, u64> = HashMap::new(); + TPM_EO_map.insert("EQ", 0x0); + TPM_EO_map.insert("NEQ", 0x1); + TPM_EO_map.insert("SIGNED_GT", 0x2); + TPM_EO_map.insert("UNSIGNED_GT", 0x3); + TPM_EO_map.insert("SIGNED_LT", 0x4); + TPM_EO_map.insert("UNSIGNED_LT", 0x5); + TPM_EO_map.insert("SIGNED_GE", 0x6); + TPM_EO_map.insert("UNSIGNED_GE", 0x7); + TPM_EO_map.insert("SIGNED_LE", 0x8); + TPM_EO_map.insert("UNSIGNED_LE", 0x9); + TPM_EO_map.insert("BITSET", 0xA); + TPM_EO_map.insert("BITCLEAR", 0xB); + map.insert(std::any::TypeId::of::(), TPM_EO_map); + + let mut TPM_ST_map: HashMap<&'static str, u64> = HashMap::new(); + TPM_ST_map.insert("RSP_COMMAND", 0xC4); + TPM_ST_map.insert("NULL", 0x8000); + TPM_ST_map.insert("NO_SESSIONS", 0x8001); + TPM_ST_map.insert("SESSIONS", 0x8002); + TPM_ST_map.insert("ATTEST_NV", 0x8014); + TPM_ST_map.insert("ATTEST_COMMAND_AUDIT", 0x8015); + TPM_ST_map.insert("ATTEST_SESSION_AUDIT", 0x8016); + TPM_ST_map.insert("ATTEST_CERTIFY", 0x8017); + TPM_ST_map.insert("ATTEST_QUOTE", 0x8018); + TPM_ST_map.insert("ATTEST_TIME", 0x8019); + TPM_ST_map.insert("ATTEST_CREATION", 0x801A); + TPM_ST_map.insert("ATTEST_NV_DIGEST", 0x801C); + TPM_ST_map.insert("CREATION", 0x8021); + TPM_ST_map.insert("VERIFIED", 0x8022); + TPM_ST_map.insert("AUTH_SECRET", 0x8023); + TPM_ST_map.insert("HASHCHECK", 0x8024); + TPM_ST_map.insert("AUTH_SIGNED", 0x8025); + TPM_ST_map.insert("FU_MANIFEST", 0x8029); + map.insert(std::any::TypeId::of::(), TPM_ST_map); + + let mut TPM_SU_map: HashMap<&'static str, u64> = HashMap::new(); + TPM_SU_map.insert("CLEAR", 0x0); + TPM_SU_map.insert("STATE", 0x1); + map.insert(std::any::TypeId::of::(), TPM_SU_map); + + let mut TPM_SE_map: HashMap<&'static str, u64> = HashMap::new(); + TPM_SE_map.insert("HMAC", 0x0); + TPM_SE_map.insert("POLICY", 0x1); + TPM_SE_map.insert("TRIAL", 0x3); + map.insert(std::any::TypeId::of::(), TPM_SE_map); + + let mut TPM_CAP_map: HashMap<&'static str, u64> = HashMap::new(); + TPM_CAP_map.insert("FIRST", 0x0); + TPM_CAP_map.insert("ALGS", 0x0); + TPM_CAP_map.insert("HANDLES", 0x1); + TPM_CAP_map.insert("COMMANDS", 0x2); + TPM_CAP_map.insert("PP_COMMANDS", 0x3); + TPM_CAP_map.insert("AUDIT_COMMANDS", 0x4); + TPM_CAP_map.insert("PCRS", 0x5); + TPM_CAP_map.insert("TPM_PROPERTIES", 0x6); + TPM_CAP_map.insert("PCR_PROPERTIES", 0x7); + TPM_CAP_map.insert("ECC_CURVES", 0x8); + TPM_CAP_map.insert("AUTH_POLICIES", 0x9); + TPM_CAP_map.insert("ACT", 0xA); + TPM_CAP_map.insert("LAST", 0xA); + TPM_CAP_map.insert("VENDOR_PROPERTY", 0x100); + map.insert(std::any::TypeId::of::(), TPM_CAP_map); + + let mut TPM_PT_map: HashMap<&'static str, u64> = HashMap::new(); + TPM_PT_map.insert("NONE", 0x0); + TPM_PT_map.insert("PT_GROUP", 0x100); + TPM_PT_map.insert("PT_FIXED", 0x100); + TPM_PT_map.insert("FAMILY_INDICATOR", 0x100); + TPM_PT_map.insert("LEVEL", 0x101); + TPM_PT_map.insert("REVISION", 0x102); + TPM_PT_map.insert("DAY_OF_YEAR", 0x103); + TPM_PT_map.insert("YEAR", 0x104); + TPM_PT_map.insert("MANUFACTURER", 0x105); + TPM_PT_map.insert("VENDOR_STRING_1", 0x106); + TPM_PT_map.insert("VENDOR_STRING_2", 0x107); + TPM_PT_map.insert("VENDOR_STRING_3", 0x108); + TPM_PT_map.insert("VENDOR_STRING_4", 0x109); + TPM_PT_map.insert("VENDOR_TPM_TYPE", 0x10A); + TPM_PT_map.insert("FIRMWARE_VERSION_1", 0x10B); + TPM_PT_map.insert("FIRMWARE_VERSION_2", 0x10C); + TPM_PT_map.insert("INPUT_BUFFER", 0x10D); + TPM_PT_map.insert("HR_TRANSIENT_MIN", 0x10E); + TPM_PT_map.insert("HR_PERSISTENT_MIN", 0x10F); + TPM_PT_map.insert("HR_LOADED_MIN", 0x110); + TPM_PT_map.insert("ACTIVE_SESSIONS_MAX", 0x111); + TPM_PT_map.insert("PCR_COUNT", 0x112); + TPM_PT_map.insert("PCR_SELECT_MIN", 0x113); + TPM_PT_map.insert("CONTEXT_GAP_MAX", 0x114); + TPM_PT_map.insert("NV_COUNTERS_MAX", 0x116); + TPM_PT_map.insert("NV_INDEX_MAX", 0x117); + TPM_PT_map.insert("MEMORY", 0x118); + TPM_PT_map.insert("CLOCK_UPDATE", 0x119); + TPM_PT_map.insert("CONTEXT_HASH", 0x11A); + TPM_PT_map.insert("CONTEXT_SYM", 0x11B); + TPM_PT_map.insert("CONTEXT_SYM_SIZE", 0x11C); + TPM_PT_map.insert("ORDERLY_COUNT", 0x11D); + TPM_PT_map.insert("MAX_COMMAND_SIZE", 0x11E); + TPM_PT_map.insert("MAX_RESPONSE_SIZE", 0x11F); + TPM_PT_map.insert("MAX_DIGEST", 0x120); + TPM_PT_map.insert("MAX_OBJECT_CONTEXT", 0x121); + TPM_PT_map.insert("MAX_SESSION_CONTEXT", 0x122); + TPM_PT_map.insert("PS_FAMILY_INDICATOR", 0x123); + TPM_PT_map.insert("PS_LEVEL", 0x124); + TPM_PT_map.insert("PS_REVISION", 0x125); + TPM_PT_map.insert("PS_DAY_OF_YEAR", 0x126); + TPM_PT_map.insert("PS_YEAR", 0x127); + TPM_PT_map.insert("SPLIT_MAX", 0x128); + TPM_PT_map.insert("TOTAL_COMMANDS", 0x129); + TPM_PT_map.insert("LIBRARY_COMMANDS", 0x12A); + TPM_PT_map.insert("VENDOR_COMMANDS", 0x12B); + TPM_PT_map.insert("NV_BUFFER_MAX", 0x12C); + TPM_PT_map.insert("MODES", 0x12D); + TPM_PT_map.insert("MAX_CAP_BUFFER", 0x12E); + TPM_PT_map.insert("PT_VAR", 0x200); + TPM_PT_map.insert("PERMANENT", 0x200); + TPM_PT_map.insert("STARTUP_CLEAR", 0x201); + TPM_PT_map.insert("HR_NV_INDEX", 0x202); + TPM_PT_map.insert("HR_LOADED", 0x203); + TPM_PT_map.insert("HR_LOADED_AVAIL", 0x204); + TPM_PT_map.insert("HR_ACTIVE", 0x205); + TPM_PT_map.insert("HR_ACTIVE_AVAIL", 0x206); + TPM_PT_map.insert("HR_TRANSIENT_AVAIL", 0x207); + TPM_PT_map.insert("HR_PERSISTENT", 0x208); + TPM_PT_map.insert("HR_PERSISTENT_AVAIL", 0x209); + TPM_PT_map.insert("NV_COUNTERS", 0x20A); + TPM_PT_map.insert("NV_COUNTERS_AVAIL", 0x20B); + TPM_PT_map.insert("ALGORITHM_SET", 0x20C); + TPM_PT_map.insert("LOADED_CURVES", 0x20D); + TPM_PT_map.insert("LOCKOUT_COUNTER", 0x20E); + TPM_PT_map.insert("MAX_AUTH_FAIL", 0x20F); + TPM_PT_map.insert("LOCKOUT_INTERVAL", 0x210); + TPM_PT_map.insert("LOCKOUT_RECOVERY", 0x211); + TPM_PT_map.insert("NV_WRITE_RECOVERY", 0x212); + TPM_PT_map.insert("AUDIT_COUNTER_0", 0x213); + TPM_PT_map.insert("AUDIT_COUNTER_1", 0x214); + map.insert(std::any::TypeId::of::(), TPM_PT_map); + + let mut TPM_PT_PCR_map: HashMap<&'static str, u64> = HashMap::new(); + TPM_PT_PCR_map.insert("FIRST", 0x0); + TPM_PT_PCR_map.insert("SAVE", 0x0); + TPM_PT_PCR_map.insert("EXTEND_L0", 0x1); + TPM_PT_PCR_map.insert("RESET_L0", 0x2); + TPM_PT_PCR_map.insert("EXTEND_L1", 0x3); + TPM_PT_PCR_map.insert("RESET_L1", 0x4); + TPM_PT_PCR_map.insert("EXTEND_L2", 0x5); + TPM_PT_PCR_map.insert("RESET_L2", 0x6); + TPM_PT_PCR_map.insert("EXTEND_L3", 0x7); + TPM_PT_PCR_map.insert("RESET_L3", 0x8); + TPM_PT_PCR_map.insert("EXTEND_L4", 0x9); + TPM_PT_PCR_map.insert("RESET_L4", 0xA); + TPM_PT_PCR_map.insert("NO_INCREMENT", 0x11); + TPM_PT_PCR_map.insert("DRTM_RESET", 0x12); + TPM_PT_PCR_map.insert("POLICY", 0x13); + TPM_PT_PCR_map.insert("AUTH", 0x14); + TPM_PT_PCR_map.insert("LAST", 0x14); + map.insert(std::any::TypeId::of::(), TPM_PT_PCR_map); + + let mut TPM_PS_map: HashMap<&'static str, u64> = HashMap::new(); + TPM_PS_map.insert("MAIN", 0x0); + TPM_PS_map.insert("PC", 0x1); + TPM_PS_map.insert("PDA", 0x2); + TPM_PS_map.insert("CELL_PHONE", 0x3); + TPM_PS_map.insert("SERVER", 0x4); + TPM_PS_map.insert("PERIPHERAL", 0x5); + TPM_PS_map.insert("TSS", 0x6); + TPM_PS_map.insert("STORAGE", 0x7); + TPM_PS_map.insert("AUTHENTICATION", 0x8); + TPM_PS_map.insert("EMBEDDED", 0x9); + TPM_PS_map.insert("HARDCOPY", 0xA); + TPM_PS_map.insert("INFRASTRUCTURE", 0xB); + TPM_PS_map.insert("VIRTUALIZATION", 0xC); + TPM_PS_map.insert("TNC", 0xD); + TPM_PS_map.insert("MULTI_TENANT", 0xE); + TPM_PS_map.insert("TC", 0xF); + map.insert(std::any::TypeId::of::(), TPM_PS_map); + + let mut TPM_HT_map: HashMap<&'static str, u64> = HashMap::new(); + TPM_HT_map.insert("PCR", 0x0); + TPM_HT_map.insert("NV_INDEX", 0x1); + TPM_HT_map.insert("HMAC_SESSION", 0x2); + TPM_HT_map.insert("LOADED_SESSION", 0x2); + TPM_HT_map.insert("POLICY_SESSION", 0x3); + TPM_HT_map.insert("SAVED_SESSION", 0x3); + TPM_HT_map.insert("PERMANENT", 0x40); + TPM_HT_map.insert("TRANSIENT", 0x80); + TPM_HT_map.insert("PERSISTENT", 0x81); + TPM_HT_map.insert("AC", 0x90); + map.insert(std::any::TypeId::of::(), TPM_HT_map); + + let mut TPM_RH_map: HashMap<&'static str, u64> = HashMap::new(); + TPM_RH_map.insert("FIRST", 0x40000000); + TPM_RH_map.insert("SRK", 0x40000000); + TPM_RH_map.insert("OWNER", 0x40000001); + TPM_RH_map.insert("REVOKE", 0x40000002); + TPM_RH_map.insert("TRANSPORT", 0x40000003); + TPM_RH_map.insert("OPERATOR", 0x40000004); + TPM_RH_map.insert("ADMIN", 0x40000005); + TPM_RH_map.insert("EK", 0x40000006); + TPM_RH_map.insert("NULL", 0x40000007); + TPM_RH_map.insert("UNASSIGNED", 0x40000008); + TPM_RH_map.insert("PW", 0x40000009); + TPM_RH_map.insert("LOCKOUT", 0x4000000A); + TPM_RH_map.insert("ENDORSEMENT", 0x4000000B); + TPM_RH_map.insert("PLATFORM", 0x4000000C); + TPM_RH_map.insert("PLATFORM_NV", 0x4000000D); + TPM_RH_map.insert("AUTH_00", 0x40000010); + TPM_RH_map.insert("AUTH_FF", 0x4000010F); + TPM_RH_map.insert("ACT_0", 0x40000110); + TPM_RH_map.insert("ACT_F", 0x4000011F); + TPM_RH_map.insert("LAST", 0x4000011F); + map.insert(std::any::TypeId::of::(), TPM_RH_map); + + let mut TPM_NT_map: HashMap<&'static str, u64> = HashMap::new(); + TPM_NT_map.insert("ORDINARY", 0x0); + TPM_NT_map.insert("COUNTER", 0x1); + TPM_NT_map.insert("BITS", 0x2); + TPM_NT_map.insert("EXTEND", 0x4); + TPM_NT_map.insert("PIN_FAIL", 0x8); + TPM_NT_map.insert("PIN_PASS", 0x9); + map.insert(std::any::TypeId::of::(), TPM_NT_map); + + let mut TPM_AT_map: HashMap<&'static str, u64> = HashMap::new(); + TPM_AT_map.insert("ANY", 0x0); + TPM_AT_map.insert("ERROR", 0x1); + TPM_AT_map.insert("PV1", 0x2); + TPM_AT_map.insert("VEND", 0x80000000); + map.insert(std::any::TypeId::of::(), TPM_AT_map); + + let mut TPM_AE_map: HashMap<&'static str, u64> = HashMap::new(); + TPM_AE_map.insert("NONE", 0x0); + map.insert(std::any::TypeId::of::(), TPM_AE_map); + + let mut PLATFORM_map: HashMap<&'static str, u64> = HashMap::new(); + PLATFORM_map.insert("FAMILY", 0x322E3000); + PLATFORM_map.insert("LEVEL", 0x0); + PLATFORM_map.insert("VERSION", 0xA2); + PLATFORM_map.insert("YEAR", 0x7E3); + PLATFORM_map.insert("DAY_OF_YEAR", 0x168); + map.insert(std::any::TypeId::of::(), PLATFORM_map); + + let mut Implementation_map: HashMap<&'static str, u64> = HashMap::new(); + Implementation_map.insert("FIELD_UPGRADE_IMPLEMENTED", 0x0); + Implementation_map.insert("HASH_LIB", 0x1); + Implementation_map.insert("SYM_LIB", 0x1); + Implementation_map.insert("MATH_LIB", 0x1); + Implementation_map.insert("IMPLEMENTATION_PCR", 0x18); + Implementation_map.insert("PCR_SELECT_MAX", 0x3); + Implementation_map.insert("PLATFORM_PCR", 0x18); + Implementation_map.insert("PCR_SELECT_MIN", 0x3); + Implementation_map.insert("DRTM_PCR", 0x11); + Implementation_map.insert("HCRTM_PCR", 0x0); + Implementation_map.insert("NUM_LOCALITIES", 0x5); + Implementation_map.insert("MAX_HANDLE_NUM", 0x3); + Implementation_map.insert("MAX_ACTIVE_SESSIONS", 0x40); + Implementation_map.insert("MAX_LOADED_SESSIONS", 0x3); + Implementation_map.insert("MAX_SESSION_NUM", 0x3); + Implementation_map.insert("MAX_LOADED_OBJECTS", 0x3); + Implementation_map.insert("MIN_EVICT_OBJECTS", 0x2); + Implementation_map.insert("NUM_POLICY_PCR_GROUP", 0x1); + Implementation_map.insert("NUM_AUTHVALUE_PCR_GROUP", 0x1); + Implementation_map.insert("MAX_CONTEXT_SIZE", 0x4F0); + Implementation_map.insert("MAX_DIGEST_BUFFER", 0x400); + Implementation_map.insert("MAX_NV_INDEX_SIZE", 0x800); + Implementation_map.insert("MAX_NV_BUFFER_SIZE", 0x400); + Implementation_map.insert("MAX_CAP_BUFFER", 0x400); + Implementation_map.insert("NV_MEMORY_SIZE", 0x4000); + Implementation_map.insert("MIN_COUNTER_INDICES", 0x8); + Implementation_map.insert("NUM_STATIC_PCR", 0x10); + Implementation_map.insert("MAX_ALG_LIST_SIZE", 0x40); + Implementation_map.insert("PRIMARY_SEED_SIZE", 0x20); + Implementation_map.insert("CONTEXT_ENCRYPT_ALGORITHM", 0x6); + Implementation_map.insert("NV_CLOCK_UPDATE_INTERVAL", 0xC); + Implementation_map.insert("NUM_POLICY_PCR", 0x1); + Implementation_map.insert("MAX_COMMAND_SIZE", 0x1000); + Implementation_map.insert("MAX_RESPONSE_SIZE", 0x1000); + Implementation_map.insert("ORDERLY_BITS", 0x8); + Implementation_map.insert("MAX_SYM_DATA", 0x80); + Implementation_map.insert("MAX_RNG_ENTROPY_SIZE", 0x40); + Implementation_map.insert("RAM_INDEX_SPACE", 0x200); + Implementation_map.insert("RSA_DEFAULT_PUBLIC_EXPONENT", 0x10001); + Implementation_map.insert("ENABLE_PCR_NO_INCREMENT", 0x1); + Implementation_map.insert("CRT_FORMAT_RSA", 0x1); + Implementation_map.insert("VENDOR_COMMAND_COUNT", 0x0); + Implementation_map.insert("MAX_VENDOR_BUFFER_SIZE", 0x400); + Implementation_map.insert("MAX_DERIVATION_BITS", 0x2000); + Implementation_map.insert("RSA_MAX_PRIME", 0x80); + Implementation_map.insert("RSA_PRIVATE_SIZE", 0x280); + Implementation_map.insert("SIZE_OF_X509_SERIAL_NUMBER", 0x14); + Implementation_map.insert("PRIVATE_VENDOR_SPECIFIC_BYTES", 0x280); + map.insert(std::any::TypeId::of::(), Implementation_map); + + let mut TPM_HC_map: HashMap<&'static str, u64> = HashMap::new(); + TPM_HC_map.insert("HR_HANDLE_MASK", 0xFFFFFF); + TPM_HC_map.insert("HR_RANGE_MASK", 0xFF000000); + TPM_HC_map.insert("HR_SHIFT", 0x18); + TPM_HC_map.insert("HR_PCR", 0x0); + TPM_HC_map.insert("HR_HMAC_SESSION", 0x2000000); + TPM_HC_map.insert("HR_POLICY_SESSION", 0x3000000); + TPM_HC_map.insert("HR_TRANSIENT", 0x80000000); + TPM_HC_map.insert("HR_PERSISTENT", 0x81000000); + TPM_HC_map.insert("HR_NV_INDEX", 0x1000000); + TPM_HC_map.insert("HR_PERMANENT", 0x40000000); + TPM_HC_map.insert("PCR_FIRST", 0x0); + TPM_HC_map.insert("PCR_LAST", 0x17); + TPM_HC_map.insert("HMAC_SESSION_FIRST", 0x2000000); + TPM_HC_map.insert("HMAC_SESSION_LAST", 0x200003F); + TPM_HC_map.insert("LOADED_SESSION_FIRST", 0x2000000); + TPM_HC_map.insert("LOADED_SESSION_LAST", 0x200003F); + TPM_HC_map.insert("POLICY_SESSION_FIRST", 0x3000000); + TPM_HC_map.insert("POLICY_SESSION_LAST", 0x300003F); + TPM_HC_map.insert("TRANSIENT_FIRST", 0x80000000); + TPM_HC_map.insert("ACTIVE_SESSION_FIRST", 0x3000000); + TPM_HC_map.insert("ACTIVE_SESSION_LAST", 0x300003F); + TPM_HC_map.insert("TRANSIENT_LAST", 0x80000002); + TPM_HC_map.insert("PERSISTENT_FIRST", 0x81000000); + TPM_HC_map.insert("PERSISTENT_LAST", 0x81FFFFFF); + TPM_HC_map.insert("PLATFORM_PERSISTENT", 0x81800000); + TPM_HC_map.insert("NV_INDEX_FIRST", 0x1000000); + TPM_HC_map.insert("NV_INDEX_LAST", 0x1FFFFFF); + TPM_HC_map.insert("PERMANENT_FIRST", 0x40000000); + TPM_HC_map.insert("PERMANENT_LAST", 0x4000011F); + TPM_HC_map.insert("HR_NV_AC", 0x1D00000); + TPM_HC_map.insert("NV_AC_FIRST", 0x1D00000); + TPM_HC_map.insert("NV_AC_LAST", 0x1D0FFFF); + TPM_HC_map.insert("HR_AC", 0x90000000); + TPM_HC_map.insert("AC_FIRST", 0x90000000); + TPM_HC_map.insert("AC_LAST", 0x9000FFFF); + map.insert(std::any::TypeId::of::(), TPM_HC_map); + + let mut TPMA_ALGORITHM_map: HashMap<&'static str, u64> = HashMap::new(); + TPMA_ALGORITHM_map.insert("asymmetric", 0x1); + TPMA_ALGORITHM_map.insert("symmetric", 0x2); + TPMA_ALGORITHM_map.insert("hash", 0x4); + TPMA_ALGORITHM_map.insert("object", 0x8); + TPMA_ALGORITHM_map.insert("signing", 0x100); + TPMA_ALGORITHM_map.insert("encrypting", 0x200); + TPMA_ALGORITHM_map.insert("method", 0x400); + map.insert(std::any::TypeId::of::(), TPMA_ALGORITHM_map); + + let mut TPMA_OBJECT_map: HashMap<&'static str, u64> = HashMap::new(); + TPMA_OBJECT_map.insert("fixedTPM", 0x2); + TPMA_OBJECT_map.insert("stClear", 0x4); + TPMA_OBJECT_map.insert("fixedParent", 0x10); + TPMA_OBJECT_map.insert("sensitiveDataOrigin", 0x20); + TPMA_OBJECT_map.insert("userWithAuth", 0x40); + TPMA_OBJECT_map.insert("adminWithPolicy", 0x80); + TPMA_OBJECT_map.insert("noDA", 0x400); + TPMA_OBJECT_map.insert("encryptedDuplication", 0x800); + TPMA_OBJECT_map.insert("restricted", 0x10000); + TPMA_OBJECT_map.insert("decrypt", 0x20000); + TPMA_OBJECT_map.insert("sign", 0x40000); + TPMA_OBJECT_map.insert("encrypt", 0x40000); + TPMA_OBJECT_map.insert("x509sign", 0x80000); + map.insert(std::any::TypeId::of::(), TPMA_OBJECT_map); + + let mut TPMA_SESSION_map: HashMap<&'static str, u64> = HashMap::new(); + TPMA_SESSION_map.insert("continueSession", 0x1); + TPMA_SESSION_map.insert("auditExclusive", 0x2); + TPMA_SESSION_map.insert("auditReset", 0x4); + TPMA_SESSION_map.insert("decrypt", 0x20); + TPMA_SESSION_map.insert("encrypt", 0x40); + TPMA_SESSION_map.insert("audit", 0x80); + map.insert(std::any::TypeId::of::(), TPMA_SESSION_map); + + let mut TPMA_LOCALITY_map: HashMap<&'static str, u64> = HashMap::new(); + TPMA_LOCALITY_map.insert("LOC_ZERO", 0x1); + TPMA_LOCALITY_map.insert("LOC_ONE", 0x2); + TPMA_LOCALITY_map.insert("LOC_TWO", 0x4); + TPMA_LOCALITY_map.insert("LOC_THREE", 0x8); + TPMA_LOCALITY_map.insert("LOC_FOUR", 0x10); + map.insert(std::any::TypeId::of::(), TPMA_LOCALITY_map); + + let mut TPMA_PERMANENT_map: HashMap<&'static str, u64> = HashMap::new(); + TPMA_PERMANENT_map.insert("ownerAuthSet", 0x1); + TPMA_PERMANENT_map.insert("endorsementAuthSet", 0x2); + TPMA_PERMANENT_map.insert("lockoutAuthSet", 0x4); + TPMA_PERMANENT_map.insert("disableClear", 0x100); + TPMA_PERMANENT_map.insert("inLockout", 0x200); + TPMA_PERMANENT_map.insert("tpmGeneratedEPS", 0x400); + map.insert(std::any::TypeId::of::(), TPMA_PERMANENT_map); + + let mut TPMA_STARTUP_CLEAR_map: HashMap<&'static str, u64> = HashMap::new(); + TPMA_STARTUP_CLEAR_map.insert("phEnable", 0x1); + TPMA_STARTUP_CLEAR_map.insert("shEnable", 0x2); + TPMA_STARTUP_CLEAR_map.insert("ehEnable", 0x4); + TPMA_STARTUP_CLEAR_map.insert("phEnableNV", 0x8); + TPMA_STARTUP_CLEAR_map.insert("orderly", 0x80000000); + map.insert(std::any::TypeId::of::(), TPMA_STARTUP_CLEAR_map); + + let mut TPMA_MEMORY_map: HashMap<&'static str, u64> = HashMap::new(); + TPMA_MEMORY_map.insert("sharedRAM", 0x1); + TPMA_MEMORY_map.insert("sharedNV", 0x2); + TPMA_MEMORY_map.insert("objectCopiedToRam", 0x4); + map.insert(std::any::TypeId::of::(), TPMA_MEMORY_map); + + let mut TPMA_CC_map: HashMap<&'static str, u64> = HashMap::new(); + TPMA_CC_map.insert("nv", 0x400000); + TPMA_CC_map.insert("extensive", 0x800000); + TPMA_CC_map.insert("flushed", 0x1000000); + TPMA_CC_map.insert("rHandle", 0x10000000); + TPMA_CC_map.insert("V", 0x20000000); + map.insert(std::any::TypeId::of::(), TPMA_CC_map); + + let mut TPMA_MODES_map: HashMap<&'static str, u64> = HashMap::new(); + TPMA_MODES_map.insert("FIPS_140_2", 0x1); + map.insert(std::any::TypeId::of::(), TPMA_MODES_map); + + let mut TPMA_X509_KEY_USAGE_map: HashMap<&'static str, u64> = HashMap::new(); + TPMA_X509_KEY_USAGE_map.insert("decipherOnly", 0x800000); + TPMA_X509_KEY_USAGE_map.insert("encipherOnly", 0x1000000); + TPMA_X509_KEY_USAGE_map.insert("cRLSign", 0x2000000); + TPMA_X509_KEY_USAGE_map.insert("keyCertSign", 0x4000000); + TPMA_X509_KEY_USAGE_map.insert("keyAgreement", 0x8000000); + TPMA_X509_KEY_USAGE_map.insert("dataEncipherment", 0x10000000); + TPMA_X509_KEY_USAGE_map.insert("keyEncipherment", 0x20000000); + TPMA_X509_KEY_USAGE_map.insert("nonrepudiation", 0x40000000); + TPMA_X509_KEY_USAGE_map.insert("contentCommitment", 0x40000000); + TPMA_X509_KEY_USAGE_map.insert("digitalSignature", 0x80000000); + map.insert(std::any::TypeId::of::(), TPMA_X509_KEY_USAGE_map); + + let mut TPMA_ACT_map: HashMap<&'static str, u64> = HashMap::new(); + TPMA_ACT_map.insert("signaled", 0x1); + TPMA_ACT_map.insert("preserveSignaled", 0x2); + map.insert(std::any::TypeId::of::(), TPMA_ACT_map); + + let TPM_NV_INDEX_map: HashMap<&'static str, u64> = HashMap::new(); + map.insert(std::any::TypeId::of::(), TPM_NV_INDEX_map); + + let mut TPMA_NV_map: HashMap<&'static str, u64> = HashMap::new(); + TPMA_NV_map.insert("PPWRITE", 0x1); + TPMA_NV_map.insert("OWNERWRITE", 0x2); + TPMA_NV_map.insert("AUTHWRITE", 0x4); + TPMA_NV_map.insert("POLICYWRITE", 0x8); + TPMA_NV_map.insert("ORDINARY", 0x0); + TPMA_NV_map.insert("COUNTER", 0x10); + TPMA_NV_map.insert("BITS", 0x20); + TPMA_NV_map.insert("EXTEND", 0x40); + TPMA_NV_map.insert("PIN_FAIL", 0x80); + TPMA_NV_map.insert("PIN_PASS", 0x90); + TPMA_NV_map.insert("POLICY_DELETE", 0x400); + TPMA_NV_map.insert("WRITELOCKED", 0x800); + TPMA_NV_map.insert("WRITEALL", 0x1000); + TPMA_NV_map.insert("WRITEDEFINE", 0x2000); + TPMA_NV_map.insert("WRITE_STCLEAR", 0x4000); + TPMA_NV_map.insert("GLOBALLOCK", 0x8000); + TPMA_NV_map.insert("PPREAD", 0x10000); + TPMA_NV_map.insert("OWNERREAD", 0x20000); + TPMA_NV_map.insert("AUTHREAD", 0x40000); + TPMA_NV_map.insert("POLICYREAD", 0x80000); + TPMA_NV_map.insert("NO_DA", 0x2000000); + TPMA_NV_map.insert("ORDERLY", 0x4000000); + TPMA_NV_map.insert("CLEAR_STCLEAR", 0x8000000); + TPMA_NV_map.insert("READLOCKED", 0x10000000); + TPMA_NV_map.insert("WRITTEN", 0x20000000); + TPMA_NV_map.insert("PLATFORMCREATE", 0x40000000); + TPMA_NV_map.insert("READ_STCLEAR", 0x80000000); + map.insert(std::any::TypeId::of::(), TPMA_NV_map); + + map + }; + +} + diff --git a/TssCodeGen/README.md b/TssCodeGen/README.md index 8c389b89..fcbc3c55 100644 --- a/TssCodeGen/README.md +++ b/TssCodeGen/README.md @@ -3,7 +3,7 @@ # Purpose -This is the tool that automatically (re)generates the interface part of the TPM Software Stack (TSS) implementations for all supported programming languages/frameworks ([.Net][TSS.Net], [C++][TSS.CPP], [Java][TSS.Java], [Node.js][TSS.JS], [Python][TSS.Py]) based on the TCG's [TPM 2.0 specification] documents. +This is the tool that automatically (re)generates the interface part of the TPM Software Stack (TSS) implementations for all supported programming languages/frameworks ([.Net][TSS.Net], [C++][TSS.CPP], [Rust][TSS.Rust], [Java][TSS.Java], [Node.js][TSS.JS], [Python][TSS.Py]) based on the TCG's [TPM 2.0 specification] documents. Auto-generated code includes the following components of the TPM 2.0 interface: * constants (represented as enums); @@ -18,7 +18,7 @@ Auto-generated code includes the following components of the TPM 2.0 interface: When built and run in-place from a Visual Studio with no command line options provided, the tool will pick the TPM 2.0 specification data from the [TpmSpec](./TpmSpec) directory, and update TSS for all supported languages in this repo clone. -If the tool is used from a directory different from the one used by the Visual Studio build, you may need to use command line options to specify the location of the TPM 2.0 specification documents (`-spec`) and the target TSS implementations (`-dest`). You can also specify a subset of target TSS programming languages to update using a combination of options `-dotNet`, `-cpp`, `-java`, `-node`, `-py`. +If the tool is used from a directory different from the one used by the Visual Studio build, you may need to use command line options to specify the location of the TPM 2.0 specification documents (`-spec`) and the target TSS implementations (`-dest`). You can also specify a subset of target TSS programming languages to update using a combination of options `-dotNet`, `-cpp`, `-java`, `-node`, `-py`, `-rust`. Run the tool with the `-help` option to get more detailed information about its command line options. @@ -69,7 +69,7 @@ The tool works in three phases: 3) Code generation phase. - A specialized class for each of the target program language ([CGenDotNet](./src/CGenDotNet.cs), [CGenCpp](./src/CGenCpp.cs), [CGenJava](./src/CGenJava.cs), [CGenNode](./src/CGenNode.cs), [CGenPy](./src/CGenPy.cs)) produces the code based on the AST representation. + A specialized class for each of the target program language ([CGenDotNet](./src/CGenDotNet.cs), [CGenCpp](./src/CGenCpp.cs), [CGenRust](./src/CGenRust.cs), [CGenJava](./src/CGenJava.cs), [CGenNode](./src/CGenNode.cs), [CGenPy](./src/CGenPy.cs)) produces the code based on the AST representation. ## *Abstract Syntax Tree (AST) classes* @@ -155,7 +155,7 @@ The `CodeGenBase.Generate()` method implements the same generic workflow for all * TPM union factory implementation from the collection of the `UnionMember` and realted `UnionMember` instances. - Union factory is used to instantiate the correct union member (class implementing the given union interface) based on the union type and selector (tag) value. This is necessary while unmarshaling TPM structures with fields of a union type. * Class definitions from all `TpmStruct` instances. This includes field definitions, constructors, marshaling methods (except for [TSS.Net]), and on case-by-case basis additional interface methods. - - The set of automatically generated methods for a few TPM 2.0 structures is extended with custom additions via .snips files ([C++](../TSS.CPP/Src/TpmExtensions.cpp.snips), [Java](../TSS.Java/src/TpmExtensions.java.snips), [Node.js](../TSS.JS/src/TpmExtensions.js.snips), [Python](../TSS.Py/src/TpmExtensions.py.snips)). Snippet files contain fragments of the code that are appended to the auto-generated classes (class declarations in the case of C++) without any additional translations. Note that [TSS.Net] does not use this mechanism, as it custmizes its auto-generated classes using *partial classes* syntax. + - The set of automatically generated methods for a few TPM 2.0 structures is extended with custom additions via .snips files ([C++](../TSS.CPP/Src/TpmExtensions.cpp.snips), [Rust](../TSS.Rust/src/tpm_extensions.rs.snips), [Java](../TSS.Java/src/TpmExtensions.java.snips), [Node.js](../TSS.JS/src/TpmExtensions.js.snips), [Python](../TSS.Py/src/TpmExtensions.py.snips)). Snippet files contain fragments of the code that are appended to the auto-generated classes (class declarations in the case of C++) without any additional translations. Note that [TSS.Net] does not use this mechanism, as it custmizes its auto-generated classes using *partial classes* syntax. * TPM command definitions from the select `TpmStruct` instances representing command and response parameters. .Net code generator additionally creates a static class with marshaling metadata `CommandInformation`, and for C++ two maps for enum-to-string and string-to-enum conversions (`Enum2StrMap` and `Str2EnumMap`) are generated. @@ -166,12 +166,14 @@ Generated code is accumulated in an internal buffer and then is written out to a * [TSS.CPP] follows [TSS.JS]/[TSS.Py] in splitting the TPM data type and command *declarations* between two header files ([TpmTypes.h](../TSS.CPP/include/TpmTypes.h) and [Tpm2.h](../TSS.CPP/include/Tpm2.h)). Yet it additionally creates the third source file for the *definitions* of marshaling methods, union factory and enum names conversion maps ([TpmTypes.cpp](../TSS.CPP/Src/TpmTypes.cpp)). - Note also that in contrast to other languages the C++ output sources are not completely (re)created by the code generator, but are rather *updated* by means of replacing their sections marked by the `<>` comment with the new auto-generated code. * [TSS.Net] places all auto-generated definitions in the single source file ([X_TpmDefs.cs](../TSS.NET/TSS.NET/X_TpmDefs.cs)). +* [TSS.Rust] keeps all TPM data types in [tpm_types.rs](../TSS.Rust/src/tpm_types.rs) and TPM command definitions in [tpm2.rs](../TSS.Rust/src/tpm2.rs), similar to [TSS.JS]/[TSS.Py]. Rust unions are represented as enums with tuple variants. * Java keeps each definition in its own [separate source file](../TSS.Java/src/tss/tpm), plus [Tpm.java](../TSS.Java/src/tss/Tpm.java) for TPM command definitions. [TSS.Net]: ../TSS.NET [TSS.CPP]: ../TSS.CPP +[TSS.Rust]: ../TSS.Rust [TSS.Java]: ../TSS.Java [TSS.JS]: ../TSS.JS [TSS.Py]: ../TSS.Py diff --git a/TssCodeGen/src/CGenJava.cs b/TssCodeGen/src/CGenJava.cs index d04628f8..8a6b822a 100644 --- a/TssCodeGen/src/CGenJava.cs +++ b/TssCodeGen/src/CGenJava.cs @@ -69,7 +69,7 @@ internal static bool ConflictingEnumMember(string name, string typeName) /// Constants and bitfields are represented as classes derived /// from TpmEnum, and TpmAttribute correspondingly in Java - void GenEnum(TpmType e, List elements, int wireSize) + void GenEnum(TpmType e, List elements, long wireSize) { needsUtil = true; // Collection needs java.util.* diff --git a/TssCodeGen/src/CGenRust.cs b/TssCodeGen/src/CGenRust.cs new file mode 100644 index 00000000..7c681bdf --- /dev/null +++ b/TssCodeGen/src/CGenRust.cs @@ -0,0 +1,1064 @@ +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See the LICENSE file in the project root for full license information. + */ + +using System; +using System.Diagnostics; +using System.Collections.Generic; +using System.Linq; +using System.Text.RegularExpressions; + +namespace CodeGen +{ + /// Rust TSS code generator + internal class CGenRust : CodeGenBase + { + static readonly (string, string)[] TpmStructureFunctions = new (string, string)[] { + ("serialize", "(&self, buffer: &mut TpmBuffer)"), + ("deserialize", "(&mut self, buffer: &mut TpmBuffer)"), + ("fromTpm", "(&self, buffer: &mut TpmBuffer)"), + ("fromBytes", "(&mut self, buffer: &mut Vec)"), + }; + + // Maps enum type to a map of enumerator names to values + Dictionary> EnumMap; + + public CGenRust(string rootDir) : base(rootDir, @"src\tpm_extensions.rs.snips") { } + + internal override void Generate() + { + EnumMap = new Dictionary>(); + + GenerateTpmTypesRs(); + UpdateExistingSource(@"src\tpm_types.rs"); + + GenerateTpmCommandPrototypes(); + UpdateExistingSource(@"src\tpm2.rs"); + } + + /// Determines whether this struct is represented as a type alias in Rust + static bool IsTypedefStruct(TpmStruct s) + { + return s.DerivedFrom != null && s.ContainingUnions.Count == 0; + } + + static string ParamForField(StructField f) { + if (f.IsArray() || !f.IsValueType()) + { + return $"&{TransType(f)}"; + } + else + { + return TransType(f); + } + } + + static string TransType(StructField f) + { + string typeName = f.TypeName; + + // Handle union object types + if (f.MarshalType == MarshalType.UnionObject) + { + return $"Option<{ToRustName(typeName)}>"; + } + + // Handle types with generics (containers like Vec, Option, etc.) + if (typeName.Contains("<") && typeName.Contains(">")) + { + int openBracketIndex = typeName.IndexOf('<'); + int closeBracketIndex = typeName.LastIndexOf('>'); + + string baseType = typeName.Substring(0, openBracketIndex); + string genericParams = typeName.Substring(openBracketIndex + 1, closeBracketIndex - openBracketIndex - 1); + + return $"{baseType}<{ToRustName(genericParams)}>"; + } + + // Standard type conversion + return ToRustName(typeName); + } + + string GetCommandReturnType(CommandFlavor gen, TpmStruct resp, string methodName, + out string returnFieldName) + { + returnFieldName = null; + if (gen == CommandFlavor.AsyncCommand) + return "Result<(), TpmError>"; + + string returnType = "Result<(), TpmError>"; + var respFields = resp.NonTagFields; + if (ForceJustOneReturnParm.Contains(methodName)) + { + respFields = respFields.Take(1).ToArray(); + } + + if (respFields.Count() > 1) + return $"Result<{resp.Name}, TpmError>"; + + if (respFields.Count() == 1) + { + returnFieldName = respFields[0].Name; + returnType = $"Result<{TransType(respFields[0])}, TpmError>"; + } + return returnType; + } + + void GenerateTpmTypesRs() + { + // Generate the enums, bitfields, unions, and structs + foreach (var e in TpmTypes.Get()) + GenEnum(e); + + foreach (var bf in TpmTypes.Get()) + GenBitfield(bf); + + foreach (var u in TpmTypes.Get()) + GenUnion(u); + + foreach (var s in TpmTypes.Get()) + GenStructDecl(s); + + // Generate the enum maps + GenEnumMap(); + } + + /// + /// Checks if an enum has duplicate values among its elements + /// + private bool HasDuplicateValues(List elements) + { + HashSet values = new HashSet(); + foreach (var element in elements) + { + if (!values.Add(element.NumericValue)) + { + return true; // Found a duplicate + } + } + return false; + } + + void GenEnum(TpmType e, List elements) + { + WriteComment(e); + + var enumVals = new Dictionary(); + + var enumUnderlyingType = e.GetFinalUnderlyingType(); + var sizeInBits = enumUnderlyingType.GetSize() * 8; + var enumUnderlyingTypeName = enumUnderlyingType.Name; + var enumUnderlyingTypeSigned = enumUnderlyingTypeName.StartsWith("i") ? true : false; + + // Generate a newtype struct with constants for enums with duplicates + Write($"#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]"); + Write($"pub struct {e.Name}(pub {enumUnderlyingTypeName});"); + Write(""); + + // Generate constants for each enum value + TabIn($"impl {e.Name} {{"); + + foreach (var elt in elements) + { + WriteComment(AsSummary(elt.Comment)); + var enumValue = ToRustEnumValue(elt, sizeInBits, enumUnderlyingTypeSigned); + var enumHexValue = enumUnderlyingTypeSigned ? enumValue.ToString() : ToHex(enumValue); + var originalValueComment = ""; + if (enumHexValue != elt.Value) + { + originalValueComment = $" // Original value: {elt.Value}"; + } + + Write($"pub const {elt.Name}: Self = Self({enumHexValue});{originalValueComment}"); + + // Do not include artificially added named constants into the name conversion maps + if (elt.SpecName != null) + enumVals[elt.Name] = e is TpmEnum ? ToHex(elt.NumericValue) : elt.Value; + } + + // Add TryFrom implementation for the newtype struct + Write(""); + TabIn($"pub fn try_from(value: {enumUnderlyingTypeName}) -> Result {{"); + TabIn("match value {"); + foreach (var elt in elements.GroupBy(x => x.NumericValue).Select(g => g.Last())) + { + var enumValue = ToRustEnumValue(elt, sizeInBits, enumUnderlyingTypeSigned); + + // Only include first occurrence of each value to avoid duplicate match arms + Write($"{enumValue} => Ok(Self::{elt.Name}), // Original value: {elt.Value}"); + } + Write("_ => Err(TpmError::InvalidEnumValue),"); + TabOut("}", false); + TabOut("}", false); + + TabOut("}"); + Write(""); + + // Implement TpmEnum trait for the struct + TabIn($"impl TpmEnum<{enumUnderlyingTypeName}> for {e.Name} {{"); + TabIn($"fn get_value(&self) -> {enumUnderlyingTypeName} {{"); + Write("self.0.into()"); + TabOut("}"); + TabIn("fn try_from_trait(value: u64) -> Result where Self: Sized {"); + Write($"{e.Name}::try_from(value as {enumUnderlyingTypeName})"); + TabOut("}"); + TabIn("fn new_from_trait(value: u64) -> Result where Self: Sized {"); + Write($"Ok({e.Name}(value as {enumUnderlyingTypeName}))"); + TabOut("}", false); + TabOut("}"); + Write(""); + + // Add numeric conversions + TabIn($"impl From<{e.Name}> for u{sizeInBits} {{"); + TabIn($"fn from(value: {e.Name}) -> Self {{"); + Write($"value.0 as u{sizeInBits}"); + TabOut("}", false); + TabOut("}"); + Write(""); + + TabIn($"impl From<{e.Name}> for i{sizeInBits} {{"); + TabIn($"fn from(value: {e.Name}) -> Self {{"); + Write($"value.0 as i{sizeInBits}"); + TabOut("}", false); + TabOut("}"); + Write(""); + + // Implement Display trait + TabIn($"impl fmt::Display for {e.Name} {{"); + TabIn("fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {"); + TabIn("match self.0 {"); + + // Since several enum variants can map to the same value, we need to group them and only print the last + // one in the match statement (the last is the most updated one) + var elementsToValues = elements.GroupBy(element => ToRustEnumValue(element, sizeInBits, enumUnderlyingTypeSigned)) + .Select(variants => (variants.Key, variants.Last().Name)); + foreach (var elementToValue in elementsToValues) + { + Write($"{elementToValue.Key} => write!(f, \"{elementToValue.Name}\"),"); + } + + Write($"_ => write!(f, \"{{}}\", enum_to_str(self.0 as u64, std::any::TypeId::of::<{e.Name}>())),"); + TabOut("}", false); + TabOut("}", false); + TabOut("}"); + Write(""); + + EnumMap[e.Name] = enumVals; + } + + void GenEnum(TpmEnum e) + { + GenEnum(e, e.Members); + } + + void GenBitfield(TpmBitfield bf) + { + var bitfieldElements = GetBifieldElements(bf); + // Generate the enum with constants approach + GenEnum(bf, bitfieldElements); + + // Add bitwise operations for flags using the newtype pattern + TabIn($"impl std::ops::BitOr for {bf.Name} {{"); + Write("type Output = Self;"); + Write(""); + TabIn("fn bitor(self, rhs: Self) -> Self::Output {"); + Write($"Self(self.0 | rhs.0)"); + TabOut("}"); + TabOut("}"); + Write(""); + + // From impl + TabIn($"impl From for {bf.Name} {{"); + TabIn($"fn from(value: u{bf.GetFinalUnderlyingType().GetSize() * 8}) -> Self {{"); + Write($"Self(value.into())"); + TabOut("}", false); + TabOut("}"); + Write(""); + + } + + void GenUnion(TpmUnion u) + { + if (!u.Implement) + return; + + var unionSelectorType = GetUnionSelectorType(u); + + WriteComment(u); + + Write($"#[derive(Clone)]"); + Write($"pub enum {u.Name} {{"); + TabIn(); + + foreach (var m in u.Members) + { + if (m.Type.IsElementary()) + { + Write($"{ToRustEnumName(m.Name)},"); + } + else + { + Write($"{ToRustEnumName(m.Name)}({m.Type.Name}),"); + } + } + + TabOut("}"); + Write(""); + + WriteComment("Union selector type"); + TabIn($"impl {u.Name} {{"); + TabIn($"pub fn GetUnionSelector(&self) -> {unionSelectorType} {{"); + TabIn("match self {"); + foreach (var m in u.Members) + { + string memberName = ToRustEnumName(m.Name); + if (m.Type.IsElementary()) + { + Write($"Self::{memberName} => {m.SelectorValue.QualifiedName}, "); + } + else + { + Write($"Self::{memberName}(_) => {m.Type.Name}::GetUnionSelector(),"); + } + } + TabOut("}", false); + TabOut("}"); + + TabIn($"pub fn create(selector: {unionSelectorType}) -> Result, TpmError> {{"); + TabIn("match selector {"); + foreach (var m in u.Members) + { + string memberName = ToRustEnumName(m.Name); + if (m.Type.IsElementary()) + { + Write($"{m.SelectorValue.QualifiedName} => Ok(None),"); + } + else + { + Write($"{m.SelectorValue.QualifiedName} => Ok(Some(Self::{memberName}({m.Type.Name}::default()))),"); + } + + } + Write("_ => Err(TpmError::InvalidUnion),"); + + TabOut("}", false); + TabOut("}", false); + + TabOut("}"); + + // Implement Debug trait + TabIn($"impl fmt::Debug for {u.Name} {{"); + TabIn("fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {"); + TabIn("match self {"); + foreach (var m in u.Members) + { + string memberName = ToRustEnumName(m.Name); + if (m.Type.IsElementary()) + { + Write($"Self::{memberName} => write!(f, \"{u.Name}::{memberName}\"),"); + } + else + { + Write($"Self::{memberName}(inner) => write!(f, \"{u.Name}::{memberName}({{:?}})\", inner),"); + } + } + TabOut("}", false); + TabOut("}", false); + TabOut("}", false); + + // Marshaling methods + TabIn($"impl TpmStructure for {u.Name} {{"); + + foreach (var functionNameAndParams in TpmStructureFunctions) + { + TabIn("fn " + functionNameAndParams.Item1 + functionNameAndParams.Item2 + " -> Result<(), TpmError> {"); + TabIn("match self {"); + foreach (var m in u.Members) + { + string memberName = ToRustEnumName(m.Name); + if (m.Type.IsElementary()) + { + Write($"Self::{memberName} => Ok(()),"); + } + else + { + Write($"Self::{memberName}(inner) => inner.{functionNameAndParams.Item1}(buffer),"); + } + } + TabOut("}", false); + TabOut("}"); + } + + TabOut("}"); + + TabIn($"impl TpmMarshaller for {u.Name} {{"); + var tpmMarshallerFunctions = new (string, string)[] { + ("toTpm", "(&self, buffer: &mut TpmBuffer)"), + ("initFromTpm", "(&mut self, buffer: &mut TpmBuffer)"), + }; + + foreach (var functionNameAndParams in tpmMarshallerFunctions) + { + TabIn("fn " + functionNameAndParams.Item1 + functionNameAndParams.Item2 + " -> Result<(), TpmError> {"); + TabIn("match self {"); + foreach (var m in u.Members) + { + string memberName = ToRustEnumName(m.Name); + if (m.Type.IsElementary()) + { + Write($"Self::{memberName} => Ok(()),"); + } + else + { + Write($"Self::{memberName}(inner) => inner.{functionNameAndParams.Item1}(buffer),"); + } + } + TabOut("}", false); + TabOut("}"); + } + + TabOut("}"); + + Write(""); + } + + void GenGetUnionSelector(TpmStruct s) + { + string selType = GetUnionMemberSelectorInfo(s, out string selVal); + if (selType == null) + { + return; + } + + TabIn($"fn GetUnionSelector() -> {selType} {{"); + Write($"{selVal}"); + TabOut("}", false); + } + + void GenStructDecl(TpmStruct s) + { + string structName = s.Name; + + if (IsTypedefStruct(s)) + { + Debug.Assert(s.Fields.Count == 0); + WriteComment(s); + Write($"pub type {structName} = {s.DerivedFrom.Name};"); + Write(""); + return; + } + + WriteComment(s); + Write($"#[derive(Debug, Clone, Derivative)]"); + Write("#[derivative(Default)]"); + Write($"pub struct {structName} {{"); + TabIn(); + + GenFields(s); + + TabOut("}"); + Write(""); + + // Implement struct methods + TabIn($"impl {structName} {{"); + + // Constructor + if (!s.Info.IsResponse() && s.NonTagFields.Count() > 0) + { + Write("/// Creates a new instance with the specified values"); + Write("pub fn new("); + TabIn(); + + GenConstructorFieldsDecl(s); + + Write($") -> Self {{"); + TabIn("Self {"); + + GenConstructorFieldsInit(s); + + Write("..Default::default()"); + + TabOut("}", false); + TabOut("}", false); + Write(""); + } + + GenGetUnionSelector(s); + + TabOut("}"); + + GenTpmStructureImplementation(s); + + GenTpmMarshallerImplementation(s); + + GenTpmCmdStructureImplementation(s); + + Write(""); + } + + // Generates the constructor fields initialization, supporting "derived" structs by containing the same fields + void GenConstructorFieldsInit(TpmStruct s) { + if (s.DerivedFrom != null) + { + GenConstructorFieldsInit(s.DerivedFrom); + } + + foreach (var f in s.NonTagFields) + { + if (f.MarshalType == MarshalType.ConstantValue || f.MarshalType == MarshalType.UnionSelector) + continue; + + var fieldName = ToRustName(f.Name); + Write($"{fieldName}: {fieldName}.clone(),"); + } + } + + // Generates the constructor fields declaration, supporting "derived" structs by containing the same fields + void GenConstructorFieldsDecl(TpmStruct s) { + if (s.DerivedFrom != null) { + GenConstructorFieldsDecl(s.DerivedFrom); + } + + foreach (var f in s.NonTagFields) + { + if (f.MarshalType == MarshalType.ConstantValue || f.MarshalType == MarshalType.UnionSelector) + continue; + + Write($"{ToRustName(f.Name)}: {ParamForField(f)},"); + } + } + + // Generates the struct's fields, supporting "derived" structs by containing the same fields + void GenFields(TpmStruct s) { + var fieldsToInit = s.NonDefaultInitFields.Select(f => f.Name).ToHashSet(); + + if (s.DerivedFrom != null) { + GenFields(s.DerivedFrom); + } + + // Fields + foreach (var f in s.NonSizeFields) + { + if (f.MarshalType == MarshalType.ConstantValue) + // No member field for a constant tag + continue; + + WriteComment(f); + if (f.MarshalType == MarshalType.UnionSelector) + { + // Selectors are handled through methods in Rust + continue; + } + + if (fieldsToInit.Contains(f.Name)) + { + Write($"#[derivative(Default(value=\"{f.GetInitVal()}\"))]"); + } + Write($"pub {ToRustName(f.Name)}: {TransType(f)},"); + } + + InsertSnip(s.Name); + } + + void GenTpmStructureImplementation(TpmStruct s) + { + // Marshaling methods + TabIn($"impl TpmStructure for {s.Name} {{"); + + TabIn("fn fromTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> {"); + Write($"buffer.createObj::<{s.Name}>()?;"); + Write("Ok(())"); + TabOut("}"); + + TabIn("fn fromBytes(&mut self, buffer: &mut Vec) -> Result<(), TpmError> {"); + Write("let mut tpm_buffer = TpmBuffer::from(buffer);"); + Write($"self.initFromTpm(&mut tpm_buffer)"); + TabOut("}"); + + GenStructMarshalingImpl(s); + + TabOut("}"); + } + + void GenTpmMarshallerImplementation(TpmStruct s) + { + // Marshaling methods + TabIn($"impl TpmMarshaller for {s.Name} {{"); + + Write("/// Serialize this structure to a TPM buffer"); + TabIn("fn toTpm(&self, buffer: &mut TpmBuffer) -> Result<(), TpmError> {"); + Write("self.serialize(buffer)"); + TabOut("}"); + Write(""); + + Write("/// Deserialize this structure from a TPM buffer"); + TabIn("fn initFromTpm(&mut self, buffer: &mut TpmBuffer) -> Result<(), TpmError> {"); + Write("self.deserialize(buffer)"); + TabOut("}"); + + TabOut("}"); + } + + void GenTpmCmdStructureImplementation(TpmStruct s) + { + var info = s.IsCmdStruct() ? s.Info as CmdStructInfo : null; + + if (info == null) + { + return; + } + + TabIn($"impl CmdStructure for {s.Name} {{"); + + Write($"fn num_handles(&self) -> u16 {{ {info.NumHandles} }}"); + Write(""); + + if (info.SessEncSizeLen != 0) + { + Debug.Assert(info.SessEncValLen != 0); + Write($"fn sess_enc_info(&self) -> SessEncInfo {{ SessEncInfo {{ size_len: {info.SessEncSizeLen}, val_len: {info.SessEncValLen} }} }}"); + } + + TabOut("}"); + + if (info.IsRequest()) + { + GenReqStructureImplementation(s, info); + } + else + { + GenRespStructureImplementation(s, info); + } + } + + private void GenRespStructureImplementation(TpmStruct s, CmdStructInfo info) + { + TabIn($"impl RespStructure for {s.Name} {{"); + + if (info.NumHandles == 0) + { + Write($"fn get_handle(&self) -> TPM_HANDLE {{ TPM_HANDLE::default() }}"); + Write(""); + Write($"fn set_handle(&mut self, _handle: &TPM_HANDLE) {{ }}"); + } + else + { + // Per TPM spec, handles are always the first fields in a command/response struct, + // and Fields is guaranteed non-empty when NumHandles > 0. + Write($"fn get_handle(&self) -> TPM_HANDLE {{ self.{s.Fields[0].Name}.clone() }}"); + Write(""); + Write($"fn set_handle(&mut self, handle: &TPM_HANDLE) {{ self.{s.Fields[0].Name} = handle.clone(); }}"); + } + + // If the response struct has a "name" field, override get_resp_name() + var nameField = s.NonTagFields.FirstOrDefault(f => f.Name == "name"); + if (nameField != null) + { + Write(""); + Write($"fn get_resp_name(&self) -> Vec {{ self.name.clone() }}"); + } + + TabOut("}"); + } + + private void GenReqStructureImplementation(TpmStruct s, CmdStructInfo info) + { + string handles = string.Join(", ", s.Fields.Take(info.NumHandles).Select(f => "self." + f.Name + ".clone()")); + + TabIn($"impl ReqStructure for {s.Name} {{"); + + Write($"fn num_auth_handles(&self) -> u16 {{ {info.NumAuthHandles} }}"); + Write(""); + Write($"fn get_handles(&self) -> Vec {{ vec![{handles}] }}"); + + TabOut("}"); + } + + void GenerateTpmCommandPrototypes() + { + var commands = TpmTypes.Get().Where(s => s.Info.IsRequest()); + + TabIn("impl Tpm2 {"); + + foreach (TpmStruct s in commands) + GenCommand(s, CommandFlavor.Synch); + + TabOut("}"); + Write(""); + + Write("/// Asynchronous TPM2 command methods"); + TabIn("pub struct AsyncMethods<'a> {"); + Write("tpm: &'a mut Tpm2,"); + TabOut("}"); + Write(""); + + TabIn("impl<'a> AsyncMethods<'a> {"); + Write(""); + + foreach (TpmStruct s in commands) + GenCommand(s, CommandFlavor.AsyncCommand); + + foreach (TpmStruct s in commands) + GenCommand(s, CommandFlavor.AsyncResponse); + + TabOut("}"); + } + + enum CommandFlavor + { + Synch, AsyncCommand, AsyncResponse + } + + void GenCommand(TpmStruct req, CommandFlavor gen) + { + var resp = GetRespStruct(req); + + string cmdName = ToRustName(GetCommandName(req)); + + if (gen == CommandFlavor.AsyncCommand) + cmdName += "_async"; + else if (gen == CommandFlavor.AsyncResponse) + cmdName += "_complete"; + + string annotation = Helpers.WrapText(AsSummary(req.Comment)) + eol; + var reqFields = new StructField[0]; + if (gen != CommandFlavor.AsyncResponse) + { + reqFields = req.NonTagFields; + foreach (var f in reqFields) + annotation += GetParamComment(f) + eol; + } + WriteComment(annotation + (GetReturnComment(resp.NonTagFields)), false); + + string returnType = GetCommandReturnType(gen, resp, cmdName, out string returnFieldName); + + Write($"pub fn {cmdName}("); + TabIn(); + + Write($"&mut self,"); + + if (gen != CommandFlavor.AsyncResponse && reqFields.Length > 0) + { + foreach (var f in reqFields) + { + if (f.MarshalType == MarshalType.ConstantValue) + continue; + + Write($"{ToRustName(f.Name)}: {ParamForField(f)},"); + } + } + + TabOut($") -> {returnType} {{"); + TabIn(); + GenCommandImplementation(req, resp, reqFields, returnFieldName, gen); + TabOut("}"); + Write(""); + } + + private void GenCommandImplementation(TpmStruct req, TpmStruct resp, StructField[] reqFields, string returnFieldName, CommandFlavor gen) + { + // Create request structure + if (reqFields.Length > 0) + { + Write($"let req = {req.Name}::new("); + TabIn(); + foreach (var f in reqFields) + { + if (f.MarshalType == MarshalType.ConstantValue) + continue; + + Write($"{ToRustName(f.Name)},"); + } + TabOut(");"); + Write(""); + } + else if (gen != CommandFlavor.AsyncResponse) + { + Write($"let req = {req.Name}::default();"); + Write(""); + } + + var respFields = resp.NonTagFields; + if (gen != CommandFlavor.AsyncCommand) + { + // Create response structure (or empty if there is no response) + if (respFields.Length > 0) + { + Write($"let mut resp = {resp.Name}::default();"); + } + else + { + Write($"let mut resp = EmptyTpmResponse::default();"); + } + } + + // Call dispatch method + var cmdCode = "TPM_CC::" + ToRustName(GetCommandName(req)); + if (gen == CommandFlavor.AsyncCommand) + { + Write($"self.tpm.dispatch_command({cmdCode}, &req)?;"); + } + else if (gen == CommandFlavor.AsyncResponse) + { + Write($"self.tpm.process_response({cmdCode}, &mut resp)?;"); + } + else + { + Write($"self.dispatch({cmdCode}, req, &mut resp)?;"); + } + + if (gen == CommandFlavor.AsyncCommand) + { + Write("Ok(())"); + } + else + { + if (returnFieldName != null) + { + Write($"Ok(resp.{ToRustName(returnFieldName)})"); + } + else if (respFields.Length > 0) + { + Write("Ok(resp)"); + } + else + { + Write("Ok(())"); + } + } + } + + void GenEnumMap() + { + TabIn("lazy_static::lazy_static! {"); + Write("/// Maps enum type IDs to a map of values to string representations"); + Write("pub static ref ENUM_TO_STR_MAP: HashMap> = {"); + TabIn("let mut map = HashMap::new();"); + + foreach (var e in EnumMap) + { + var mutable = e.Value.Count > 0 ? "mut" : ""; + Write($"let {mutable} {ToRustName(e.Key)}_map: HashMap = HashMap::new();"); + foreach (var v in e.Value) + { + Write($"{ToRustName(e.Key)}_map.insert({v.Value}, \"{v.Key}\");"); + } + Write($"map.insert(std::any::TypeId::of::<{e.Key}>(), {ToRustName(e.Key)}_map);"); + Write(""); + } + + Write("map"); + TabOut("};"); + Write(""); + + Write("/// Maps enum type IDs to a map of string representations to values"); + Write("static ref STR_TO_ENUM_MAP: HashMap> = {"); + TabIn("let mut map = HashMap::new();"); + + foreach (var e in EnumMap) + { + var mutable = e.Value.Count > 0 ? "mut" : ""; + Write($"let {mutable} {ToRustName(e.Key)}_map: HashMap<&'static str, u64> = HashMap::new();"); + foreach (var v in e.Value) + { + Write($"{ToRustName(e.Key)}_map.insert(\"{v.Key}\", {v.Value});"); + } + Write($"map.insert(std::any::TypeId::of::<{e.Key}>(), {ToRustName(e.Key)}_map);"); + Write(""); + } + + Write("map"); + TabOut("};"); + TabOut("}"); + Write(""); + } + + void GenStructMarshalingImpl(TpmStruct s) + { + Write("// Implement serialization/deserialization"); + + // To TPM implementation + TabIn("fn serialize(&self, buf: &mut TpmBuffer) -> Result<(), TpmError> {"); + Write("// Serialize fields"); + var toTpmOps = GetFieldsMarshalOpsRecursive(s, GetToTpmFieldsMarshalOps); + + foreach (var op in toTpmOps) + { + Write(op + ";"); + } + Write("Ok(())"); + TabOut("}"); + Write(""); + + // From TPM implementation + TabIn("fn deserialize(&mut self, buf: &mut TpmBuffer) -> Result<(), TpmError> {"); + Write("// Deserialize fields"); + var fromTpmOps = GetFieldsMarshalOpsRecursive(s, GetFromTpmFieldsMarshalOps); + foreach (var op in fromTpmOps) + { + Write(op + ";"); + } + Write("Ok(())"); + TabOut("}"); + } + + // Recursively gets all marshal ops for the struct and its base classes (fields are contained in rust rather + // than derived) + List GetFieldsMarshalOpsRecursive(TpmStruct s, Func> getMarshalOpsFunc) { + var ops = new List(); + + if (s.DerivedFrom != null) { + ops.AddRange(GetFieldsMarshalOpsRecursive(s.DerivedFrom, getMarshalOpsFunc)); + } + + ops.AddRange(getMarshalOpsFunc(s.MarshalFields)); + + return ops; + } + + // Helper methods for Rust-specific formatting + + // Returns name as-is to keep TPM spec naming conventions consistent across all language bindings. + static string ToRustName(string name) => name; + + static long ToRustEnumValue(TpmNamedConstant element, int bits, bool signed) + { + return Convert.ToInt64(CastToNumberWithBitsAndSign(element.NumericValue, bits, signed)); + } + + // Returns name as-is to keep TPM spec naming conventions consistent across all language bindings. + static string ToRustEnumName(string name) => name; + + + string ConvertToRustInitVal(string cppInitVal) + { + // Handle common C++ init values + switch (cppInitVal) + { + case "nullptr": return "None"; + case "0": return "0"; + case "true": return "true"; + case "false": return "false"; + default: + return cppInitVal; + } + } + + protected override void WriteComment(string comment, bool wrap = true) + { + WriteComment(comment, "/// ", "/// ", "", wrap); + } + + // Helper methods for array handling and serialization + + /// + /// Determines if a field is a list (vector/collection) by checking the type name + /// + private bool IsList(StructField f) + { + if (!f.IsArray()) + return false; + + // Check if it's a dynamic array/list (not a fixed size array) + return f.Type.SpecName.StartsWith("TPML_") || + (f.SizeTagField != null && f.SizeTagField.MarshalType == MarshalType.ArrayCount); + } + + /// + /// Gets the element type name for lists/arrays + /// + private string GetElementTypeName(StructField f) + { + if (f.Type.SpecName.StartsWith("TPML_")) + { + // Extract the element type from TPML_X (list of X) + string elementTypeName = f.Type.SpecName.Substring(5); + return elementTypeName; + } + + // For regular arrays, use the base type + return f.Type.SpecName; + } + + private static object CastToNumberWithBitsAndSign(long number, int bits, bool sign) + { + if (sign) + { + // Cast to signed types + if (bits == 8) + { + return (sbyte)number; // Cast to signed byte (8 bits) + } + else if (bits == 16) + { + return (short)number; // Cast to short (16 bits) + } + else if (bits == 32) + { + return (int)number; // Cast to int (32 bits) + } + else if (bits == 64) + { + return (long)number; // Cast to long (64 bits) + } + } + else + { + // Cast to unsigned types + if (bits == 8) + { + return (byte)number; // Cast to unsigned byte (8 bits) + } + else if (bits == 16) + { + return (ushort)number; // Cast to unsigned short (16 bits) + } + else if (bits == 32) + { + return (uint)number; // Cast to unsigned int (32 bits) + } + else if (bits == 64) + { + return (ulong)number; // Cast to unsigned long (64 bits) + } + } + + throw new ArgumentException("Unsupported bit size or invalid number range"); + } + + /// + /// Gets the size of an array if it's fixed size, or 0 if dynamic + /// + private int GetArraySize(StructField f) + { + if (!f.IsArray()) + return 0; + + // If there's a size tag field, it's a dynamic array + if (f.SizeTagField != null && f.SizeTagField.MarshalType == MarshalType.ArrayCount) + return 0; + + // Try to extract size from constraints if available + if (f.MaxVal != null) + { + return (int)f.MaxVal.NumericValue; + } + + // Default size for byte arrays if nothing else specified + if (f.Type.SpecName == "BYTE") + return 64; // Common buffer size in TPM + + return 0; + } + + /// + /// Gets the base element type for use in lists/arrays + /// + private TpmType GetElementType(StructField f) + { + string elementTypeName = GetElementTypeName(f); + return TpmTypes.Lookup(elementTypeName) ?? f.Type; + } + } +} diff --git a/TssCodeGen/src/CodeGenBase.cs b/TssCodeGen/src/CodeGenBase.cs index 85a980d7..fcc873d9 100644 --- a/TssCodeGen/src/CodeGenBase.cs +++ b/TssCodeGen/src/CodeGenBase.cs @@ -41,17 +41,18 @@ protected CodeGenBase(string rootDir, string snipsFileName = null) LoadSnips(rootDir + snipsFileName); } - + internal abstract void Generate(); - static void AddBitfieldElt(List elements, string name, int val, + static void AddBitfieldElt(List elements, string name, long val, string comment = null, string oldStyleName = null, bool custom = false) { // Comment is null only for custom enumerators "XXX_BIT_OFFSET" and "XXX_BIT_LENGTH" - var nc = new TpmNamedConstant(null, custom ? null : name, null, comment); + var value = comment == null ? val.ToString() : ToHex(val); + var nc = new TpmNamedConstant(null, custom ? null : name, value, comment); nc.Name = name; - nc.Value = comment == null ? val.ToString() : ToHex(val); + nc.Value = value; nc.OldStyleName = oldStyleName ?? name; elements.Add(nc); } @@ -88,7 +89,7 @@ public static List GetBifieldElements(TpmBitfield bf) string nameBase = b.Name.Contains("_") ? TargetLang.NameToDotNet(b.Name) : b.Name; int len = b.StartBit - b.EndBit + 1; var suff = TargetLang.DotNet ? new string[] { "BitMask", "BitOffset", "BitLength" } - : new string[] { "_BIT_MASK" , "_BIT_OFFSET", "_BIT_LENGTH" }; + : new string[] { "_BIT_MASK", "_BIT_OFFSET", "_BIT_LENGTH" }; AddBitfieldElt(elements, nameBase + suff[0], ((1 << len) - 1) << b.EndBit, b.Comment, null, true); AddBitfieldElt(elements, nameBase + suff[1], b.EndBit, null, null, true); AddBitfieldElt(elements, nameBase + suff[2], len, null, null, true); @@ -106,6 +107,9 @@ public static List GetBifieldElements(TpmBitfield bf) public static List GetToTpmFieldsMarshalOps(StructField[] fields) { var marshalOps = new List(); + string fieldNamePrefix = TargetLang.Rust ? "&" : ""; + string resultSuffix = TargetLang.Rust ? "?" : ""; + foreach (StructField f in fields) { int size = f.Type.GetSize(); @@ -114,49 +118,60 @@ public static List GetToTpmFieldsMarshalOps(StructField[] fields) { case MarshalType.Normal: if (f.IsValueType()) - marshalOps.Add($"buf.write{WireNameForInt(size)}({fieldName})"); + marshalOps.Add($"buf.write{WireNameForInt(size)}({TargetLang.GetEnumValue(fieldName, f.TypeName, size)})"); else - marshalOps.Add($"{fieldName}.toTpm(buf)"); + marshalOps.Add($"{fieldName}.toTpm(buf){resultSuffix}"); if (f.Attrs.HasFlag(StructFieldAttr.TermOnNull)) - marshalOps.Add(TargetLang.If($"{fieldName} == {TpmTypes.AlgNull}") + " return"); + { + string earlyReturn = TargetLang.Rust ? " { return Ok(()) }" : " return"; + marshalOps.Add(TargetLang.If($"{fieldName} == {TpmTypes.AlgNull}") + earlyReturn); + } break; case MarshalType.ConstantValue: - marshalOps.Add($"buf.write{WireNameForInt(size)}({ConstTag(f)})"); + marshalOps.Add($"buf.write{WireNameForInt(size)}({TargetLang.GetEnumValue(ConstTag(f), f.TypeName, size)})"); break; case MarshalType.SizedStruct: Debug.Assert(f.SizeTagField != null); - marshalOps.Add($"buf.writeSizedObj({fieldName})"); + marshalOps.Add($"buf.writeSizedObj({fieldNamePrefix + fieldName}){resultSuffix}"); break; case MarshalType.EncryptedVariableLengthArray: case MarshalType.SpecialVariableLengthArray: // TPMT_HA size is tagged by its hash alg (the first field) - marshalOps.Add($"buf.writeByteBuf({fieldName})"); + marshalOps.Add($"buf.writeByteBuf({fieldNamePrefix + fieldName})"); break; case MarshalType.VariableLengthArray: var sizeTagLen = f.SizeTagField.Type.GetSize(); if (f.IsByteBuffer()) - marshalOps.Add($"buf.writeSizedByteBuf({fieldName}" + (sizeTagLen == 2 ? ")" : $", {sizeTagLen})")); + { + // Rust doesn't support default arguments for functions, so we need to pass the size tag length explicitly + bool shouldNotPassSizeTag = sizeTagLen == 2 && !TargetLang.Rust; + marshalOps.Add($"buf.writeSizedByteBuf({fieldNamePrefix}{fieldName}" + (shouldNotPassSizeTag ? ")" : $", {sizeTagLen})")); + } else if (f.IsValueType()) - marshalOps.Add($"buf.writeValArr({fieldName}, {size})"); + marshalOps.Add($"buf.writeValArr({fieldName + TargetLang.AsReference(true)}, {size})"); else - marshalOps.Add($"buf.writeObjArr({fieldName})"); + marshalOps.Add($"buf.writeObjArr({fieldName + TargetLang.AsReference(true)}){resultSuffix}"); break; case MarshalType.UnionSelector: // A trick to allow using default-constructed TPMT_SENSITIVE as an empty (non-marshaling) object string unionField = ThisMember + f.RelatedUnion.Name; if (f == fields.First()) - marshalOps.Add(TargetLang.If($"{unionField} == {TargetLang.Null}") + " return"); - marshalOps.Add($"buf.write{WireNameForInt(size)}({unionField}{TargetLang.Member}GetUnionSelector())"); + { + string earlyReturn = TargetLang.Rust ? " { return Ok(()) }" : " return"; + marshalOps.Add(TargetLang.IfNull(unionField) + earlyReturn); + } + + marshalOps.Add($"buf.write{WireNameForInt(size)}({unionField}{TargetLang.UnionMember(true)}GetUnionSelector(){TargetLang.GetUnionValue(size)})"); break; case MarshalType.UnionObject: - marshalOps.Add($"{fieldName}{TargetLang.Member}toTpm(buf)"); + marshalOps.Add($"{fieldName}{TargetLang.UnionMember(true)}toTpm(buf){resultSuffix}"); break; default: @@ -169,6 +184,8 @@ public static List GetToTpmFieldsMarshalOps(StructField[] fields) public static List GetFromTpmFieldsMarshalOps(StructField[] fields) { + string resultSuffix = TargetLang.Rust ? "?" : ""; + var marshalOps = new List(); foreach (StructField f in fields) { @@ -178,13 +195,16 @@ public static List GetFromTpmFieldsMarshalOps(StructField[] fields) { case MarshalType.Normal: if (f.IsValueType()) - marshalOps.Add($"{fieldName} = buf.read{WireNameForInt(size)}()"); + marshalOps.Add($"{fieldName} = {TargetLang.ParseEnum(f.TypeName, $"buf.read{WireNameForInt(size)}()", f.Type.GetFinalUnderlyingType().Name)}"); else - marshalOps.Add(TargetLang.Cpp ? $"{fieldName}.initFromTpm(buf)" - : $"{fieldName} = {f.TypeName}.fromTpm(buf)"); + marshalOps.Add(TargetLang.Cpp || TargetLang.Rust ? $"{fieldName}.initFromTpm(buf){resultSuffix}" + : $"{fieldName} = {f.TypeName}.fromTpm(buf){resultSuffix}"); if (f.Attrs.HasFlag(StructFieldAttr.TermOnNull)) - marshalOps.Add(TargetLang.If($"{fieldName} == {TpmTypes.AlgNull}") + " return"); + { + string earlyReturn = TargetLang.Rust ? " { return Ok(()) }" : " return"; + marshalOps.Add(TargetLang.If($"{fieldName} == {TpmTypes.AlgNull}") + earlyReturn); + } break; case MarshalType.ConstantValue: @@ -194,8 +214,9 @@ public static List GetFromTpmFieldsMarshalOps(StructField[] fields) case MarshalType.SizedStruct: Debug.Assert(f.SizeTagField != null); - marshalOps.Add(TargetLang.Cpp ? $"buf.readSizedObj({fieldName})" - : $"{fieldName} = buf.createSizedObj({TargetLang.TypeInfo(f.TypeName)})"); + marshalOps.Add(TargetLang.Cpp ? $"buf.readSizedObj({fieldName})" : + TargetLang.Rust ? $"buf.readSizedObj(&mut {fieldName})?" : + $"{fieldName} = buf.createSizedObj({TargetLang.TypeInfo(f.TypeName)})"); break; case MarshalType.EncryptedVariableLengthArray: @@ -211,26 +232,41 @@ public static List GetFromTpmFieldsMarshalOps(StructField[] fields) case MarshalType.VariableLengthArray: var sizeTagLen = f.SizeTagField.Type.GetSize(); if (f.IsByteBuffer()) - marshalOps.Add($"{fieldName} = buf.readSizedByteBuf(" + (sizeTagLen == 2 ? ")" : $"{sizeTagLen})")); + { + // Rust doesn't support default arguments for functions, so we need to pass the size tag length explicitly + bool shouldNotPassSizeTag = sizeTagLen == 2 && !TargetLang.Rust; + marshalOps.Add($"{fieldName} = buf.readSizedByteBuf(" + (shouldNotPassSizeTag ? ")" : $"{sizeTagLen})")); + } else if (f.IsValueType()) - marshalOps.Add(TargetLang.Cpp ? $"buf.readValArr({fieldName}, {f.Type.GetSize()})" - : $"{fieldName} = buf.readValArr({f.Type.GetSize()})"); + marshalOps.Add(TargetLang.Cpp ? $"buf.readValArr({fieldName}, {f.Type.GetSize()})" : + TargetLang.Rust ? $"buf.readValArr({fieldName + TargetLang.AsReference(false)}, {f.Type.GetSize()})?" : + $"{fieldName} = buf.readValArr({f.Type.GetSize()})"); else - marshalOps.Add(TargetLang.Cpp ? $"buf.readObjArr({fieldName})" + marshalOps.Add(TargetLang.Cpp || TargetLang.Rust ? $"buf.readObjArr({fieldName + TargetLang.AsReference(false)}){resultSuffix}" : $"{fieldName} = buf.readObjArr({TargetLang.TypeInfo(f.TypeName.TrimEnd('[', ']'))})"); break; case MarshalType.UnionSelector: var localVar = TargetLang.LocalVar(f.Name, f.TypeName); - marshalOps.Add($"{localVar} = " + - (f.IsValueType() ? $"buf.read{WireNameForInt(size)}()" : $"{f.TypeName}.fromTpm(buf)")); + if (f.IsValueType()) + { + marshalOps.Add($"{localVar} = {TargetLang.ParseEnum(f.TypeName, $"buf.read{WireNameForInt(size)}()", f.Type.GetFinalUnderlyingType().Name)}"); + } + else + marshalOps.Add($"{localVar} = {f.TypeName}.fromTpm(buf){resultSuffix}"); break; case MarshalType.UnionObject: - var selector = (f as UnionField).UnionSelector.Name; - marshalOps.Add(TargetLang.Cpp ? $"UnionFactory::Create({fieldName}, {selector})" - : $"{fieldName} = UnionFactory.create({TargetLang.Quote(f.TypeName)}, {selector})"); - marshalOps.Add($"{fieldName}{TargetLang.Member}initFromTpm(buf)"); + var selector = (f as UnionField).UnionSelector; + var selectorName = selector.Name; + if (TargetLang.Cpp) + marshalOps.Add($"UnionFactory::Create({fieldName}, {selectorName})"); + else if (TargetLang.Rust) + marshalOps.Add($"{fieldName} = {f.TypeName}::create(r#{selectorName})?"); + else + marshalOps.Add($"{fieldName} = UnionFactory.create({TargetLang.Quote(f.TypeName)}, {selectorName})"); + + marshalOps.Add($"{fieldName}{TargetLang.UnionMember(false)}initFromTpm(buf){resultSuffix}"); break; default: break; @@ -351,15 +387,17 @@ internal static string Separator(T elem, IEnumerable list, string sep = ", return Object.ReferenceEquals(list.Last(), elem) ? term : sep; } - internal static string ToHex(int value) + internal static string ToHex(long value) { - return "0x" + Convert.ToString(value, 16).ToUpper(); + // Cast to uint to avoid sign-extension of 32-bit values (e.g. 0x80000000) + return "0x" + Convert.ToString((uint)value, 16).ToUpper(); } - internal static string ToHex(uint value) { return ToHex((int)value); } + internal static string ToHex(ulong value) { return ToHex((long)value); } internal static string WireNameForInt(int size) { - switch(size){ + switch (size) + { case 1: return "Byte"; case 2: return "Short"; case 4: return "Int"; @@ -427,7 +465,7 @@ public static string GetUnionChoicesList(TpmType t) public static string AsSummary(string comment) { - return string.IsNullOrEmpty(comment) ? comment + return string.IsNullOrEmpty(comment) ? comment : (TargetLang.Cpp || TargetLang.DotNet) ? " " + comment + " " : comment; } @@ -519,12 +557,12 @@ protected void WriteComment(string comment, string beg, string mid, string end = if (!comment.Contains('\n')) { if (end.StartsWith("\n")) - end = end.Substring(1); + end = end.Substring(1); end = " " + end.TrimStart(' '); } comment += end; } - var lines = comment.Split(new char[] {'\n'}); + var lines = comment.Split(new char[] { '\n' }); for (int i = 0; i < lines.Length; ++i) Write(lines[i]); CommentWritten = true; @@ -552,12 +590,12 @@ protected void WriteComment(TpmNamedConstant nc) WriteComment(AsSummary(nc.Comment)); } - protected bool NewLine = true, + protected bool NewLine = true, EmptyLineWritten = false, CommentWritten = false; protected const int SpacesPerTab = 4; - protected int IndentLevel; + protected int IndentLevel; protected string CurIndent() { @@ -586,9 +624,9 @@ protected void Write(string str, bool newLine = true) NewLine = true; } - string curIndent = CurIndent(), + string curIndent = CurIndent(), indent = NewLine ? curIndent : ""; - var lines = str.Replace("\r", "").Split(new char[] {'\n'}); + var lines = str.Replace("\r", "").Split(new char[] { '\n' }); for (int i = 0; i < lines.Length; ++i) { GeneratedCode.Append(indent + lines[i]); diff --git a/TssCodeGen/src/Expression.cs b/TssCodeGen/src/Expression.cs index 024c4275..0fa963f4 100644 --- a/TssCodeGen/src/Expression.cs +++ b/TssCodeGen/src/Expression.cs @@ -16,26 +16,28 @@ class Token { } + // Uses long (64-bit) to correctly handle unsigned 32-bit TPM constants (e.g. 0x80000000) + // that would overflow a signed int. class Operand : Token { string _Value; - int? _NumValue; + long? _NumValue; public Operand (string val) { _Value = val; } - public Operand (int val) { _NumValue = val; } + public Operand (long val) { _NumValue = val; } public static implicit operator Operand (string val) { return new Operand(val); } - public static implicit operator Operand (int val) { return new Operand(val); } + public static implicit operator Operand (long val) { return new Operand(val); } public string Value { get { return _Value; } } - public int NumericValue + public long NumericValue { get { if (_NumValue == null) _NumValue = Expression.Eval(Value); - return (int)_NumValue; + return (long)_NumValue; } } } // class Operand @@ -87,7 +89,7 @@ public bool Is (OpCode op) return Op == op; } - public int Apply (int lhs, int rhs) + public long Apply (long lhs, long rhs) { switch(Op) { @@ -117,10 +119,10 @@ class Expression { public static bool IsNumber(string val) { - int numIs; - return Int32.TryParse(val, out numIs) || + long numIs; + return Int64.TryParse(val, out numIs) || val.ToLower().StartsWith("0x") && - Int32.TryParse(val.Substring(2), NumberStyles.HexNumber, + Int64.TryParse(val.Substring(2), NumberStyles.HexNumber, new NumberFormatInfo(), out numIs); } @@ -128,11 +130,11 @@ public static bool IsNumber(string val) /// the Part 2, or Vendor Specicfic part of the TPM 2.0 spec added a new constant /// value defined not in a table, but rather in a NOTE. In this case this definition /// needs to be manually added into the ImplementationConstants array. - public static int Eval(string val) + public static long Eval(string val) { if (IsNumber(val)) { - return Convert.ToInt32(val, val.ToLower().StartsWith("0x") ? 16 : 10); + return Convert.ToInt64(val, val.ToLower().StartsWith("0x") ? 16 : 10); } if (TpmTypes.ContainsConstant(val)) { @@ -193,7 +195,7 @@ public static int Eval(string val) ops.Pop().Apply(values); } Debug.Assert(values.Count == 1); - int res = values.Pop().NumericValue; + long res = values.Pop().NumericValue; return res; } diff --git a/TssCodeGen/src/TargetLang.cs b/TssCodeGen/src/TargetLang.cs index fac613ee..c1ac4819 100644 --- a/TssCodeGen/src/TargetLang.cs +++ b/TssCodeGen/src/TargetLang.cs @@ -19,7 +19,8 @@ public enum Lang CPP, Java, JS, - Py + Py, + Rust } /// Handles language specific syntax of the generated code and translations of names, types @@ -30,9 +31,15 @@ public enum Lang /// the current target language: Curent, DotNet, Cpp, Java, Node, Py. public static partial class TargetLang { - /// Lists code generators corresponding to the supported target languages - /// from the Lang enum (listed in the same order) - static Type[] CodeGenerators = { typeof(CGenCpp), typeof(CGenJava), typeof(CGenNode), typeof(CGenPy) }; + /// Maps each target language to its code generator class + static Dictionary CodeGenerators = new Dictionary + { + { Lang.CPP, typeof(CGenCpp) }, + { Lang.Java, typeof(CGenJava) }, + { Lang.JS, typeof(CGenNode) }, + { Lang.Py, typeof(CGenPy) }, + { Lang.Rust, typeof(CGenRust) } + }; static Lang _curLang = Lang.None; @@ -60,25 +67,27 @@ public ElementaryType(int size, params string[] nameList) } static Dictionary ElementaryTypes = new Dictionary { - // .Net C++ Java TypeScript Python - { "BYTE", new ElementaryType(1, "byte", "BYTE", "byte", "number", "int")}, - { "UINT8", new ElementaryType(1, "byte", "UINT8", "byte", "number", "int")}, - { "INT8", new ElementaryType(1, "sbyte", "INT8", "byte", "number", "int")}, - { "UINT16", new ElementaryType(2, "ushort", "UINT16", "int", "number", "int")}, - { "INT16", new ElementaryType(2, "short", "INT16", "int", "number", "int")}, - { "UINT32", new ElementaryType(4, "uint", "UINT32", "int", "number", "int")}, - { "INT32", new ElementaryType(4, "int", "INT32", "int", "number", "int")}, - { "UINT64", new ElementaryType(8, "ulong", "UINT64", "long", "number", "int")}, - { "INT64", new ElementaryType(8, "long", "INT64", "long", "number", "int")}, - { "BOOL", new ElementaryType(1, "bool", "BOOL", "boolean", "boolean", "bool")} + // .Net C++ Java TypeScript Python Rust + { "BYTE", new ElementaryType(1, "byte", "BYTE", "byte", "number", "int", "u8")}, + { "UINT8", new ElementaryType(1, "byte", "UINT8", "byte", "number", "int", "u8")}, + { "INT8", new ElementaryType(1, "sbyte", "INT8", "byte", "number", "int", "i8")}, + { "UINT16", new ElementaryType(2, "ushort", "UINT16", "int", "number", "int", "u16")}, + { "INT16", new ElementaryType(2, "short", "INT16", "int", "number", "int", "i16")}, + { "UINT32", new ElementaryType(4, "uint", "UINT32", "int", "number", "int", "u32")}, + { "INT32", new ElementaryType(4, "int", "INT32", "int", "number", "int", "i32")}, + { "UINT64", new ElementaryType(8, "ulong", "UINT64", "long", "number", "int", "u64")}, + { "INT64", new ElementaryType(8, "long", "INT64", "long", "number", "int", "i64")}, + { "BOOL", new ElementaryType(1, "bool", "BOOL", "boolean", "boolean", "bool", "bool")} }; + static HashSet ElementaryTypesCurrentLang => + ElementaryTypes.Select(et => et.Value.Names[(int)Current - 1]).ToHashSet(); + public static IEnumerable GetElementaryTypes() => ElementaryTypes.Select(et => new TpmValueType(et.Key, et.Value.Size)); public static string NameFor(string typeName) => ElementaryTypes[typeName].Names[(int)Current - 1]; - public static Lang Current => _curLang; public static bool DotNet => _curLang == Lang.DotNet; @@ -86,31 +95,64 @@ public static IEnumerable GetElementaryTypes() public static bool Java => _curLang == Lang.Java; public static bool Node => _curLang == Lang.JS; public static bool Py => _curLang == Lang.Py; + public static bool Rust => _curLang == Lang.Rust; public static bool IsOneOf(params Lang[] toCompare) => Current.IsOneOf(toCompare); // Standalone "this" reference (as used, e.g. to pass it as a function argument) - public static string This => Py ? "self" : "this"; + public static string This => (Py || Rust) ? "self" : "this"; public static string ThisMember => _thisQual; - public static string ClassMember => Cpp ? "::" : "."; + public static string ClassMember => (Cpp || Rust) ? "::" : "."; + + public static string AsReference(bool isConst) => Rust ? (isConst ? ".as_ref()" : ".as_mut()") : ""; + public static string UnionMember(bool isConst) => Rust ? AsReference(isConst) + ".unwrap()." : Member; public static string Member => Cpp ? "->" : "."; public static string Null => _null; public static string Neg => Py ? "not " : "!"; public static string LineComment => Py ? "#" : "//"; public static string If(string cond) => Py ? $"if {cond}:" : $"if ({cond})"; + + public static string IfNull(string obj) => TargetLang.If(Rust ? $"{obj}.is_none()" : $"{obj} == {TargetLang.Null}"); public static string Quote(string str) => _quote + str + _quote; - public static string TypeInfo(string typeName) => typeName + (Java ? ".class" : ""); + public static string TypeInfo(string typeName) => typeName + (Java ? ".class" : Rust ? "::type_id()" : ""); public static string LocalVar(string varName, string typeName) - => Py ? varName : Node ? $"let {varName}: {typeName}" : $"{typeName} {varName}"; + => Py ? varName : Node ? $"let {varName}: {typeName}" : Rust ? $"let r#{varName}: {typeName}" : $"{typeName} {varName}"; - public static string NewObject(string type) => $"{_new}{type}()"; + public static string NewObject(string type) => Rust ? $"{type}::default()" : $"{_new}{type}()"; public static string DigestSize(string hashAlgField) => $"{_digestSize}({_thisQual}{hashAlgField})"; + public static string GetUnionValue(int sizeInBytes) => Rust ? GetEnumValue("", $"u{sizeInBytes}") : ""; + + public static string GetEnumValue(string enumValue, string enumTypename, int valueSizeInBytes = 4) { + if (!Rust) return enumValue; + + // In Rust, if the enum type is a primitive type (such as i32), we need to get the unsigned version of it + // (e.g. u32) using the "as" operator, as into() isn't implemented for such conversions + if (ElementaryTypesCurrentLang.Contains(enumTypename)) { + return $"{enumValue} as u{valueSizeInBytes * 8}"; + } + + // Otherwise, we can use the into() method to convert the enum value to the target type + return $"{enumValue}.into()"; + } + + public static string ParseEnum(string selectorTypeName, string value, string underlyingType) { + if (!Rust) return value; + + if (ElementaryTypesCurrentLang.Contains(selectorTypeName)) + { + return $"{value} as {underlyingType}"; + } + + return $"{selectorTypeName}({value} as {underlyingType})"; + } + + public static int MaxCommentLine => TargetLang.Py ? 72 : 90; public static string EnumeratorAsUint(string name) @@ -120,22 +162,22 @@ public static string EnumeratorAsUint(string name) } public static CodeGenBase NewCodeGen (Lang lang, string rootDir) - => (CodeGenBase)Activator.CreateInstance(CodeGenerators[(int)lang - 2], rootDir); + => (CodeGenBase)Activator.CreateInstance(CodeGenerators[lang], rootDir); /// This method is called before code generation for the given target /// language begins public static void SetTargetLang(Lang lang) { // This assertion will fail if a new target language is added to the Lang enum - // without also adding the corresponding - Debug.Assert(Enum.GetValues(typeof(Lang)).Length == CodeGenerators.Length + 2); + // without also adding the corresponding code generator to CodeGenerators + Debug.Assert(Enum.GetValues(typeof(Lang)).Length == CodeGenerators.Count + 2); _curLang = lang; _thisQual = DotNet || Cpp || Java ? "" : This + "."; - _null = Py ? "None" : Cpp ? "nullptr" : "null"; - _new = DotNet || Java || Node ? "new " : ""; - _quote = Py || Node ? "'" : "\""; - _digestSize = Cpp ? "TPMT_HA::DigestSize" : "Crypto.digestSize"; + _null = Py ? "None" : Rust ? "Default::default()" : Cpp ? "nullptr" : "null"; + _new = DotNet || Java || Node ? "new " : Rust ? "" : ""; + _quote = Py || Node ? "'" : Rust ? "\"" : "\""; + _digestSize = Cpp ? "TPMT_HA::DigestSize" : Rust ? "Crypto::digestSize" : "Crypto.digestSize"; GeneratedEnums = new HashSet(); @@ -176,8 +218,8 @@ public static void SetTargetLang(Lang lang) static bool IsGenerated(TpmEnum e) { - // In Java mutual order of definitions is not important - return Java || (GeneratedEnums != null && GeneratedEnums.Contains(e)); + // In Java and Rust mutual order of definitions is not important + return Java || Rust || (GeneratedEnums != null && GeneratedEnums.Contains(e)); } } // static class TargetLang diff --git a/TssCodeGen/src/TpmTranslations.cs b/TssCodeGen/src/TpmTranslations.cs index d97fd965..9a064a7e 100644 --- a/TssCodeGen/src/TpmTranslations.cs +++ b/TssCodeGen/src/TpmTranslations.cs @@ -444,7 +444,7 @@ public static string TranslateConstExpr(TpmConstExpr ce, TpmEnum enclosingEnum = { var nameDelimiters = new char[] { ' ', ',', '{', '}', '(', ')', '+', '-', '<', '*', '/', '`' }; - string suffix = TargetLang.Java ? ".toInt()" : ""; + string suffix = TargetLang.Java ? ".toInt()" : TargetLang.Rust ? ".into()" : ""; string expr = ce.Expr; string[] tokens = expr.Split(nameDelimiters); bool sizeofOccurred = false, @@ -484,12 +484,12 @@ public static string TranslateConstExpr(TpmConstExpr ce, TpmEnum enclosingEnum = Debug.Assert(sizeofOccurred); sizeofOccurred = false; TpmType t = TpmTypes.Lookup(token); - if (t is TpmStruct || TargetLang.IsOneOf(Lang.Java, Lang.JS, Lang.Py)) + if (t is TpmStruct || TargetLang.IsOneOf(Lang.Java, Lang.JS, Lang.Py, Lang.Rust)) { string sizeofExpr = "sizeof(" + token + ")"; Debug.Assert(expr.Contains(sizeofExpr)); - commentNeeded = TargetLang.Py; - string origExpr = TargetLang.Py ? "" : $"/*{sizeofExpr}*/"; + commentNeeded = TargetLang.Py || TargetLang.Rust; + string origExpr = (TargetLang.Py || TargetLang.Rust) ? "" : $"/*{sizeofExpr}*/"; expr = expr.Replace(sizeofExpr, $"0x{t.GetSize():X}{origExpr}"); } else if (TargetLang.DotNet) @@ -504,7 +504,7 @@ public static string TranslateConstExpr(TpmConstExpr ce, TpmEnum enclosingEnum = if (!TargetLang.IsGenerated(nc.EnclosingEnum)) { translated = nc.NumericValue.ToString(); - if (!TargetLang.Py) + if (!TargetLang.Py && !TargetLang.Rust) translated += "/*" + token + "*/"; else commentNeeded = true; @@ -530,9 +530,15 @@ public static string TranslateConstExpr(TpmConstExpr ce, TpmEnum enclosingEnum = } while (true); expr = expr.Replace("<<", " << (int)"); } + + // For Rust, we might need to add type suffixes for literals + if (TargetLang.Rust && expr.Contains("<<")) + { + expr = expr.Replace("<<", " << "); + } if (commentNeeded) - expr += $" # {ce.Expr}"; + expr += TargetLang.Rust ? $" /* {ce.Expr} */" : $" # {ce.Expr}"; return expr; } // TranslateConstExpr() @@ -549,6 +555,8 @@ static string TranslateFieldType(StructField f) { if (TargetLang.Cpp) typeName = "ByteVec"; + else if (TargetLang.Rust) + return "Vec"; else { if (TargetLang.Node) @@ -562,12 +570,13 @@ static string TranslateFieldType(StructField f) { if (TargetLang.Cpp) typeName = $"vector<{typeName}>"; + else if (TargetLang.Rust) + typeName = $"Vec<{typeName}>"; else return typeName + "[]"; } return typeName; } - } // partial class TargetLang } // namespace CodeGen diff --git a/TssCodeGen/src/TpmTypes.cs b/TssCodeGen/src/TpmTypes.cs index 70d1fdff..1681bf76 100644 --- a/TssCodeGen/src/TpmTypes.cs +++ b/TssCodeGen/src/TpmTypes.cs @@ -564,12 +564,12 @@ public override int CalcSize() if (counter != null) { if (counter.MarshalType == MarshalType.LengthOfStruct) - size += counter.MaxVal.NumericValue; + size += (int)counter.MaxVal.NumericValue; else if (counter.MarshalType == MarshalType.Normal && counter.Type.IsAlgOrHashAlg()) size += 64; // corresponds to SHA512 digest size continue; } - size += f.Type.GetSize() * (counter != null ? counter.MaxVal.NumericValue : 1); + size += (int)f.Type.GetSize() * (counter != null ? (int)counter.MaxVal.NumericValue : 1); } return size; } @@ -601,7 +601,7 @@ public override int CalcSize() { int fieldSize = f.Type.GetSize(); if (f.ArraySize != null) - fieldSize *= f.ArraySize.NumericValue; + fieldSize *= (int)f.ArraySize.NumericValue; size = Math.Max(size, fieldSize); } return size; @@ -948,7 +948,7 @@ public static implicit operator TpmConstExpr(string s) } /// Result of computing the constant's value expression - public int NumericValue => Expression.Eval(Expr); + public long NumericValue => Expression.Eval(Expr); } // class TpmConstExpr @@ -987,7 +987,7 @@ public TpmNamedConstant(TpmEnum enclosingEnum, string specName, string value, st } /// Result of computing the constant's value expression - public int NumericValue => SpecValue.NumericValue; + public long NumericValue => SpecValue.NumericValue; /// Enum member name qualified with the its enum type name public string QualifiedName => EnclosingEnum.Name + TargetLang.ClassMember + Name;