tpm2_protocol/
data.rs

1// SPDX-License-Identifier: MIT OR Apache-2.0
2// Copyright (c) 2025 Opinsys Oy
3// Copyright (c) 2024-2025 Jarkko Sakkinen
4
5use crate::{
6    tpm2b, tpm2b_struct, tpm_bitflags, tpm_bool, tpm_enum, tpm_hash_size, tpm_struct, tpml,
7    TpmBuffer, TpmBuild, TpmErrorKind, TpmParse, TpmParseTagged, TpmResult, TpmSized, TpmTagged,
8    TpmWriter, TPM_MAX_COMMAND_SIZE,
9};
10use core::{
11    convert::TryFrom,
12    fmt::{self, Debug, Display, Formatter},
13    mem::size_of,
14    ops::Deref,
15};
16
17pub const MAX_DIGEST_SIZE: usize = 64;
18pub const MAX_ECC_KEY_BYTES: usize = 66;
19pub const MAX_SYM_KEY_BYTES: usize = 32;
20pub const MAX_LABEL_SIZE: usize = 32;
21pub const MAX_RSA_KEY_BYTES: usize = 512;
22pub const MAX_SENSITIVE_DATA: usize = 256;
23pub const MAX_NV_BUFFER_SIZE: usize = 2048;
24pub const MAX_TIMEOUT: usize = 8;
25pub const MAX_CONTEXT_DATA: usize = 1664;
26pub const MAX_DATA_SIZE: usize = 256;
27pub const MAX_EVENT_SIZE: usize = 1024;
28pub const MAX_BUFFER_SIZE: usize = 1024;
29pub const MAX_OPERAND_SIZE: usize = 1024;
30pub const MAX_PRIVATE_SIZE: usize = 1408;
31pub const MAX_PRIVATE_VENDOR_SPECIFIC_SIZE: usize = 1024;
32
33tpm2b!(Tpm2b, TPM_MAX_COMMAND_SIZE);
34tpm2b!(Tpm2bAuth, MAX_DIGEST_SIZE);
35tpm2b!(Tpm2bContextSensitive, MAX_CONTEXT_DATA);
36tpm2b!(Tpm2bData, MAX_DATA_SIZE);
37tpm2b!(Tpm2bDerive, MAX_DIGEST_SIZE);
38tpm2b!(Tpm2bDigest, MAX_DIGEST_SIZE);
39tpm2b!(Tpm2bEccParameter, MAX_ECC_KEY_BYTES);
40tpm2b!(Tpm2bEncryptedSecret, MAX_ECC_KEY_BYTES);
41tpm2b!(Tpm2bEvent, MAX_EVENT_SIZE);
42tpm2b!(Tpm2bIv, MAX_SYM_KEY_BYTES);
43tpm2b!(Tpm2bLabel, MAX_LABEL_SIZE);
44tpm2b!(Tpm2bMaxBuffer, MAX_BUFFER_SIZE);
45tpm2b!(Tpm2bMaxNvBuffer, MAX_NV_BUFFER_SIZE);
46tpm2b!(Tpm2bName, { MAX_DIGEST_SIZE + 2 });
47tpm2b!(Tpm2bNonce, MAX_DIGEST_SIZE);
48tpm2b!(Tpm2bOperand, MAX_OPERAND_SIZE);
49tpm2b!(Tpm2bPrivate, MAX_PRIVATE_SIZE);
50tpm2b!(Tpm2bPrivateKeyRsa, MAX_RSA_KEY_BYTES);
51tpm2b!(Tpm2bPrivateVendorSpecific, MAX_PRIVATE_VENDOR_SPECIFIC_SIZE);
52tpm2b!(Tpm2bPublicKeyRsa, MAX_RSA_KEY_BYTES);
53tpm2b!(Tpm2bSensitiveData, MAX_SENSITIVE_DATA);
54tpm2b!(Tpm2bSymKey, MAX_SYM_KEY_BYTES);
55tpm2b!(Tpm2bTimeout, MAX_TIMEOUT);
56
57tpm_enum! {
58    /// Enumeration of the `TPM_ALG_ID` values.
59    ///
60    /// Reference: TPM 2.0 Structures Specification, section 6.3.
61    #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Copy, Clone, Hash, Default)]
62    pub enum TpmAlgId(u16) {
63        (Error, 0x0000, "TPM_ALG_ERROR"),
64        (Rsa, 0x0001, "TPM_ALG_RSA"),
65        (Sha1, 0x0004, "TPM_ALG_SHA1"),
66        (Hmac, 0x0005, "TPM_ALG_HMAC"),
67        (Aes, 0x0006, "TPM_ALG_AES"),
68        (Mgf1, 0x0007, "TPM_ALG_MGF1"),
69        (KeyedHash, 0x0008, "TPM_ALG_KEYEDHASH"),
70        (Xor, 0x000A, "TPM_ALG_XOR"),
71        (Sha256, 0x000B, "TPM_ALG_SHA256"),
72        (Sha384, 0x000C, "TPM_ALG_SHA384"),
73        (Sha512, 0x000D, "TPM_ALG_SHA512"),
74        /// `TPM_ALG_NULL`
75        #[default]
76        (Null, 0x0010, "TPM_ALG_NULL"),
77        (Sm3_256, 0x0012, "TPM_ALG_SM3_256"),
78        (Sm4, 0x0013, "TPM_ALG_SM4"),
79        (Rsassa, 0x0014, "TPM_ALG_RSASSA"),
80        (Rsaes, 0x0015, "TPM_ALG_RSAES"),
81        (Rsapss, 0x0016, "TPM_ALG_RSAPSS"),
82        (Oaep, 0x0017, "TPM_ALG_OAEP"),
83        (Ecdsa, 0x0018, "TPM_ALG_ECDSA"),
84        (Ecdh, 0x0019, "TPM_ALG_ECDH"),
85        (Ecdaa, 0x001A, "TPM_ALG_ECDAA"),
86        (Sm2, 0x001B, "TPM_ALG_SM2"),
87        (Ecschnorr, 0x001C, "TPM_ALG_ECSCHNORR"),
88        (Ecmqv, 0x001D, "TPM_ALG_ECMQV"),
89        (Kdf1Sp800_56A, 0x0020, "TPM_ALG_KDF1_SP800_56A"),
90        (Kdf2, 0x0021, "TPM_ALG_KDF2"),
91        (Kdf1Sp800_108, 0x0022, "TPM_ALG_KDF1_SP800_108"),
92        (Ecc, 0x0023, "TPM_ALG_ECC"),
93        (SymCipher, 0x0025, "TPM_ALG_SYMCIPHER"),
94        (Camellia, 0x0026, "TPM_ALG_CAMELLIA"),
95        (Ctr, 0x0040, "TPM_ALG_CTR"),
96        (Ofb, 0x0041, "TPM_ALG_OFB"),
97        (Cbc, 0x0042, "TPM_ALG_CBC"),
98        (Cfb, 0x0043, "TPM_ALG_CFB"),
99        (Ecb, 0x0044, "TPM_ALG_ECB"),
100    }
101}
102
103tpm_enum! {
104    /// `TPM_CAP`
105    #[derive(Debug, PartialEq, Eq, Copy, Clone)]
106    pub enum TpmCap(u32) {
107        (Algs, 0x0000_0000, "TPM_CAP_ALGS"),
108        (Handles, 0x0000_0001, "TPM_CAP_HANDLES"),
109        (Commands, 0x0000_0002, "TPM_CAP_COMMANDS"),
110        (PpCommands, 0x0000_0003, "TPM_CAP_PP_COMMANDS"),
111        (AuditCommands, 0x0000_0004, "TPM_CAP_AUDIT_COMMANDS"),
112        (Pcrs, 0x0000_0005, "TPM_CAP_PCRS"),
113        (TpmProperties, 0x0000_0006, "TPM_CAP_TPM_PROPERTIES"),
114        (PcrProperties, 0x0000_0007, "TPM_CAP_PCR_PROPERTIES"),
115        (EccCurves, 0x0000_0008, "TPM_CAP_ECC_CURVES"),
116        (AuthPolicies, 0x0000_0009, "TPM_CAP_AUTH_POLICIES"),
117    }
118}
119
120tpm_enum! {
121    /// Enumeration of the `TPM_CC`values
122    ///
123    /// Reference: TPM 2.0 Structures Specification, section 6.5.2.
124    #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Copy, Clone)]
125    pub enum TpmCc(u32) {
126        (NvUndefineSpaceSpecial, 0x0000_011F, "TPM_CC_NV_UndefineSpaceSpecial"),
127        (EvictControl, 0x0000_0120, "TPM_CC_EvictControl"),
128        (HierarchyControl, 0x0000_0121, "TPM_CC_HierarchyControl"),
129        (NvUndefineSpace, 0x0000_0122, "TPM_CC_NV_UndefineSpace"),
130        (ChangeEps, 0x0000_0124, "TPM_CC_ChangeEPS"),
131        (ChangePps, 0x0000_0125, "TPM_CC_ChangePPS"),
132        (Clear, 0x0000_0126, "TPM_CC_Clear"),
133        (ClearControl, 0x0000_0127, "TPM_CC_ClearControl"),
134        (ClockSet, 0x0000_0128, "TPM_CC_ClockSet"),
135        (HierarchyChangeAuth, 0x0000_0129, "TPM_CC_HierarchyChangeAuth"),
136        (NvDefineSpace, 0x0000_012A, "TPM_CC_NV_DefineSpace"),
137        (PcrAllocate, 0x0000_012B, "TPM_CC_PCR_Allocate"),
138        (PcrSetAuthPolicy, 0x0000_012C, "TPM_CC_PCR_SetAuthPolicy"),
139        (PpCommands, 0x0000_012D, "TPM_CC_PP_Commands"),
140        (SetPrimaryPolicy, 0x0000_012E, "TPM_CC_SetPrimaryPolicy"),
141        (FieldUpgradeStart, 0x0000_012F, "TPM_CC_FieldUpgradeStart"),
142        (ClockRateAdjust, 0x0000_0130, "TPM_CC_ClockRateAdjust"),
143        (CreatePrimary, 0x0000_0131, "TPM_CC_CreatePrimary"),
144        (NvGlobalWriteLock, 0x0000_0132, "TPM_CC_NV_GlobalWriteLock"),
145        (GetCommandAuditDigest, 0x0000_0133, "TPM_CC_GetCommandAuditDigest"),
146        (NvIncrement, 0x0000_0134, "TPM_CC_NV_Increment"),
147        (NvSetBits, 0x0000_0135, "TPM_CC_NV_SetBits"),
148        (NvExtend, 0x0000_0136, "TPM_CC_NV_Extend"),
149        (NvWrite, 0x0000_0137, "TPM_CC_NV_Write"),
150        (NvWriteLock, 0x0000_0138, "TPM_CC_NV_WriteLock"),
151        (DictionaryAttackLockReset, 0x0000_0139, "TPM_CC_DictionaryAttackLockReset"),
152        (DictionaryAttackParameters, 0x0000_013A, "TPM_CC_DictionaryAttackParameters"),
153        (NvChangeAuth, 0x0000_013B, "TPM_CC_NV_ChangeAuth"),
154        (PcrEvent, 0x0000_013C, "TPM_CC_PCR_Event"),
155        (PcrReset, 0x0000_013D, "TPM_CC_PCR_Reset"),
156        (SequenceComplete, 0x0000_013E, "TPM_CC_SequenceComplete"),
157        (SetAlgorithmSet, 0x0000_013F, "TPM_CC_SetAlgorithmSet"),
158        (SetCommandCodeAuditStatus, 0x0000_0140, "TPM_CC_SetCommandCodeAuditStatus"),
159        (FieldUpgradeData, 0x0000_0141, "TPM_CC_FieldUpgradeData"),
160        (IncrementalSelfTest, 0x0000_0142, "TPM_CC_IncrementalSelfTest"),
161        (SelfTest, 0x0000_0143, "TPM_CC_SelfTest"),
162        (Startup, 0x0000_0144, "TPM_CC_Startup"),
163        (Shutdown, 0x0000_0145, "TPM_CC_Shutdown"),
164        (StirRandom, 0x0000_0146, "TPM_CC_StirRandom"),
165        (ActivateCredential, 0x0000_0147, "TPM_CC_ActivateCredential"),
166        (Certify, 0x0000_0148, "TPM_CC_Certify"),
167        (PolicyNv, 0x0000_0149, "TPM_CC_PolicyNV"),
168        (CertifyCreation, 0x0000_014A, "TPM_CC_CertifyCreation"),
169        (Duplicate, 0x0000_014B, "TPM_CC_Duplicate"),
170        (GetTime, 0x0000_014C, "TPM_CC_GetTime"),
171        (GetSessionAuditDigest, 0x0000_014D, "TPM_CC_GetSessionAuditDigest"),
172        (NvRead, 0x0000_014E, "TPM_CC_NV_Read"),
173        (NvReadLock, 0x0000_014F, "TPM_CC_NV_ReadLock"),
174        (ObjectChangeAuth, 0x0000_0150, "TPM_CC_ObjectChangeAuth"),
175        (PolicySecret, 0x0000_0151, "TPM_CC_PolicySecret"),
176        (Rewrap, 0x0000_0152, "TPM_CC_Rewrap"),
177        (Create, 0x0000_0153, "TPM_CC_Create"),
178        (EcdhZGen, 0x0000_0154, "TPM_CC_ECDH_ZGen"),
179        (Hmac, 0x0000_0155, "TPM_CC_HMAC"),
180        (Import, 0x0000_0156, "TPM_CC_Import"),
181        (Load, 0x0000_0157, "TPM_CC_Load"),
182        (Quote, 0x0000_0158, "TPM_CC_Quote"),
183        (RsaDecrypt, 0x0000_0159, "TPM_CC_RSA_Decrypt"),
184        (HmacStart, 0x0000_015B, "TPM_CC_HMAC_Start"),
185        (SequenceUpdate, 0x0000_015C, "TPM_CC_SequenceUpdate"),
186        (Sign, 0x0000_015D, "TPM_CC_Sign"),
187        (Unseal, 0x0000_015E, "TPM_CC_Unseal"),
188        (PolicySigned, 0x0000_0160, "TPM_CC_PolicySigned"),
189        (ContextLoad, 0x0000_0161, "TPM_CC_ContextLoad"),
190        (ContextSave, 0x0000_0162, "TPM_CC_ContextSave"),
191        (EcdhKeygen, 0x0000_0163, "TPM_CC_ECDH_KeyGen"),
192        (EncryptDecrypt, 0x0000_0164, "TPM_CC_EncryptDecrypt"),
193        (FlushContext, 0x0000_0165, "TPM_CC_FlushContext"),
194        (LoadExternal, 0x0000_0167, "TPM_CC_LoadExternal"),
195        (MakeCredential, 0x0000_0168, "TPM_CC_MakeCredential"),
196        (NvReadPublic, 0x0000_0169, "TPM_CC_NV_ReadPublic"),
197        (PolicyAuthorize, 0x0000_016A, "TPM_CC_PolicyAuthorize"),
198        (PolicyAuthValue, 0x0000_016B, "TPM_CC_PolicyAuthValue"),
199        (PolicyCommandCode, 0x0000_016C, "TPM_CC_PolicyCommandCode"),
200        (PolicyCounterTimer, 0x0000_016D, "TPM_CC_PolicyCounterTimer"),
201        (PolicyCpHash, 0x0000_016E, "TPM_CC_PolicyCpHash"),
202        (PolicyLocality, 0x0000_016F, "TPM_CC_PolicyLocality"),
203        (PolicyNameHash, 0x0000_0170, "TPM_CC_PolicyNameHash"),
204        (PolicyOR, 0x0000_0171, "TPM_CC_PolicyOR"),
205        (PolicyTicket, 0x0000_0172, "TPM_CC_PolicyTicket"),
206        (ReadPublic, 0x0000_0173, "TPM_CC_ReadPublic"),
207        (RsaEncrypt, 0x0000_0174, "TPM_CC_RSA_Encrypt"),
208        (StartAuthSession, 0x0000_0176, "TPM_CC_StartAuthSession"),
209        (VerifySignature, 0x0000_0177, "TPM_CC_VerifySignature"),
210        (EccParameters, 0x0000_0178, "TPM_CC_ECC_Parameters"),
211        (FirmwareRead, 0x0000_0179, "TPM_CC_FirmwareRead"),
212        (GetCapability, 0x0000_017A, "TPM_CC_GetCapability"),
213        (GetRandom, 0x0000_017B, "TPM_CC_GetRandom"),
214        (GetTestResult, 0x0000_017C, "TPM_CC_GetTestResult"),
215        (Hash, 0x0000_017D, "TPM_CC_Hash"),
216        (PcrRead, 0x0000_017E, "TPM_CC_PCR_Read"),
217        (PolicyPcr, 0x0000_017F, "TPM_CC_PolicyPCR"),
218        (PolicyRestart, 0x0000_0180, "TPM_CC_PolicyRestart"),
219        (ReadClock, 0x0000_0181, "TPM_CC_ReadClock"),
220        (PcrExtend, 0x0000_0182, "TPM_CC_PCR_Extend"),
221        (PcrSetAuthValue, 0x0000_0183, "TPM_CC_PCR_SetAuthValue"),
222        (NvCertify, 0x0000_0184, "TPM_CC_NV_Certify"),
223        (EventSequenceComplete, 0x0000_0185, "TPM_CC_EventSequenceComplete"),
224        (HashSequenceStart, 0x0000_0186, "TPM_CC_HashSequenceStart"),
225        (PolicyPhysicalPresence, 0x0000_0187, "TPM_CC_PolicyPhysicalPresence"),
226        (PolicyDuplicationSelect, 0x0000_0188, "TPM_CC_PolicyDuplicationSelect"),
227        (PolicyGetDigest, 0x0000_0189, "TPM_CC_PolicyGetDigest"),
228        (TestParms, 0x0000_018A, "TPM_CC_TestParms"),
229        (Commit, 0x0000_018B, "TPM_CC_Commit"),
230        (PolicyPassword, 0x0000_018C, "TPM_CC_PolicyPassword"),
231        (ZGen2Phase, 0x0000_018D, "TPM_CC_ZGen_2Phase"),
232        (EcEphemeral, 0x0000_018E, "TPM_CC_EC_Ephemeral"),
233        (PolicyNvWritten, 0x0000_018F, "TPM_CC_PolicyNvWritten"),
234        (PolicyTemplate, 0x0000_0190, "TPM_CC_PolicyTemplate"),
235        (CreateLoaded, 0x0000_0191, "TPM_CC_CreateLoaded"),
236        (PolicyAuthorizeNv, 0x0000_0192, "TPM_CC_PolicyAuthorizeNV"),
237        (EncryptDecrypt2, 0x0000_0193, "TPM_CC_EncryptDecrypt2"),
238        (VendorTcgTest, 0x2000_0000, "TPM_CC_Vendor_TCG_Test"),
239    }
240}
241
242tpm_enum! {
243    #[derive(Debug, PartialEq, Eq, Clone, Copy)]
244    pub enum TpmEccCurve(u16) {
245        (None, 0x0000, "TPM_ECC_NONE"),
246        (NistP192, 0x0001, "TPM_ECC_NIST_P192"),
247        (NistP224, 0x0002, "TPM_ECC_NIST_P224"),
248        (NistP256, 0x0003, "TPM_ECC_NIST_P256"),
249        (NistP384, 0x0004, "TPM_ECC_NIST_P384"),
250        (NistP521, 0x0005, "TPM_ECC_NIST_P521"),
251    }
252}
253
254pub const TPM_RC_VER1: u32 = 0x0100;
255pub const TPM_RC_FMT1: u32 = 0x0080;
256pub const TPM_RC_WARN: u32 = 0x0900;
257pub const TPM_RC_P_BIT: u32 = 1 << 6;
258pub const TPM_RC_N_SHIFT: u32 = 8;
259pub const TPM_RC_FMT1_ERROR_MASK: u32 = 0x003F;
260
261#[derive(Debug, PartialEq, Eq, Copy, Clone)]
262pub enum TpmRcIndex {
263    Parameter(u8),
264    Handle(u8),
265    Session(u8),
266}
267
268impl Display for TpmRcIndex {
269    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
270        match self {
271            TpmRcIndex::Parameter(i) => write!(f, "parameter[{i}]"),
272            TpmRcIndex::Handle(i) => write!(f, "handle[{i}]"),
273            TpmRcIndex::Session(i) => write!(f, "session[{i}]"),
274        }
275    }
276}
277
278tpm_enum! {
279    #[derive(Debug, PartialEq, Eq, Copy, Clone)]
280    #[allow(clippy::upper_case_acronyms)]
281    pub enum TpmRcBase(u32) {
282        (Success, 0x0000, "TPM_RC_SUCCESS"),
283        (BadTag, 0x001E, "TPM_RC_BAD_TAG"),
284        (Initialize, TPM_RC_VER1, "TPM_RC_INITIALIZE"),
285        (Failure, TPM_RC_VER1 | 0x001, "TPM_RC_FAILURE"),
286        (Sequence, TPM_RC_VER1 | 0x003, "TPM_RC_SEQUENCE"),
287        (Private, TPM_RC_VER1 | 0x00B, "TPM_RC_PRIVATE"),
288        (Hmac, TPM_RC_VER1 | 0x019, "TPM_RC_HMAC"),
289        (Disabled, TPM_RC_VER1 | 0x020, "TPM_RC_DISABLED"),
290        (Exclusive, TPM_RC_VER1 | 0x021, "TPM_RC_EXCLUSIVE"),
291        (AuthType, TPM_RC_VER1 | 0x024, "TPM_RC_AUTH_TYPE"),
292        (AuthMissing, TPM_RC_VER1 | 0x025, "TPM_RC_AUTH_MISSING"),
293        (Policy, TPM_RC_VER1 | 0x026, "TPM_RC_POLICY"),
294        (Pcr, TPM_RC_VER1 | 0x027, "TPM_RC_PCR"),
295        (PcrChanged, TPM_RC_VER1 | 0x028, "TPM_RC_PCR_CHANGED"),
296        (Upgrade, TPM_RC_VER1 | 0x02D, "TPM_RC_UPGRADE"),
297        (TooManyContexts, TPM_RC_VER1 | 0x02E, "TPM_RC_TOO_MANY_CONTEXTS"),
298        (AuthUnavailable, TPM_RC_VER1 | 0x02F, "TPM_RC_AUTH_UNAVAILABLE"),
299        (Reboot, TPM_RC_VER1 | 0x030, "TPM_RC_REBOOT"),
300        (Unbalanced, TPM_RC_VER1 | 0x031, "TPM_RC_UNBALANCED"),
301        (CommandSize, TPM_RC_VER1 | 0x042, "TPM_RC_COMMAND_SIZE"),
302        (CommandCode, TPM_RC_VER1 | 0x043, "TPM_RC_COMMAND_CODE"),
303        (AuthSize, TPM_RC_VER1 | 0x044, "TPM_RC_AUTHSIZE"),
304        (AuthContext, TPM_RC_VER1 | 0x045, "TPM_RC_AUTH_CONTEXT"),
305        (NvRange, TPM_RC_VER1 | 0x046, "TPM_RC_NV_RANGE"),
306        (NvSize, TPM_RC_VER1 | 0x047, "TPM_RC_NV_SIZE"),
307        (NvLocked, TPM_RC_VER1 | 0x048, "TPM_RC_NV_LOCKED"),
308        (NvAuthorization, TPM_RC_VER1 | 0x049, "TPM_RC_NV_AUTHORIZATION"),
309        (NvUninitialized, TPM_RC_VER1 | 0x04A, "TPM_RC_NV_UNINITIALIZED"),
310        (NvSpace, TPM_RC_VER1 | 0x04B, "TPM_RC_NV_SPACE"),
311        (NvDefined, TPM_RC_VER1 | 0x04C, "TPM_RC_NV_DEFINED"),
312        (BadContext, TPM_RC_VER1 | 0x050, "TPM_RC_BAD_CONTEXT"),
313        (CpHash, TPM_RC_VER1 | 0x051, "TPM_RC_CPHASH"),
314        (Parent, TPM_RC_VER1 | 0x052, "TPM_RC_PARENT"),
315        (NeedsTest, TPM_RC_VER1 | 0x053, "TPM_RC_NEEDS_TEST"),
316        (NoResult, TPM_RC_VER1 | 0x054, "TPM_RC_NO_RESULT"),
317        (Sensitive, TPM_RC_VER1 | 0x055, "TPM_RC_SENSITIVE"),
318        (ReadOnly, TPM_RC_VER1 | 0x056, "TPM_RC_READ_ONLY"),
319        (Asymmetric, TPM_RC_FMT1 | 0x001, "TPM_RC_ASYMMETRIC"),
320        (Attributes, TPM_RC_FMT1 | 0x002, "TPM_RC_ATTRIBUTES"),
321        (Hash, TPM_RC_FMT1 | 0x003, "TPM_RC_HASH"),
322        (Value, TPM_RC_FMT1 | 0x004, "TPM_RC_VALUE"),
323        (Hierarchy, TPM_RC_FMT1 | 0x005, "TPM_RC_HIERARCHY"),
324        (KeySize, TPM_RC_FMT1 | 0x007, "TPM_RC_KEY_SIZE"),
325        (Mgf, TPM_RC_FMT1 | 0x008, "TPM_RC_MGF"),
326        (Mode, TPM_RC_FMT1 | 0x009, "TPM_RC_MODE"),
327        (Type, TPM_RC_FMT1 | 0x00A, "TPM_RC_TYPE"),
328        (Handle, TPM_RC_FMT1 | 0x00B, "TPM_RC_HANDLE"),
329        (Kdf, TPM_RC_FMT1 | 0x00C, "TPM_RC_KDF"),
330        (Range, TPM_RC_FMT1 | 0x00D, "TPM_RC_RANGE"),
331        (AuthFail, TPM_RC_FMT1 | 0x00E, "TPM_RC_AUTH_FAIL"),
332        (Nonce, TPM_RC_FMT1 | 0x00F, "TPM_RC_NONCE"),
333        (Pp, TPM_RC_FMT1 | 0x010, "TPM_RC_PP"),
334        (Scheme, TPM_RC_FMT1 | 0x012, "TPM_RC_SCHEME"),
335        (Size, TPM_RC_FMT1 | 0x015, "TPM_RC_SIZE"),
336        (Symmetric, TPM_RC_FMT1 | 0x016, "TPM_RC_SYMMETRIC"),
337        (Tag, TPM_RC_FMT1 | 0x017, "TPM_RC_TAG"),
338        (Selector, TPM_RC_FMT1 | 0x018, "TPM_RC_SELECTOR"),
339        (Insufficient, TPM_RC_FMT1 | 0x01A, "TPM_RC_INSUFFICIENT"),
340        (Signature, TPM_RC_FMT1 | 0x01B, "TPM_RC_SIGNATURE"),
341        (Key, TPM_RC_FMT1 | 0x01C, "TPM_RC_KEY"),
342        (PolicyFail, TPM_RC_FMT1 | 0x01D, "TPM_RC_POLICY_FAIL"),
343        (Integrity, TPM_RC_FMT1 | 0x01F, "TPM_RC_INTEGRITY"),
344        (Ticket, TPM_RC_FMT1 | 0x020, "TPM_RC_TICKET"),
345        (ReservedBits, TPM_RC_FMT1 | 0x021, "TPM_RC_RESERVED_BITS"),
346        (BadAuth, TPM_RC_FMT1 | 0x022, "TPM_RC_BAD_AUTH"),
347        (Expired, TPM_RC_FMT1 | 0x023, "TPM_RC_EXPIRED"),
348        (PolicyCc, TPM_RC_FMT1 | 0x024, "TPM_RC_POLICY_CC"),
349        (Binding, TPM_RC_FMT1 | 0x025, "TPM_RC_BINDING"),
350        (Curve, TPM_RC_FMT1 | 0x026, "TPM_RC_CURVE"),
351        (EccPoint, TPM_RC_FMT1 | 0x027, "TPM_RC_ECC_POINT"),
352        (FwLimited, TPM_RC_FMT1 | 0x028, "TPM_RC_FW_LIMITED"),
353        (SvnLimited, TPM_RC_FMT1 | 0x029, "TPM_RC_SVN_LIMITED"),
354        (Channel, TPM_RC_FMT1 | 0x030, "TPM_RC_CHANNEL"),
355        (ChannelKey, TPM_RC_FMT1 | 0x031, "TPM_RC_CHANNEL_KEY"),
356        (ContextGap, TPM_RC_WARN | 0x001, "TPM_RC_CONTEXT_GAP"),
357        (ObjectMemory, TPM_RC_WARN | 0x002, "TPM_RC_OBJECT_MEMORY"),
358        (SessionMemory, TPM_RC_WARN | 0x003, "TPM_RC_SESSION_MEMORY"),
359        (Memory, TPM_RC_WARN | 0x004, "TPM_RC_MEMORY"),
360        (TpmSessions, TPM_RC_WARN | 0x005, "TPM_RC_SESSION_HANDLES"),
361        (TpmTransients, TPM_RC_WARN | 0x006, "TPM_RC_OBJECT_HANDLES"),
362        (Locality, TPM_RC_WARN | 0x007, "TPM_RC_LOCALITY"),
363        (Yielded, TPM_RC_WARN | 0x008, "TPM_RC_YIELDED"),
364        (Canceled, TPM_RC_WARN | 0x009, "TPM_RC_CANCELED"),
365        (Testing, TPM_RC_WARN | 0x00A, "TPM_RC_TESTING"),
366        (ReferenceH0, TPM_RC_WARN | 0x010, "TPM_RC_REFERENCE_H0"),
367        (ReferenceH1, TPM_RC_WARN | 0x011, "TPM_RC_REFERENCE_H1"),
368        (ReferenceH2, TPM_RC_WARN | 0x012, "TPM_RC_REFERENCE_H2"),
369        (ReferenceH3, TPM_RC_WARN | 0x013, "TPM_RC_REFERENCE_H3"),
370        (ReferenceH4, TPM_RC_WARN | 0x014, "TPM_RC_REFERENCE_H4"),
371        (ReferenceH5, TPM_RC_WARN | 0x015, "TPM_RC_REFERENCE_H5"),
372        (ReferenceH6, TPM_RC_WARN | 0x016, "TPM_RC_REFERENCE_H6"),
373        (ReferenceS0, TPM_RC_WARN | 0x018, "TPM_RC_REFERENCE_S0"),
374        (ReferenceS1, TPM_RC_WARN | 0x019, "TPM_RC_REFERENCE_S1"),
375        (ReferenceS2, TPM_RC_WARN | 0x01A, "TPM_RC_REFERENCE_S2"),
376        (ReferenceS3, TPM_RC_WARN | 0x01B, "TPM_RC_REFERENCE_S3"),
377        (ReferenceS4, TPM_RC_WARN | 0x01C, "TPM_RC_REFERENCE_S4"),
378        (ReferenceS5, TPM_RC_WARN | 0x01D, "TPM_RC_REFERENCE_S5"),
379        (ReferenceS6, TPM_RC_WARN | 0x01E, "TPM_RC_REFERENCE_S6"),
380        (NvRate, TPM_RC_WARN | 0x020, "TPM_RC_NV_RATE"),
381        (Lockout, TPM_RC_WARN | 0x021, "TPM_RC_LOCKOUT"),
382        (Retry, TPM_RC_WARN | 0x022, "TPM_RC_RETRY"),
383        (NvUnavailable, TPM_RC_WARN | 0x023, "TPM_RC_NV_UNAVAILABLE"),
384        (NotUsed, 0xFFFF_FFFF, "TPM_RC_NOT_USED"),
385    }
386}
387
388#[must_use]
389#[derive(Debug, PartialEq, Eq, Copy, Clone)]
390pub struct TpmRc(u32);
391
392impl TpmRc {
393    /// Returns the base of the response code.
394    ///
395    /// # Errors
396    ///
397    /// Returns `TpmErrorKind::InternalError` if the `TpmRc` was constructed
398    /// with an invalid value, indicating a bug in the library.
399    pub fn base(self) -> Result<TpmRcBase, crate::TpmErrorKind> {
400        let value = self.0;
401        let base_code = if (value & TPM_RC_FMT1) != 0 {
402            TPM_RC_FMT1 | (value & TPM_RC_FMT1_ERROR_MASK)
403        } else {
404            value
405        };
406
407        TpmRcBase::try_from(base_code).map_err(|()| crate::TpmErrorKind::InternalError)
408    }
409
410    /// Returns the index of a parameter, handle, or session in error for format 1 response codes.
411    #[must_use]
412    pub fn index(self) -> Option<TpmRcIndex> {
413        let value = self.0;
414
415        if (value & TPM_RC_FMT1) == 0 {
416            return None;
417        }
418
419        let is_parameter = (value & TPM_RC_P_BIT) != 0;
420
421        let n = ((value >> TPM_RC_N_SHIFT) & 0b1111) as u8;
422        if n == 0 {
423            return None;
424        }
425
426        if is_parameter {
427            Some(TpmRcIndex::Parameter(n))
428        } else if n <= 7 {
429            Some(TpmRcIndex::Handle(n))
430        } else {
431            Some(TpmRcIndex::Session(n - 8))
432        }
433    }
434
435    /// Returns the raw `u32` value of the response code.
436    #[must_use]
437    pub fn value(self) -> u32 {
438        self.0
439    }
440
441    /// Returns `true` if the response code is a warning.
442    #[must_use]
443    pub fn is_warning(self) -> bool {
444        (self.0 & TPM_RC_WARN) == TPM_RC_WARN
445    }
446
447    /// Returns `true` if the response code is a fatal error.
448    #[must_use]
449    pub fn is_error(self) -> bool {
450        !self.is_warning() && self.0 != 0
451    }
452}
453
454impl TryFrom<u32> for TpmRc {
455    type Error = crate::TpmErrorKind;
456
457    fn try_from(value: u32) -> Result<Self, Self::Error> {
458        let base_code = if (value & TPM_RC_FMT1) != 0 {
459            TPM_RC_FMT1 | (value & TPM_RC_FMT1_ERROR_MASK)
460        } else {
461            value
462        };
463
464        TpmRcBase::try_from(base_code).map_err(|()| crate::TpmErrorKind::InvalidDiscriminant {
465            type_name: "TpmRcBase",
466            value: u64::from(base_code),
467        })?;
468
469        Ok(TpmRc(value))
470    }
471}
472
473impl From<TpmRc> for u32 {
474    fn from(val: TpmRc) -> Self {
475        val.0
476    }
477}
478
479impl From<TpmRcBase> for TpmRc {
480    fn from(value: TpmRcBase) -> Self {
481        TpmRc(value as u32)
482    }
483}
484
485impl Display for TpmRc {
486    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
487        match self.base() {
488            Ok(base) => {
489                if let Some(index) = self.index() {
490                    write!(f, "[{base}, {index}]")
491                } else {
492                    write!(f, "{base}")
493                }
494            }
495            Err(_) => {
496                write!(f, "TPM_RC_UNKNOWN(0x{:08X})", self.0)
497            }
498        }
499    }
500}
501
502tpm_enum! {
503    /// `TPM_RH`
504    #[derive(Debug, Default, PartialEq, Eq, Copy, Clone)]
505    pub enum TpmRh(u32) {
506        (Srk, 0x4000_0000, "TPM_RH_SRK"),
507        (Owner, 0x4000_0001, "TPM_RH_OWNER"),
508        #[default]
509        (Null, 0x4000_0007, "TPM_RH_NULL"),
510        (Unassigned, 0x4000_0008, "TPM_RH_UNASSIGNED"),
511        (Password, 0x4000_0009, "TPM_RH_PW"),
512        (Lockout, 0x4000_000A, "TPM_RH_LOCKOUT"),
513        (Endorsement, 0x4000_000B, "TPM_RH_ENDORSEMENT"),
514        (Platform, 0x4000_000C, "TPM_RH_PLATFORM"),
515        (PlatformNv, 0x4000_000D, "TPM_RH_PLATFORM_NV"),
516        (Auth00, 0x4000_0010, "TPM_RH_AUTH_00"),
517        (AuthFF, 0x4000_010F, "TPM_RH_AUTH_FF"),
518        (TransientFirst, 0x8000_0000, "First transient handle"),
519        (PersistentFirst, 0x8100_0000, "First persistent handle"),
520    }
521}
522
523tpm_enum! {
524    /// `TPM_SE`
525    #[derive(Debug, PartialEq, Eq, Copy, Clone, Default)]
526    pub enum TpmSe(u8) {
527        /// `TPM_SE_HMAC`
528        #[default]
529        (Hmac, 0x00, "TPM_SE_HMAC"),
530        /// `TPM_SE_POLICY`
531        (Policy, 0x01, "TPM_SE_POLICY"),
532        /// `TPM_SE_TRIAL`
533        (Trial, 0x03, "TPM_SE_TRIAL"),
534    }
535}
536
537tpm_enum! {
538    /// `TPM_ST`
539    #[derive(Debug, PartialEq, Eq, Copy, Clone, Default)]
540    pub enum TpmSt(u16) {
541        (RspCommand, 0x00C4, "TPM_ST_RSP_COMMAND"),
542        #[default]
543        (Null, 0x8000, "TPM_ST_NULL"),
544        (NoSessions, 0x8001, "TPM_ST_NO_SESSIONS"),
545        (Sessions, 0x8002, "TPM_ST_SESSIONS"),
546        (AttestNv, 0x8014, "TPM_ST_ATTEST_NV"),
547        (AttestCommandAudit, 0x8015, "TPM_ST_ATTEST_COMMAND_AUDIT"),
548        (AttestSessionAudit, 0x8016, "TPM_ST_ATTEST_SESSION_AUDIT"),
549        (AttestCertify, 0x8017, "TPM_ST_ATTEST_CERTIFY"),
550        (AttestQuote, 0x8018, "TPM_ST_ATTEST_QUOTE"),
551        (AttestTime, 0x8019, "TPM_ST_ATTEST_TIME"),
552        (AttestCreation, 0x801A, "TPM_ST_ATTEST_CREATION"),
553        (Creation, 0x8021, "TPM_ST_CREATION"),
554        (Verified, 0x8022, "TPM_ST_VERIFIED"),
555        (AuthSecret, 0x8023, "TPM_ST_AUTH_SECRET"),
556        (HashCheck, 0x8024, "TPM_ST_HASHCHECK"),
557        (AuthSigned, 0x8025, "TPM_ST_AUTH_SIGNED"),
558        (FuManifest, 0x8029, "TPM_ST_FU_MANIFEST"),
559    }
560}
561
562tpm_bitflags! {
563    /// `TPMA_ALGORITHM`
564    #[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
565    pub struct TpmaAlgorithm(u32) {
566        /// `TPMA_ALGORITHM_ASYMMETRIC`
567        const ASYMMETRIC = 0x0000_0001;
568        /// `TPMA_ALGORITHM_SYMMETRIC`
569        const SYMMETRIC = 0x0000_0002;
570        /// `TPMA_ALGORITHM_HASH`
571        const HASH = 0x0000_0004;
572        /// `TPMA_ALGORITHM_OBJECT`
573        const OBJECT = 0x0000_0008;
574        /// `TPMA_ALGORITHM_SIGNING`
575        const SIGNING = 0x0000_0100;
576        /// `TPMA_ALGORITHM_ENCRYPTING`
577        const ENCRYPTING = 0x0000_0200;
578        /// `TPMA_ALGORITHM_METHOD`
579        const METHOD = 0x0000_0400;
580        /// `TPMA_ALGORITHM_RSA_KEY_SIZES_1024`
581        const RSA_KEY_SIZES_1024 = 0x0001_0000;
582        /// `TPMA_ALGORITHM_RSA_KEY_SIZES_2048`
583        const RSA_KEY_SIZES_2048 = 0x0002_0000;
584        /// `TPMA_ALGORITHM_RSA_KEY_SIZES_3072`
585        const RSA_KEY_SIZES_3072 = 0x0004_0000;
586        /// `TPMA_ALGORITHM_RSA_KEY_SIZES_4096`
587        const RSA_KEY_SIZES_4096 = 0x0008_0000;
588    }
589}
590
591tpm_bitflags! {
592    /// `TPMA_LOCALITY` (Table 41)
593    #[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
594    pub struct TpmaLocality(u8) {
595        const TPM_LOC_ZERO = 0x01;
596        const TPM_LOC_ONE = 0x02;
597        const TPM_LOC_TWO = 0x04;
598        const TPM_LOC_THREE = 0x08;
599        const TPM_LOC_FOUR = 0x10;
600        const EXTENDED = 0xE0;
601    }
602}
603
604tpm_bitflags! {
605    /// `TPMA_NV` (Table 233)
606    #[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
607    pub struct TpmaNv(u32) {
608        const PPWRITE = 0x0000_0001;
609        const OWNERWRITE = 0x0000_0002;
610        const AUTHWRITE = 0x0000_0004;
611        const POLICYWRITE = 0x0000_0008;
612        const TPM_NT_ORDINARY = 0x0000_0000;
613        const TPM_NT_COUNTER = 0x0000_0010;
614        const TPM_NT_BITS = 0x0000_0020;
615        const TPM_NT_EXTEND = 0x0000_0040;
616        const TPM_NT_PIN_FAIL = 0x0000_0080;
617        const TPM_NT_PIN_PASS = 0x0000_0090;
618        const POLICY_DELETE = 0x0000_0400;
619        const WRITELOCKED = 0x0000_0800;
620        const WRITEALL = 0x0000_1000;
621        const WRITEDEFINE = 0x0000_2000;
622        const WRITE_STCLEAR = 0x0000_4000;
623        const GLOBALLOCK = 0x0000_8000;
624        const PPREAD = 0x0001_0000;
625        const OWNERREAD = 0x0002_0000;
626        const AUTHREAD = 0x0004_0000;
627        const POLICYREAD = 0x0008_0000;
628        const NO_DA = 0x0200_0000;
629        const ORDERLY = 0x0400_0000;
630        const CLEAR_STCLEAR = 0x0800_0000;
631        const READLOCKED = 0x1000_0000;
632        const WRITTEN = 0x2000_0000;
633        const PLATFORMCREATE = 0x4000_0000;
634        const READ_STCLEAR = 0x8000_0000;
635    }
636}
637
638tpm_bitflags! {
639    /// `TPMA_OBJECT`
640    #[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
641    pub struct TpmaObject(u32) {
642        /// Hierarchy is immutable
643        const FIXED_TPM = 0x0000_0002;
644        /// TPM chip reset invalidates also saved contexts
645        const ST_CLEAR = 0x0000_0004;
646        /// Parent is immutable
647        const FIXED_PARENT = 0x0000_0010;
648        /// TPM-only generated secrets
649        const SENSITIVE_DATA_ORIGIN = 0x0000_0020;
650        /// Allow user access without policy session
651        const USER_WITH_AUTH = 0x0000_0040;
652        /// Deny admin access without policy session
653        const ADMIN_WITH_POLICY = 0x0000_0080;
654        /// Deny dictionary attack protections
655        const NO_DA = 0x0000_0400;
656        /// Encrypted duplication
657        const ENCRYPTED_DUPLICATION = 0x0000_0800;
658        /// Manipulate only datas of known format
659        const RESTRICTED = 0x0001_0000;
660        /// Decrypt with the private key
661        const DECRYPT = 0x0002_0000;
662        /// Sign with the private key (for asymmetric keys) or encrypt (for symmetric keys)
663        const SIGN_ENCRYPT = 0x0004_0000;
664    }
665}
666
667tpm_bitflags! {
668    /// `TPMA_SESSION`
669    #[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
670    pub struct TpmaSession(u8) {
671        const CONTINUE_SESSION = 0x01;
672        const AUDIT_EXCLUSIVE = 0x02;
673        const AUDIT_RESET = 0x04;
674        const DECRYPT = 0x20;
675        const ENCRYPT = 0x40;
676        const AUDIT = 0x80;
677    }
678}
679
680tpm_bool! {
681    /// A TPM boolean value, corresponding to `TPMI_YES_NO`.
682    #[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
683    pub struct TpmiYesNo(bool);
684}
685
686tpml!(TpmlAlgProperty, TpmsAlgProperty, 64);
687tpml!(TpmlDigest, Tpm2bDigest, 8);
688tpml!(TpmlDigestValues, TpmtHa, 8);
689tpml!(TpmlHandle, u32, 128);
690tpml!(TpmlPcrSelection, TpmsPcrSelection, 8);
691
692pub const TPM_ST_GENERATED_VALUE: u32 = 0xFF54_4347;
693pub const TPM_PCR_SELECT_MAX: usize = 3;
694
695pub type TpmsPcrSelect = TpmBuffer<TPM_PCR_SELECT_MAX>;
696
697tpm_struct! {
698    #[derive(Debug, PartialEq, Eq, Clone, Default, Copy)]
699    pub struct TpmsAlgProperty {
700        pub alg: TpmAlgId,
701        pub alg_properties: TpmaAlgorithm,
702    }
703}
704
705#[derive(Debug, PartialEq, Eq, Clone)]
706pub struct TpmsAttest {
707    pub tag: TpmSt,
708    pub qualified_signer: Tpm2bName,
709    pub extra_data: Tpm2bData,
710    pub clock_info: TpmsClockInfo,
711    pub firmware_version: u64,
712    pub attested: TpmuAttest,
713}
714
715impl TpmTagged for TpmsAttest {
716    type Tag = TpmSt;
717    type Value = TpmuAttest;
718}
719
720impl TpmSized for TpmsAttest {
721    const SIZE: usize = TPM_MAX_COMMAND_SIZE;
722    fn len(&self) -> usize {
723        size_of::<u32>()
724            + self.tag.len()
725            + self.qualified_signer.len()
726            + self.extra_data.len()
727            + self.clock_info.len()
728            + self.firmware_version.len()
729            + self.attested.len()
730    }
731}
732
733impl TpmBuild for TpmsAttest {
734    fn build(&self, writer: &mut TpmWriter) -> TpmResult<()> {
735        TPM_ST_GENERATED_VALUE.build(writer)?;
736        self.tag.build(writer)?;
737        self.qualified_signer.build(writer)?;
738        self.extra_data.build(writer)?;
739        self.clock_info.build(writer)?;
740        self.firmware_version.build(writer)?;
741        self.attested.build(writer)
742    }
743}
744
745impl<'a> TpmParse<'a> for TpmsAttest {
746    fn parse(buf: &'a [u8]) -> TpmResult<(Self, &'a [u8])> {
747        let (magic, buf) = u32::parse(buf)?;
748        if magic != TPM_ST_GENERATED_VALUE {
749            return Err(TpmErrorKind::InvalidMagic {
750                expected: TPM_ST_GENERATED_VALUE,
751                got: magic,
752            });
753        }
754
755        let (tag, buf) = TpmSt::parse(buf)?;
756        let (qualified_signer, buf) = Tpm2bName::parse(buf)?;
757        let (extra_data, buf) = Tpm2bData::parse(buf)?;
758        let (clock_info, buf) = TpmsClockInfo::parse(buf)?;
759        let (firmware_version, buf) = u64::parse(buf)?;
760        let (attested, buf) = TpmuAttest::parse_tagged(tag, buf)?;
761
762        Ok((
763            Self {
764                tag,
765                qualified_signer,
766                extra_data,
767                clock_info,
768                firmware_version,
769                attested,
770            },
771            buf,
772        ))
773    }
774}
775
776impl Default for TpmsAttest {
777    fn default() -> Self {
778        Self {
779            tag: TpmSt::AttestQuote,
780            qualified_signer: Tpm2bName::default(),
781            extra_data: Tpm2bData::default(),
782            clock_info: TpmsClockInfo::default(),
783            firmware_version: 0,
784            attested: TpmuAttest::default(),
785        }
786    }
787}
788
789tpm_struct! {
790    #[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
791    pub struct TpmsAuthCommand {
792        pub session_handle: crate::TpmSession,
793        pub nonce: Tpm2bNonce,
794        pub session_attributes: TpmaSession,
795        pub hmac: Tpm2bAuth,
796    }
797}
798
799tpm_struct! {
800    #[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
801    pub struct TpmsAuthResponse {
802        pub nonce: Tpm2bNonce,
803        pub session_attributes: TpmaSession,
804        pub hmac: Tpm2bAuth,
805    }
806}
807
808#[derive(Debug, PartialEq, Eq, Clone)]
809pub struct TpmsCapabilityData {
810    pub capability: TpmCap,
811    pub data: TpmuCapabilities,
812}
813
814impl TpmTagged for TpmsCapabilityData {
815    type Tag = TpmCap;
816    type Value = ();
817}
818
819impl TpmSized for TpmsCapabilityData {
820    const SIZE: usize = size_of::<u32>() + TpmuCapabilities::SIZE;
821    fn len(&self) -> usize {
822        self.capability.len() + self.data.len()
823    }
824}
825
826impl TpmBuild for TpmsCapabilityData {
827    fn build(&self, writer: &mut TpmWriter) -> TpmResult<()> {
828        self.capability.build(writer)?;
829        self.data.build(writer)
830    }
831}
832
833impl<'a> TpmParse<'a> for TpmsCapabilityData {
834    fn parse(buf: &'a [u8]) -> TpmResult<(Self, &'a [u8])> {
835        let (capability, buf) = TpmCap::parse(buf)?;
836        let (data, buf) = TpmuCapabilities::parse_tagged(capability, buf)?;
837        Ok((Self { capability, data }, buf))
838    }
839}
840
841tpm_struct! {
842    /// From TPM 2.0 Part 2, 10.12.3, `TPMS_CERTIFY_INFO`
843    #[derive(Debug, PartialEq, Eq, Clone, Default, Copy)]
844    pub struct TpmsCertifyInfo {
845        pub name: Tpm2bName,
846        pub qualified_name: Tpm2bName,
847    }
848}
849
850tpm_struct! {
851    /// From TPM 2.0 Part 2, 10.6, `TPMS_CLOCK_INFO`
852    #[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
853    pub struct TpmsClockInfo {
854        pub clock: u64,
855        pub reset_count: u32,
856        pub restart_count: u32,
857        pub safe: TpmiYesNo,
858    }
859}
860
861tpm_struct! {
862    /// From TPM 2.0 Part 2, 10.12.6, `TPMS_COMMAND_AUDIT_INFO`
863    #[derive(Debug, PartialEq, Eq, Clone, Default, Copy)]
864    pub struct TpmsCommandAuditInfo {
865        pub audit_counter: u64,
866        pub digest_alg: TpmAlgId,
867        pub audit_digest: Tpm2bDigest,
868        pub command_digest: Tpm2bDigest,
869    }
870}
871
872tpm_struct! {
873    #[derive(Debug, PartialEq, Eq, Clone)]
874    pub struct TpmsContext {
875        pub sequence: u64,
876        pub saved_handle: crate::TpmTransient,
877        pub hierarchy: TpmRh,
878        pub context_blob: Tpm2b,
879    }
880}
881
882tpm_struct! {
883    #[derive(Debug, PartialEq, Eq, Clone, Default)]
884    pub struct TpmsContextData {
885        pub integrity: Tpm2bDigest,
886        pub encrypted: Tpm2bSensitive,
887    }
888}
889
890tpm_struct! {
891    #[derive(Debug, PartialEq, Eq, Clone, Default)]
892    pub struct TpmsCreationData {
893        pub pcr_select: TpmlPcrSelection,
894        pub pcr_digest: Tpm2bDigest,
895        pub locality: TpmaLocality,
896        pub parent_name_alg: TpmAlgId,
897        pub parent_name: Tpm2bName,
898        pub parent_qualified_name: Tpm2bName,
899        pub outside_info: Tpm2bData,
900    }
901}
902
903tpm_struct! {
904    /// From TPM 2.0 Part 2, 10.12.5, `TPMS_CREATION_INFO`
905    #[derive(Debug, PartialEq, Eq, Clone, Default, Copy)]
906    pub struct TpmsCreationInfo {
907        pub object_name: Tpm2bName,
908        pub creation_hash: Tpm2bDigest,
909    }
910}
911
912tpm_struct! {
913    #[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
914    pub struct TpmsEccPoint {
915        pub x: Tpm2bEccParameter,
916        pub y: Tpm2bEccParameter,
917    }
918}
919
920tpm_struct! {
921    #[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
922    pub struct TpmsEmpty {}
923}
924
925tpm_struct! {
926    #[derive(Debug, PartialEq, Eq, Clone, Default)]
927    pub struct TpmsIdObject {
928        pub integrity_hmac: Tpm2bDigest,
929        pub enc_identity: Tpm2bDigest,
930    }
931}
932
933tpm_struct! {
934    #[derive(Debug, PartialEq, Eq, Clone, Default, Copy)]
935    pub struct TpmsKeyedhashParms {
936        pub scheme: TpmtScheme,
937    }
938}
939
940tpm_struct! {
941    #[derive(Debug, PartialEq, Eq, Clone, Default, Copy)]
942    pub struct TpmsNvCertifyInfo {
943        pub index_name: Tpm2bName,
944        pub offset: u16,
945        pub nv_contents: Tpm2bMaxNvBuffer,
946    }
947}
948
949tpm_struct! {
950    #[derive(Debug, PartialEq, Eq, Clone, Default, Copy)]
951    pub struct TpmsNvPublic {
952        pub nv_index: u32,
953        pub name_alg: TpmAlgId,
954        pub attributes: TpmaNv,
955        pub auth_policy: Tpm2bDigest,
956        pub data_size: u16,
957    }
958}
959
960#[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
961pub struct TpmsPcrSelection {
962    pub hash: TpmAlgId,
963    pub pcr_select: TpmsPcrSelect,
964}
965
966impl TpmSized for TpmsPcrSelection {
967    const SIZE: usize = TpmAlgId::SIZE + 1 + TPM_PCR_SELECT_MAX;
968
969    fn len(&self) -> usize {
970        self.hash.len() + 1 + self.pcr_select.deref().len()
971    }
972}
973
974impl TpmBuild for TpmsPcrSelection {
975    fn build(&self, writer: &mut TpmWriter) -> TpmResult<()> {
976        self.hash.build(writer)?;
977        let size =
978            u8::try_from(self.pcr_select.deref().len()).map_err(|_| TpmErrorKind::ValueTooLarge)?;
979        size.build(writer)?;
980        writer.write_bytes(&self.pcr_select)
981    }
982}
983
984impl<'a> TpmParse<'a> for TpmsPcrSelection {
985    fn parse(buf: &'a [u8]) -> TpmResult<(Self, &'a [u8])> {
986        let (hash, buf) = TpmAlgId::parse(buf)?;
987        let (size, buf) = u8::parse(buf)?;
988        let size = size as usize;
989
990        if size > TPM_PCR_SELECT_MAX {
991            return Err(TpmErrorKind::ValueTooLarge);
992        }
993        if buf.len() < size {
994            return Err(TpmErrorKind::Boundary);
995        }
996
997        let (pcr_bytes, buf) = buf.split_at(size);
998        let pcr_select = TpmBuffer::try_from(pcr_bytes)?;
999
1000        Ok((Self { hash, pcr_select }, buf))
1001    }
1002}
1003
1004tpm_struct! {
1005    #[derive(Debug, PartialEq, Eq, Clone, Default)]
1006    pub struct TpmsQuoteInfo {
1007        pub pcr_select: TpmlPcrSelection,
1008        pub pcr_digest: Tpm2bDigest,
1009    }
1010}
1011
1012tpm_struct! {
1013    #[derive(Debug, PartialEq, Eq, Clone, Default)]
1014    pub struct TpmsSensitiveCreate {
1015        pub user_auth: Tpm2bAuth,
1016        pub data: Tpm2bSensitiveData,
1017    }
1018}
1019
1020tpm_struct! {
1021    #[derive(Debug, PartialEq, Eq, Clone, Default, Copy)]
1022    pub struct TpmsSessionAuditInfo {
1023        pub exclusive_session: TpmiYesNo,
1024        pub session_digest: Tpm2bDigest,
1025    }
1026}
1027
1028tpm_struct! {
1029    #[derive(Debug, PartialEq, Eq, Clone, Default, Copy)]
1030    pub struct TpmsSymcipherParms {
1031        pub sym: TpmtSymDefObject,
1032    }
1033}
1034
1035tpm_struct! {
1036    #[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
1037    pub struct TpmsTimeAttestInfo {
1038        pub time: TpmsTimeInfo,
1039        pub firmware_version: u64,
1040    }
1041}
1042
1043tpm_struct! {
1044    #[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
1045    pub struct TpmsTimeInfo {
1046        pub time: u64,
1047        pub clock_info: TpmsClockInfo,
1048    }
1049}
1050
1051#[derive(Debug, PartialEq, Eq, Clone, Copy)]
1052pub enum TpmuSymMode {
1053    Aes(TpmAlgId),
1054    Sm4(TpmAlgId),
1055    Camellia(TpmAlgId),
1056    Xor,
1057    Null,
1058}
1059
1060impl TpmTagged for TpmuSymMode {
1061    type Tag = TpmAlgId;
1062    type Value = ();
1063}
1064
1065impl Default for TpmuSymMode {
1066    fn default() -> Self {
1067        Self::Null
1068    }
1069}
1070
1071impl TpmSized for TpmuSymMode {
1072    const SIZE: usize = core::mem::size_of::<u16>();
1073    fn len(&self) -> usize {
1074        match self {
1075            Self::Aes(val) | Self::Sm4(val) | Self::Camellia(val) => val.len(),
1076            Self::Xor | Self::Null => 0,
1077        }
1078    }
1079}
1080
1081impl<'a> TpmParseTagged<'a> for TpmuSymMode {
1082    fn parse_tagged(tag: TpmAlgId, buf: &'a [u8]) -> TpmResult<(Self, &'a [u8])> {
1083        match tag {
1084            TpmAlgId::Aes => {
1085                let (val, buf) = TpmAlgId::parse(buf)?;
1086                Ok((Self::Aes(val), buf))
1087            }
1088            TpmAlgId::Sm4 => {
1089                let (val, buf) = TpmAlgId::parse(buf)?;
1090                Ok((Self::Sm4(val), buf))
1091            }
1092            TpmAlgId::Camellia => {
1093                let (val, buf) = TpmAlgId::parse(buf)?;
1094                Ok((Self::Camellia(val), buf))
1095            }
1096            TpmAlgId::Xor => Ok((Self::Xor, buf)),
1097            TpmAlgId::Null => Ok((Self::Null, buf)),
1098            _ => Err(TpmErrorKind::InvalidValue),
1099        }
1100    }
1101}
1102
1103impl TpmBuild for TpmuSymMode {
1104    fn build(&self, writer: &mut TpmWriter) -> TpmResult<()> {
1105        match self {
1106            TpmuSymMode::Aes(val) | TpmuSymMode::Sm4(val) | TpmuSymMode::Camellia(val) => {
1107                val.build(writer)
1108            }
1109            TpmuSymMode::Xor | TpmuSymMode::Null => Ok(()),
1110        }
1111    }
1112}
1113
1114#[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
1115pub struct TpmtHa {
1116    pub hash_alg: TpmAlgId,
1117    pub digest: TpmuHa,
1118}
1119
1120impl TpmTagged for TpmtHa {
1121    type Tag = TpmAlgId;
1122    type Value = TpmuHa;
1123}
1124
1125impl TpmSized for TpmtHa {
1126    const SIZE: usize = size_of::<u16>() + TpmuHa::SIZE;
1127    fn len(&self) -> usize {
1128        self.hash_alg.len() + self.digest.len()
1129    }
1130}
1131
1132impl TpmBuild for TpmtHa {
1133    fn build(&self, writer: &mut TpmWriter) -> TpmResult<()> {
1134        self.hash_alg.build(writer)?;
1135        self.digest.build(writer)
1136    }
1137}
1138
1139impl<'a> TpmParse<'a> for TpmtHa {
1140    fn parse(buf: &'a [u8]) -> TpmResult<(Self, &'a [u8])> {
1141        let (hash_alg, buf) = TpmAlgId::parse(buf)?;
1142        let (digest, buf) = TpmuHa::parse_tagged(hash_alg, buf)?;
1143        Ok((Self { hash_alg, digest }, buf))
1144    }
1145}
1146
1147tpm_struct! {
1148    /// A TPM key derivation function scheme, corresponding to `TPMT_KDF_SCHEME`.
1149    #[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
1150    pub struct TpmtKdfScheme {
1151        pub scheme: TpmAlgId,
1152    }
1153}
1154
1155#[derive(Debug, PartialEq, Eq, Clone)]
1156pub struct TpmtPublic {
1157    pub object_type: TpmAlgId,
1158    pub name_alg: TpmAlgId,
1159    pub object_attributes: TpmaObject,
1160    pub auth_policy: Tpm2bDigest,
1161    pub parameters: TpmuPublicParms,
1162    pub unique: TpmuPublicId,
1163}
1164
1165impl TpmTagged for TpmtPublic {
1166    type Tag = TpmAlgId;
1167    type Value = TpmuPublicParms;
1168}
1169
1170impl TpmSized for TpmtPublic {
1171    const SIZE: usize = TPM_MAX_COMMAND_SIZE;
1172    fn len(&self) -> usize {
1173        self.object_type.len()
1174            + self.name_alg.len()
1175            + self.object_attributes.len()
1176            + self.auth_policy.len()
1177            + self.parameters.len()
1178            + self.unique.len()
1179    }
1180}
1181
1182impl TpmBuild for TpmtPublic {
1183    fn build(&self, writer: &mut TpmWriter) -> TpmResult<()> {
1184        self.object_type.build(writer)?;
1185        self.name_alg.build(writer)?;
1186        self.object_attributes.build(writer)?;
1187        self.auth_policy.build(writer)?;
1188        self.parameters.build(writer)?;
1189        self.unique.build(writer)
1190    }
1191}
1192
1193impl<'a> TpmParse<'a> for TpmtPublic {
1194    fn parse(buf: &'a [u8]) -> TpmResult<(Self, &'a [u8])> {
1195        let (object_type, mut buf) = TpmAlgId::parse(buf)?;
1196        let (name_alg, rest) = TpmAlgId::parse(buf)?;
1197        buf = rest;
1198        let (object_attributes, rest) = TpmaObject::parse(buf)?;
1199        buf = rest;
1200        let (auth_policy, rest) = Tpm2bDigest::parse(buf)?;
1201        buf = rest;
1202        let (parameters, rest) = TpmuPublicParms::parse_tagged(object_type, buf)?;
1203        buf = rest;
1204        let (unique, rest) = TpmuPublicId::parse_tagged(object_type, buf)?;
1205        buf = rest;
1206
1207        let public_area = Self {
1208            object_type,
1209            name_alg,
1210            object_attributes,
1211            auth_policy,
1212            parameters,
1213            unique,
1214        };
1215
1216        Ok((public_area, buf))
1217    }
1218}
1219
1220impl Default for TpmtPublic {
1221    fn default() -> Self {
1222        Self {
1223            object_type: TpmAlgId::Null,
1224            name_alg: TpmAlgId::Sha256,
1225            object_attributes: TpmaObject::empty(),
1226            auth_policy: Tpm2bDigest::default(),
1227            parameters: TpmuPublicParms::Null,
1228            unique: TpmuPublicId::Null,
1229        }
1230    }
1231}
1232
1233tpm_struct! {
1234    /// A TPM signing scheme, corresponding to `TPMT_SIG_SCHEME`.
1235    #[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
1236    pub struct TpmtScheme {
1237        pub scheme: TpmAlgId,
1238    }
1239}
1240
1241#[derive(Debug, PartialEq, Eq, Clone, Default)]
1242pub struct TpmtSensitive {
1243    pub sensitive_type: TpmAlgId,
1244    pub auth_value: Tpm2bAuth,
1245    pub seed_value: Tpm2bDigest,
1246    pub sensitive: TpmuSensitiveComposite,
1247}
1248
1249impl TpmTagged for TpmtSensitive {
1250    type Tag = TpmAlgId;
1251    type Value = TpmuSensitiveComposite;
1252}
1253
1254impl TpmtSensitive {
1255    /// Constructs a `TpmtSensitive` from a given key algorithm and raw private key bytes.
1256    ///
1257    /// # Errors
1258    ///
1259    /// Returns a `TpmErrorKind::InvalidValue` if the key algorithm is not supported for this operation.
1260    pub fn from_private_bytes(
1261        key_alg: TpmAlgId,
1262        private_bytes: &[u8],
1263    ) -> Result<Self, TpmErrorKind> {
1264        let sensitive = match key_alg {
1265            TpmAlgId::Rsa => {
1266                TpmuSensitiveComposite::Rsa(Tpm2bPrivateKeyRsa::try_from(private_bytes)?)
1267            }
1268            TpmAlgId::Ecc => {
1269                TpmuSensitiveComposite::Ecc(Tpm2bEccParameter::try_from(private_bytes)?)
1270            }
1271            TpmAlgId::KeyedHash => {
1272                TpmuSensitiveComposite::Bits(Tpm2bSensitiveData::try_from(private_bytes)?)
1273            }
1274            TpmAlgId::SymCipher => {
1275                TpmuSensitiveComposite::Sym(Tpm2bSymKey::try_from(private_bytes)?)
1276            }
1277            _ => return Err(TpmErrorKind::InvalidValue),
1278        };
1279
1280        Ok(Self {
1281            sensitive_type: key_alg,
1282            auth_value: Tpm2bAuth::default(),
1283            seed_value: Tpm2bDigest::default(),
1284            sensitive,
1285        })
1286    }
1287}
1288
1289impl TpmSized for TpmtSensitive {
1290    const SIZE: usize =
1291        size_of::<TpmAlgId>() + Tpm2bAuth::SIZE + Tpm2bDigest::SIZE + TpmuSensitiveComposite::SIZE;
1292    fn len(&self) -> usize {
1293        self.sensitive_type.len()
1294            + self.auth_value.len()
1295            + self.seed_value.len()
1296            + self.sensitive.len()
1297    }
1298}
1299
1300impl TpmBuild for TpmtSensitive {
1301    fn build(&self, writer: &mut TpmWriter) -> TpmResult<()> {
1302        self.sensitive_type.build(writer)?;
1303        self.auth_value.build(writer)?;
1304        self.seed_value.build(writer)?;
1305        self.sensitive.build(writer)
1306    }
1307}
1308
1309impl<'a> TpmParse<'a> for TpmtSensitive {
1310    fn parse(buf: &'a [u8]) -> TpmResult<(Self, &'a [u8])> {
1311        let (sensitive_type, buf) = TpmAlgId::parse(buf)?;
1312        let (auth_value, buf) = Tpm2bAuth::parse(buf)?;
1313        let (seed_value, buf) = Tpm2bDigest::parse(buf)?;
1314        let (sensitive, buf) = TpmuSensitiveComposite::parse_tagged(sensitive_type, buf)?;
1315
1316        Ok((
1317            Self {
1318                sensitive_type,
1319                auth_value,
1320                seed_value,
1321                sensitive,
1322            },
1323            buf,
1324        ))
1325    }
1326}
1327
1328#[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
1329pub struct TpmtSymDef {
1330    pub algorithm: TpmAlgId,
1331    pub key_bits: TpmuSymKeyBits,
1332    pub mode: TpmuSymMode,
1333}
1334
1335impl TpmTagged for TpmtSymDef {
1336    type Tag = TpmAlgId;
1337    type Value = TpmuSymKeyBits;
1338}
1339
1340impl TpmSized for TpmtSymDef {
1341    const SIZE: usize = TpmAlgId::SIZE + TpmuSymKeyBits::SIZE + TpmAlgId::SIZE;
1342    fn len(&self) -> usize {
1343        if self.algorithm == TpmAlgId::Null {
1344            self.algorithm.len()
1345        } else {
1346            self.algorithm.len() + self.key_bits.len() + self.mode.len()
1347        }
1348    }
1349}
1350
1351impl TpmBuild for TpmtSymDef {
1352    fn build(&self, writer: &mut TpmWriter) -> TpmResult<()> {
1353        self.algorithm.build(writer)?;
1354        if self.algorithm != TpmAlgId::Null {
1355            self.key_bits.build(writer)?;
1356            self.mode.build(writer)?;
1357        }
1358        Ok(())
1359    }
1360}
1361
1362impl<'a> TpmParse<'a> for TpmtSymDef {
1363    fn parse(buf: &'a [u8]) -> TpmResult<(Self, &'a [u8])> {
1364        let (algorithm, buf) = TpmAlgId::parse(buf)?;
1365        if algorithm == TpmAlgId::Null {
1366            Ok((
1367                Self {
1368                    algorithm,
1369                    key_bits: TpmuSymKeyBits::Null,
1370                    mode: TpmuSymMode::Null,
1371                },
1372                buf,
1373            ))
1374        } else {
1375            let (key_bits, buf) = TpmuSymKeyBits::parse_tagged(algorithm, buf)?;
1376            let (mode, buf) = TpmuSymMode::parse_tagged(algorithm, buf)?;
1377            Ok((
1378                Self {
1379                    algorithm,
1380                    key_bits,
1381                    mode,
1382                },
1383                buf,
1384            ))
1385        }
1386    }
1387}
1388
1389pub type TpmtSymDefObject = TpmtSymDef;
1390
1391tpm_struct! {
1392    #[derive(Debug, PartialEq, Eq, Clone, Default)]
1393    pub struct TpmtTkAuth {
1394        pub tag: TpmSt,
1395        pub hierarchy: TpmRh,
1396        pub digest: Tpm2bDigest,
1397    }
1398}
1399
1400tpm_struct! {
1401    #[derive(Debug, PartialEq, Eq, Clone, Default)]
1402    pub struct TpmtTkCreation {
1403        pub tag: TpmSt,
1404        pub hierarchy: TpmRh,
1405        pub digest: Tpm2bDigest,
1406    }
1407}
1408
1409tpm_struct! {
1410    #[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
1411    pub struct TpmtTkHashcheck {
1412        pub tag: TpmSt,
1413        pub hierarchy: TpmRh,
1414        pub digest: Tpm2bDigest,
1415    }
1416}
1417
1418#[allow(clippy::large_enum_variant)]
1419#[derive(Debug, PartialEq, Eq, Clone)]
1420pub enum TpmuAttest {
1421    Certify(TpmsCertifyInfo),
1422    Creation(TpmsCreationInfo),
1423    Quote(TpmsQuoteInfo),
1424    CommandAudit(TpmsCommandAuditInfo),
1425    SessionAudit(TpmsSessionAuditInfo),
1426    Time(TpmsTimeAttestInfo),
1427    Nv(TpmsNvCertifyInfo),
1428}
1429
1430impl TpmTagged for TpmuAttest {
1431    type Tag = TpmSt;
1432    type Value = ();
1433}
1434
1435impl TpmSized for TpmuAttest {
1436    const SIZE: usize = TPM_MAX_COMMAND_SIZE;
1437    fn len(&self) -> usize {
1438        match self {
1439            Self::Certify(val) => val.len(),
1440            Self::Creation(val) => val.len(),
1441            Self::Quote(val) => val.len(),
1442            Self::CommandAudit(val) => val.len(),
1443            Self::SessionAudit(val) => val.len(),
1444            Self::Time(val) => val.len(),
1445            Self::Nv(val) => val.len(),
1446        }
1447    }
1448}
1449
1450impl TpmBuild for TpmuAttest {
1451    fn build(&self, writer: &mut TpmWriter) -> TpmResult<()> {
1452        match self {
1453            Self::Certify(val) => val.build(writer),
1454            Self::Creation(val) => val.build(writer),
1455            Self::Quote(val) => val.build(writer),
1456            Self::CommandAudit(val) => val.build(writer),
1457            Self::SessionAudit(val) => val.build(writer),
1458            Self::Time(val) => val.build(writer),
1459            Self::Nv(val) => val.build(writer),
1460        }
1461    }
1462}
1463
1464impl<'a> TpmParseTagged<'a> for TpmuAttest {
1465    fn parse_tagged(tag: TpmSt, buf: &'a [u8]) -> TpmResult<(Self, &'a [u8])> {
1466        match tag {
1467            TpmSt::AttestCertify => {
1468                let (val, buf) = TpmsCertifyInfo::parse(buf)?;
1469                Ok((Self::Certify(val), buf))
1470            }
1471            TpmSt::AttestCreation => {
1472                let (val, buf) = TpmsCreationInfo::parse(buf)?;
1473                Ok((Self::Creation(val), buf))
1474            }
1475            TpmSt::AttestQuote => {
1476                let (val, buf) = TpmsQuoteInfo::parse(buf)?;
1477                Ok((Self::Quote(val), buf))
1478            }
1479            TpmSt::AttestCommandAudit => {
1480                let (val, buf) = TpmsCommandAuditInfo::parse(buf)?;
1481                Ok((Self::CommandAudit(val), buf))
1482            }
1483            TpmSt::AttestSessionAudit => {
1484                let (val, buf) = TpmsSessionAuditInfo::parse(buf)?;
1485                Ok((Self::SessionAudit(val), buf))
1486            }
1487            TpmSt::AttestTime => {
1488                let (val, buf) = TpmsTimeAttestInfo::parse(buf)?;
1489                Ok((Self::Time(val), buf))
1490            }
1491            TpmSt::AttestNv => {
1492                let (val, buf) = TpmsNvCertifyInfo::parse(buf)?;
1493                Ok((Self::Nv(val), buf))
1494            }
1495            _ => Err(TpmErrorKind::InvalidValue),
1496        }
1497    }
1498}
1499
1500impl Default for TpmuAttest {
1501    fn default() -> Self {
1502        Self::Quote(TpmsQuoteInfo::default())
1503    }
1504}
1505
1506#[derive(Debug, PartialEq, Eq, Clone)]
1507pub enum TpmuCapabilities {
1508    Algs(TpmlAlgProperty),
1509    Handles(TpmlHandle),
1510    Pcrs(TpmlPcrSelection),
1511}
1512
1513impl TpmTagged for TpmuCapabilities {
1514    type Tag = TpmCap;
1515    type Value = ();
1516}
1517
1518impl TpmSized for TpmuCapabilities {
1519    const SIZE: usize = TPM_MAX_COMMAND_SIZE;
1520    fn len(&self) -> usize {
1521        match self {
1522            Self::Algs(algs) => algs.len(),
1523            Self::Handles(handles) => handles.len(),
1524            Self::Pcrs(pcrs) => pcrs.len(),
1525        }
1526    }
1527}
1528
1529impl TpmBuild for TpmuCapabilities {
1530    fn build(&self, writer: &mut TpmWriter) -> TpmResult<()> {
1531        match self {
1532            TpmuCapabilities::Algs(algs) => algs.build(writer),
1533            TpmuCapabilities::Handles(handles) => handles.build(writer),
1534            TpmuCapabilities::Pcrs(pcrs) => pcrs.build(writer),
1535        }
1536    }
1537}
1538
1539impl<'a> TpmParseTagged<'a> for TpmuCapabilities {
1540    fn parse_tagged(tag: TpmCap, buf: &'a [u8]) -> TpmResult<(Self, &'a [u8])> {
1541        match tag {
1542            TpmCap::Algs => {
1543                let (algs, buf) = TpmlAlgProperty::parse(buf)?;
1544                Ok((TpmuCapabilities::Algs(algs), buf))
1545            }
1546            TpmCap::Handles => {
1547                let (handles, buf) = TpmlHandle::parse(buf)?;
1548                Ok((TpmuCapabilities::Handles(handles), buf))
1549            }
1550            TpmCap::Pcrs => {
1551                let (pcrs, buf) = TpmlPcrSelection::parse(buf)?;
1552                Ok((TpmuCapabilities::Pcrs(pcrs), buf))
1553            }
1554            _ => Err(TpmErrorKind::InvalidValue),
1555        }
1556    }
1557}
1558
1559#[derive(Debug, PartialEq, Eq, Clone, Copy)]
1560pub enum TpmuHa {
1561    Sha1([u8; 20]),
1562    Sha256([u8; 32]),
1563    Sha384([u8; 48]),
1564    Sha512([u8; 64]),
1565    Sm3_256([u8; 32]),
1566}
1567
1568impl TpmTagged for TpmuHa {
1569    type Tag = TpmAlgId;
1570    type Value = ();
1571}
1572
1573impl TpmBuild for TpmuHa {
1574    fn build(&self, writer: &mut TpmWriter) -> TpmResult<()> {
1575        writer.write_bytes(self)
1576    }
1577}
1578
1579impl<'a> TpmParseTagged<'a> for TpmuHa {
1580    fn parse_tagged(tag: TpmAlgId, buf: &'a [u8]) -> TpmResult<(Self, &'a [u8])> {
1581        let digest_size = tpm_hash_size(&tag).ok_or(TpmErrorKind::InvalidValue)?;
1582        if buf.len() < digest_size {
1583            return Err(TpmErrorKind::Boundary);
1584        }
1585
1586        let (digest_bytes, buf) = buf.split_at(digest_size);
1587
1588        macro_rules! match_hash_alg_to_digest_variant {
1589            ($tag:expr, $bytes:expr) => {
1590                match $tag {
1591                    TpmAlgId::Sha1 => {
1592                        TpmuHa::Sha1($bytes.try_into().map_err(|_| TpmErrorKind::InternalError)?)
1593                    }
1594                    TpmAlgId::Sha256 => {
1595                        TpmuHa::Sha256($bytes.try_into().map_err(|_| TpmErrorKind::InternalError)?)
1596                    }
1597                    TpmAlgId::Sha384 => {
1598                        TpmuHa::Sha384($bytes.try_into().map_err(|_| TpmErrorKind::InternalError)?)
1599                    }
1600                    TpmAlgId::Sha512 => {
1601                        TpmuHa::Sha512($bytes.try_into().map_err(|_| TpmErrorKind::InternalError)?)
1602                    }
1603                    TpmAlgId::Sm3_256 => {
1604                        TpmuHa::Sm3_256($bytes.try_into().map_err(|_| TpmErrorKind::InternalError)?)
1605                    }
1606                    _ => return Err(TpmErrorKind::InvalidValue),
1607                }
1608            };
1609        }
1610
1611        let digest = match_hash_alg_to_digest_variant!(tag, digest_bytes);
1612
1613        Ok((digest, buf))
1614    }
1615}
1616
1617impl Default for TpmuHa {
1618    fn default() -> Self {
1619        Self::Sha256([0; 32])
1620    }
1621}
1622
1623impl TpmSized for TpmuHa {
1624    const SIZE: usize = 64;
1625    fn len(&self) -> usize {
1626        match self {
1627            Self::Sha1(d) => d.len(),
1628            Self::Sha256(d) | Self::Sm3_256(d) => d.len(),
1629            Self::Sha384(d) => d.len(),
1630            Self::Sha512(d) => d.len(),
1631        }
1632    }
1633}
1634
1635impl Deref for TpmuHa {
1636    type Target = [u8];
1637
1638    fn deref(&self) -> &Self::Target {
1639        match self {
1640            Self::Sha1(d) => d,
1641            Self::Sha256(d) | Self::Sm3_256(d) => d,
1642            Self::Sha384(d) => d,
1643            Self::Sha512(d) => d,
1644        }
1645    }
1646}
1647
1648#[allow(clippy::large_enum_variant)]
1649#[derive(Debug, PartialEq, Eq, Clone)]
1650pub enum TpmuPublicId {
1651    KeyedHash(Tpm2bDigest),
1652    SymCipher(Tpm2bSymKey),
1653    Rsa(Tpm2bPublicKeyRsa),
1654    Ecc(TpmsEccPoint),
1655    Null,
1656}
1657
1658impl TpmTagged for TpmuPublicId {
1659    type Tag = TpmAlgId;
1660    type Value = ();
1661}
1662
1663impl TpmSized for TpmuPublicId {
1664    const SIZE: usize = TPM_MAX_COMMAND_SIZE;
1665    fn len(&self) -> usize {
1666        match self {
1667            Self::KeyedHash(data) => data.len(),
1668            Self::SymCipher(data) => data.len(),
1669            Self::Rsa(data) => data.len(),
1670            Self::Ecc(point) => point.len(),
1671            Self::Null => 0,
1672        }
1673    }
1674}
1675
1676impl TpmBuild for TpmuPublicId {
1677    fn build(&self, writer: &mut TpmWriter) -> TpmResult<()> {
1678        match self {
1679            TpmuPublicId::KeyedHash(data) => data.build(writer),
1680            TpmuPublicId::SymCipher(data) => data.build(writer),
1681            TpmuPublicId::Rsa(data) => data.build(writer),
1682            TpmuPublicId::Ecc(point) => point.build(writer),
1683            TpmuPublicId::Null => Ok(()),
1684        }
1685    }
1686}
1687
1688impl<'a> TpmParseTagged<'a> for TpmuPublicId {
1689    /// Parses `TpmuPublicId` from the given buffer
1690    ///
1691    /// # Errors
1692    ///
1693    /// * `TpmErrorKind::Boundary` if the buffer is too small to contain the object.
1694    /// * `TpmErrorKind::InvalidValue` if a value in the buffer is invalid for the target type.
1695    fn parse_tagged(tag: TpmAlgId, buf: &'a [u8]) -> TpmResult<(Self, &'a [u8])> {
1696        match tag {
1697            TpmAlgId::KeyedHash => {
1698                let (val, rest) = Tpm2bDigest::parse(buf)?;
1699                Ok((Self::KeyedHash(val), rest))
1700            }
1701            TpmAlgId::SymCipher => {
1702                let (val, rest) = Tpm2bSymKey::parse(buf)?;
1703                Ok((Self::SymCipher(val), rest))
1704            }
1705            TpmAlgId::Rsa => {
1706                let (val, rest) = Tpm2bPublicKeyRsa::parse(buf)?;
1707                Ok((Self::Rsa(val), rest))
1708            }
1709            TpmAlgId::Ecc => {
1710                let (point, rest) = TpmsEccPoint::parse(buf)?;
1711                Ok((Self::Ecc(point), rest))
1712            }
1713            TpmAlgId::Null => Ok((Self::Null, buf)),
1714            _ => Err(TpmErrorKind::InvalidValue),
1715        }
1716    }
1717}
1718
1719impl Default for TpmuPublicId {
1720    fn default() -> Self {
1721        Self::Null
1722    }
1723}
1724
1725#[derive(Debug, PartialEq, Eq, Clone)]
1726pub enum TpmuPublicParms {
1727    KeyedHash {
1728        details: TpmsKeyedhashParms,
1729    },
1730    SymCipher {
1731        details: TpmsSymcipherParms,
1732    },
1733    Rsa {
1734        symmetric: TpmtSymDefObject,
1735        scheme: TpmtScheme,
1736        key_bits: u16,
1737        exponent: u32,
1738    },
1739    Ecc {
1740        symmetric: TpmtSymDefObject,
1741        scheme: TpmtScheme,
1742        curve_id: TpmEccCurve,
1743        kdf: TpmtKdfScheme,
1744    },
1745    Null,
1746}
1747
1748impl TpmTagged for TpmuPublicParms {
1749    type Tag = TpmAlgId;
1750    type Value = ();
1751}
1752
1753impl TpmSized for TpmuPublicParms {
1754    const SIZE: usize = TPM_MAX_COMMAND_SIZE;
1755    fn len(&self) -> usize {
1756        match self {
1757            Self::KeyedHash { details } => details.len(),
1758            Self::SymCipher { details } => details.len(),
1759            Self::Rsa {
1760                symmetric,
1761                scheme,
1762                key_bits,
1763                exponent,
1764            } => symmetric.len() + scheme.len() + key_bits.len() + exponent.len(),
1765            Self::Ecc {
1766                symmetric,
1767                scheme,
1768                curve_id,
1769                kdf,
1770            } => symmetric.len() + scheme.len() + curve_id.len() + kdf.len(),
1771            Self::Null => 0,
1772        }
1773    }
1774}
1775
1776impl TpmBuild for TpmuPublicParms {
1777    fn build(&self, writer: &mut TpmWriter) -> TpmResult<()> {
1778        match self {
1779            TpmuPublicParms::KeyedHash { details } => details.build(writer),
1780            TpmuPublicParms::SymCipher { details } => details.build(writer),
1781            TpmuPublicParms::Rsa {
1782                symmetric,
1783                scheme,
1784                key_bits,
1785                exponent,
1786            } => {
1787                symmetric.build(writer)?;
1788                scheme.build(writer)?;
1789                key_bits.build(writer)?;
1790                exponent.build(writer)
1791            }
1792            TpmuPublicParms::Ecc {
1793                symmetric,
1794                scheme,
1795                curve_id,
1796                kdf,
1797            } => {
1798                symmetric.build(writer)?;
1799                scheme.build(writer)?;
1800                (*curve_id as u16).build(writer)?;
1801                kdf.build(writer)
1802            }
1803            TpmuPublicParms::Null => Ok(()),
1804        }
1805    }
1806}
1807
1808impl<'a> TpmParseTagged<'a> for TpmuPublicParms {
1809    /// Parses `TpmuPublicParms` from the given buffer
1810    ///
1811    /// # Errors
1812    ///
1813    /// * `TpmErrorKind::Boundary` if the buffer is too small to contain the object.
1814    /// * `TpmErrorKind::InvalidValue` if a value in the buffer is invalid for the target type.
1815    fn parse_tagged(tag: TpmAlgId, buf: &'a [u8]) -> TpmResult<(Self, &'a [u8])> {
1816        match tag {
1817            TpmAlgId::KeyedHash => {
1818                let (details, buf) = TpmsKeyedhashParms::parse(buf)?;
1819                Ok((Self::KeyedHash { details }, buf))
1820            }
1821            TpmAlgId::SymCipher => {
1822                let (details, buf) = TpmsSymcipherParms::parse(buf)?;
1823                Ok((Self::SymCipher { details }, buf))
1824            }
1825            TpmAlgId::Rsa => {
1826                let (symmetric, buf) = TpmtSymDefObject::parse(buf)?;
1827                let (scheme, buf) = TpmtScheme::parse(buf)?;
1828                let (key_bits, buf) = u16::parse(buf)?;
1829                let (exponent, buf) = u32::parse(buf)?;
1830                Ok((
1831                    Self::Rsa {
1832                        symmetric,
1833                        scheme,
1834                        key_bits,
1835                        exponent,
1836                    },
1837                    buf,
1838                ))
1839            }
1840            TpmAlgId::Ecc => {
1841                let (symmetric, buf) = TpmtSymDefObject::parse(buf)?;
1842                let (scheme, buf) = TpmtScheme::parse(buf)?;
1843                let (curve_id_raw, buf) = u16::parse(buf)?;
1844                let curve_id = TpmEccCurve::try_from(curve_id_raw).map_err(|()| {
1845                    TpmErrorKind::InvalidDiscriminant {
1846                        type_name: "TpmEccCurve",
1847                        value: u64::from(curve_id_raw),
1848                    }
1849                })?;
1850                let (kdf, buf) = TpmtKdfScheme::parse(buf)?;
1851                Ok((
1852                    Self::Ecc {
1853                        symmetric,
1854                        scheme,
1855                        curve_id,
1856                        kdf,
1857                    },
1858                    buf,
1859                ))
1860            }
1861            TpmAlgId::Null => Ok((Self::Null, buf)),
1862            _ => Err(TpmErrorKind::InvalidValue),
1863        }
1864    }
1865}
1866
1867#[allow(clippy::large_enum_variant)]
1868#[derive(Debug, PartialEq, Eq, Clone)]
1869pub enum TpmuSensitiveComposite {
1870    Rsa(Tpm2bPrivateKeyRsa),
1871    Ecc(Tpm2bEccParameter),
1872    Bits(Tpm2bSensitiveData),
1873    Sym(Tpm2bSymKey),
1874}
1875
1876impl TpmTagged for TpmuSensitiveComposite {
1877    type Tag = TpmAlgId;
1878    type Value = ();
1879}
1880
1881impl Default for TpmuSensitiveComposite {
1882    fn default() -> Self {
1883        Self::Rsa(Tpm2bPrivateKeyRsa::default())
1884    }
1885}
1886
1887impl TpmSized for TpmuSensitiveComposite {
1888    const SIZE: usize = TPM_MAX_COMMAND_SIZE;
1889    fn len(&self) -> usize {
1890        match self {
1891            Self::Rsa(val) => val.len(),
1892            Self::Ecc(val) => val.len(),
1893            Self::Bits(val) => val.len(),
1894            Self::Sym(val) => val.len(),
1895        }
1896    }
1897}
1898
1899impl TpmBuild for TpmuSensitiveComposite {
1900    fn build(&self, writer: &mut TpmWriter) -> TpmResult<()> {
1901        match self {
1902            TpmuSensitiveComposite::Rsa(val) => val.build(writer),
1903            TpmuSensitiveComposite::Ecc(val) => val.build(writer),
1904            TpmuSensitiveComposite::Bits(val) => val.build(writer),
1905            TpmuSensitiveComposite::Sym(val) => val.build(writer),
1906        }
1907    }
1908}
1909
1910impl<'a> TpmParseTagged<'a> for TpmuSensitiveComposite {
1911    /// Parses `TpmuSensitiveComposite` from a buffer based on the sensitive type.
1912    ///
1913    /// # Errors
1914    ///
1915    /// * `TpmErrorKind::Boundary` if the buffer is too small to contain the object.
1916    /// * `TpmErrorKind::InvalidValue` if the `sensitive_type` is not a valid object
1917    ///   type for this union, or if an inner value fails to parse.
1918    fn parse_tagged(tag: TpmAlgId, buf: &'a [u8]) -> TpmResult<(Self, &'a [u8])> {
1919        match tag {
1920            TpmAlgId::Rsa => {
1921                let (val, buf) = Tpm2bPrivateKeyRsa::parse(buf)?;
1922                Ok((Self::Rsa(val), buf))
1923            }
1924            TpmAlgId::Ecc => {
1925                let (val, buf) = Tpm2bEccParameter::parse(buf)?;
1926                Ok((Self::Ecc(val), buf))
1927            }
1928            TpmAlgId::KeyedHash => {
1929                let (val, buf) = Tpm2bSensitiveData::parse(buf)?;
1930                Ok((Self::Bits(val), buf))
1931            }
1932            TpmAlgId::SymCipher => {
1933                let (val, buf) = Tpm2bSymKey::parse(buf)?;
1934                Ok((Self::Sym(val), buf))
1935            }
1936            _ => Err(TpmErrorKind::InvalidValue),
1937        }
1938    }
1939}
1940
1941#[derive(Debug, PartialEq, Eq, Clone, Copy)]
1942pub enum TpmuSymKeyBits {
1943    Aes(u16),
1944    Sm4(u16),
1945    Camellia(u16),
1946    Null,
1947}
1948
1949impl TpmTagged for TpmuSymKeyBits {
1950    type Tag = TpmAlgId;
1951    type Value = ();
1952}
1953
1954impl Default for TpmuSymKeyBits {
1955    fn default() -> Self {
1956        Self::Null
1957    }
1958}
1959
1960impl TpmSized for TpmuSymKeyBits {
1961    const SIZE: usize = core::mem::size_of::<u16>();
1962    fn len(&self) -> usize {
1963        match self {
1964            Self::Aes(val) | Self::Sm4(val) | Self::Camellia(val) => val.len(),
1965            Self::Null => 0,
1966        }
1967    }
1968}
1969
1970impl<'a> TpmParseTagged<'a> for TpmuSymKeyBits {
1971    /// Parses `TpmuSymKeyBits` from the given buffer
1972    ///
1973    /// # Errors
1974    ///
1975    /// * `TpmErrorKind::Boundary` if the buffer is too small to contain the object.
1976    /// * `TpmErrorKind::InvalidValue` if a value in the buffer is invalid for the target type.
1977    fn parse_tagged(tag: TpmAlgId, buf: &'a [u8]) -> TpmResult<(Self, &'a [u8])> {
1978        match tag {
1979            TpmAlgId::Aes => {
1980                let (val, buf) = u16::parse(buf)?;
1981                Ok((Self::Aes(val), buf))
1982            }
1983            TpmAlgId::Sm4 => {
1984                let (val, buf) = u16::parse(buf)?;
1985                Ok((Self::Sm4(val), buf))
1986            }
1987            TpmAlgId::Camellia => {
1988                let (val, buf) = u16::parse(buf)?;
1989                Ok((Self::Camellia(val), buf))
1990            }
1991            TpmAlgId::Null => Ok((Self::Null, buf)),
1992            _ => Err(TpmErrorKind::InvalidValue),
1993        }
1994    }
1995}
1996
1997impl TpmBuild for TpmuSymKeyBits {
1998    fn build(&self, writer: &mut TpmWriter) -> TpmResult<()> {
1999        match self {
2000            TpmuSymKeyBits::Aes(val) | TpmuSymKeyBits::Sm4(val) | TpmuSymKeyBits::Camellia(val) => {
2001                val.build(writer)
2002            }
2003            TpmuSymKeyBits::Null => Ok(()),
2004        }
2005    }
2006}
2007
2008tpm2b_struct!(
2009    #[derive(Debug, PartialEq, Eq, Clone, Default)]
2010    Tpm2bPublic,
2011    TpmtPublic
2012);
2013tpm2b_struct!(
2014    #[derive(Debug, PartialEq, Eq, Clone, Default)]
2015    Tpm2bTemplate,
2016    TpmtPublic
2017);
2018tpm2b_struct!(
2019    #[derive(Debug, PartialEq, Eq, Clone, Default)]
2020    Tpm2bSensitive,
2021    TpmtSensitive
2022);
2023tpm2b_struct!(
2024    #[derive(Debug, PartialEq, Eq, Clone, Default)]
2025    Tpm2bSensitiveCreate,
2026    TpmsSensitiveCreate
2027);
2028tpm2b_struct!(
2029    #[derive(Debug, PartialEq, Eq, Clone, Default)]
2030    Tpm2bAttest,
2031    TpmsAttest
2032);
2033tpm2b_struct!(
2034    #[derive(Debug, PartialEq, Eq, Clone, Default)]
2035    Tpm2bContextData,
2036    TpmsContextData
2037);
2038tpm2b_struct!(
2039    #[derive(Debug, PartialEq, Eq, Clone, Default)]
2040    Tpm2bCreationData,
2041    TpmsCreationData
2042);
2043tpm2b_struct!(
2044    #[derive(Debug, PartialEq, Eq, Clone, Default)]
2045    Tpm2bEccPoint,
2046    TpmsEccPoint
2047);
2048tpm2b_struct!(
2049    #[derive(Debug, PartialEq, Eq, Clone, Default)]
2050    Tpm2bIdObject,
2051    TpmsIdObject
2052);
2053tpm2b_struct!(
2054    #[derive(Debug, PartialEq, Eq, Clone, Default)]
2055    Tpm2bNvPublic,
2056    TpmsNvPublic
2057);