1use self::packed_nums::*;
10use bitfield_struct::bitfield;
11use thiserror::Error;
12use zerocopy::FromBytes;
13use zerocopy::FromZeros;
14use zerocopy::Immutable;
15use zerocopy::IntoBytes;
16use zerocopy::KnownLayout;
17
18#[allow(non_camel_case_types)]
19mod packed_nums {
20 pub type u16_be = zerocopy::U16<zerocopy::BigEndian>;
21 pub type u32_be = zerocopy::U32<zerocopy::BigEndian>;
22 pub type u64_be = zerocopy::U64<zerocopy::BigEndian>;
23}
24
25#[derive(Debug, Error)]
26pub enum InvalidInput {
27 #[error("input data size too large for buffer - input size > upper bound: {0} > {1}")]
28 BufferSizeTooLarge(usize, usize),
29 #[error("input list length too long - input length > upper bound: {0} > {1}")]
30 PcrSelectionsLengthTooLong(usize, usize),
31 #[error("input payload size too large - input size > upper bound: {0} > {1}")]
32 NvPublicPayloadTooLarge(usize, usize),
33}
34
35#[derive(Debug, Error)]
36pub enum TpmProtoError {
37 #[error("input user_auth to TpmsSensitiveCreate is invalid")]
38 TpmsSensitiveCreateUserAuth(#[source] InvalidInput),
39 #[error("input data to TpmsSensitiveCreate is invalid")]
40 TpmsSensitiveCreateData(#[source] InvalidInput),
41 #[error("input auth_policy to TpmtPublic is invalid")]
42 TpmtPublicAuthPolicy(#[source] InvalidInput),
43 #[error("input unique to TpmtPublic is invalid")]
44 TpmtPublicUnique(#[source] InvalidInput),
45 #[error("input auth_policy to TpmsNvPublic is invalid")]
46 TpmsNvPublicAuthPolicy(#[source] InvalidInput),
47 #[error("input outside_info to CreatePrimary is invalid")]
48 CreatePrimaryOutsideInfo(#[source] InvalidInput),
49 #[error("input creation_pcr to CreatePrimary is invalid")]
50 CreatePrimaryCreationPcr(#[source] InvalidInput),
51 #[error("input auth to NvDefineSpace is invalid")]
52 NvDefineSpaceAuth(#[source] InvalidInput),
53 #[error("input public_info to NvDefineSpace is invalid")]
54 NvDefineSpacePublicInfo(#[source] InvalidInput),
55 #[error("input data to NvWrite is invalid")]
56 NvWriteData(#[source] InvalidInput),
57 #[error("input pcr_allocation to PcrAllocate is invalid")]
58 PcrAllocatePcrAllocation(#[source] InvalidInput),
59 #[error("input data to Import is invalid")]
60 ImportData(#[source] InvalidInput),
61}
62
63#[derive(Debug, Error)]
64pub enum ResponseValidationError {
65 #[error("response size is too small to fit into the buffer")]
66 ResponseSizeTooSmall,
67 #[error(
68 "size {size} specified in the response header does not meet the minimal size of command type {expected_size}, command succeeded: {command_succeeded}"
69 )]
70 HeaderResponseSizeMismatch {
71 size: u32,
72 expected_size: usize,
73 command_succeeded: bool,
74 },
75 #[error(
76 "unexpected session tag {response_session_tag} specified in the response header, expected: {expected_session_tag}, command succeeded: {command_succeeded}"
77 )]
78 HeaderSessionTagMismatch {
79 response_session_tag: u16,
80 expected_session_tag: u16,
81 command_succeeded: bool,
82 },
83}
84
85#[repr(transparent)]
86#[derive(Copy, Clone, Debug, IntoBytes, Immutable, KnownLayout, FromBytes, PartialEq)]
87pub struct ReservedHandle(pub u32_be);
88
89impl PartialEq<ReservedHandle> for u32 {
90 fn eq(&self, other: &ReservedHandle) -> bool {
91 other.0.get() == *self
92 }
93}
94
95impl ReservedHandle {
96 pub const fn new(kind: u8, offset: u32) -> ReservedHandle {
97 ReservedHandle(new_u32_be((kind as u32) << 24 | offset))
98 }
99}
100
101pub const TPM20_HT_NV_INDEX: u8 = 0x01;
102pub const TPM20_HT_PERMANENT: u8 = 0x40;
103pub const TPM20_HT_PERSISTENT: u8 = 0x81;
104
105pub const TPM20_RH_OWNER: ReservedHandle = ReservedHandle::new(TPM20_HT_PERMANENT, 0x01);
106pub const TPM20_RH_PLATFORM: ReservedHandle = ReservedHandle::new(TPM20_HT_PERMANENT, 0x0c);
107pub const TPM20_RH_ENDORSEMENT: ReservedHandle = ReservedHandle::new(TPM20_HT_PERMANENT, 0x0b);
108pub const TPM20_RS_PW: ReservedHandle = ReservedHandle::new(TPM20_HT_PERMANENT, 0x09);
111
112pub const NV_INDEX_RANGE_BASE_PLATFORM_MANUFACTURER: u32 =
114 (TPM20_HT_NV_INDEX as u32) << 24 | 0x400000;
115pub const NV_INDEX_RANGE_BASE_TCG_ASSIGNED: u32 = (TPM20_HT_NV_INDEX as u32) << 24 | 0xc00000;
116
117pub const MAX_DIGEST_BUFFER_SIZE: usize = 1024;
120
121#[repr(transparent)]
122#[derive(Debug, Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
123pub struct SessionTag(pub u16_be);
124
125impl PartialEq<SessionTag> for u16 {
126 fn eq(&self, other: &SessionTag) -> bool {
127 other.0.get() == *self
128 }
129}
130
131impl SessionTag {
132 const fn new(val: u16) -> SessionTag {
133 SessionTag(new_u16_be(val))
134 }
135}
136
137#[derive(Debug, Copy, Clone)]
138#[repr(u16)]
139pub enum SessionTagEnum {
140 Null = 0x8000,
142
143 NoSessions = 0x8001,
148
149 Sessions = 0x8002,
153 AttestClock = 0x8014,
154 AttestCommandAudit = 0x8015,
155 AttestSessionAudit = 0x8016,
156 AttestCertify = 0x8017,
157 AttestQuote = 0x8018,
158 AttestTick = 0x8019,
159 AttestTickstamp = 0x801A,
160 AttestTransport = 0x801B,
161 AttestCreation = 0x801C,
162 AttestNv = 0x801D,
163 Creation = 0x8021,
165 Verified = 0x8022,
166 Auth = 0x8023,
167 Hashcheck = 0x8024,
168
169 FuManifest = 0x8029,
171}
172
173impl From<SessionTagEnum> for SessionTag {
174 fn from(x: SessionTagEnum) -> Self {
175 SessionTag::new(x as u16)
176 }
177}
178
179impl SessionTagEnum {
180 pub fn from_u16(val: u16) -> Option<SessionTagEnum> {
181 let ret = match val {
182 0x8000 => Self::Null,
183 0x8001 => Self::NoSessions,
184 0x8002 => Self::Sessions,
185 0x8014 => Self::AttestClock,
186 0x8015 => Self::AttestCommandAudit,
187 0x8016 => Self::AttestSessionAudit,
188 0x8017 => Self::AttestCertify,
189 0x8018 => Self::AttestQuote,
190 0x8019 => Self::AttestTick,
191 0x801A => Self::AttestTickstamp,
192 0x801B => Self::AttestTransport,
193 0x801C => Self::AttestCreation,
194 0x801D => Self::AttestNv,
195 0x8021 => Self::Creation,
196 0x8022 => Self::Verified,
197 0x8023 => Self::Auth,
198 0x8024 => Self::Hashcheck,
199 0x8029 => Self::FuManifest,
200 _ => return None,
201 };
202 Some(ret)
203 }
204}
205
206#[repr(transparent)]
207#[derive(Debug, Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes, PartialEq)]
208pub struct CommandCode(pub u32_be);
209
210impl PartialEq<CommandCode> for u32 {
211 fn eq(&self, other: &CommandCode) -> bool {
212 other.0.get() == *self
213 }
214}
215
216impl CommandCode {
217 const fn new(val: u32) -> CommandCode {
218 CommandCode(new_u32_be(val))
219 }
220
221 pub fn into_enum(self) -> Option<CommandCodeEnum> {
222 CommandCodeEnum::from_u32(self.0.get())
223 }
224}
225
226#[allow(non_camel_case_types, clippy::upper_case_acronyms)]
227#[derive(Debug, Clone, Copy, PartialEq)]
228#[repr(u32)]
229pub enum CommandCodeEnum {
230 NV_UndefineSpaceSpecial = 0x0000011f,
231 EvictControl = 0x00000120,
232 HierarchyControl = 0x00000121,
233 NV_UndefineSpace = 0x00000122,
234 ChangeEPS = 0x00000124,
235 ChangePPS = 0x00000125,
236 Clear = 0x00000126,
237 ClearControl = 0x00000127,
238 ClockSet = 0x00000128,
239 HierarchyChangeAuth = 0x00000129,
240 NV_DefineSpace = 0x0000012a,
241 PCR_Allocate = 0x0000012b,
242 PCR_SetAuthPolicy = 0x0000012c,
243 PP_Commands = 0x0000012d,
244 SetPrimaryPolicy = 0x0000012e,
245 FieldUpgradeStart = 0x0000012f,
246 ClockRateAdjust = 0x00000130,
247 CreatePrimary = 0x00000131,
248 NV_GlobalWriteLock = 0x00000132,
249 GetCommandAuditDigest = 0x00000133,
250 NV_Increment = 0x00000134,
251 NV_SetBits = 0x00000135,
252 NV_Extend = 0x00000136,
253 NV_Write = 0x00000137,
254 NV_WriteLock = 0x00000138,
255 DictionaryAttackLockReset = 0x00000139,
256 DictionaryAttackParameters = 0x0000013a,
257 NV_ChangeAuth = 0x0000013b,
258 PCR_Event = 0x0000013c,
259 PCR_Reset = 0x0000013d,
260 SequenceComplete = 0x0000013e,
261 SetAlgorithmSet = 0x0000013f,
262 SetCommandCodeAuditStatus = 0x00000140,
263 FieldUpgradeData = 0x00000141,
264 IncrementalSelfTest = 0x00000142,
265 SelfTest = 0x00000143,
266 Startup = 0x00000144,
267 Shutdown = 0x00000145,
268 StirRandom = 0x00000146,
269 ActivateCredential = 0x00000147,
270 Certify = 0x00000148,
271 PolicyNV = 0x00000149,
272 CertifyCreation = 0x0000014a,
273 Duplicate = 0x0000014b,
274 GetTime = 0x0000014c,
275 GetSessionAuditDigest = 0x0000014d,
276 NV_Read = 0x0000014e,
277 NV_ReadLock = 0x0000014f,
278 ObjectChangeAuth = 0x00000150,
279 PolicySecret = 0x00000151,
280 Rewrap = 0x00000152,
281 Create = 0x00000153,
282 ECDH_ZGen = 0x00000154,
283 HMAC = 0x00000155,
284 Import = 0x00000156,
285 Load = 0x00000157,
286 Quote = 0x00000158,
287 RSA_Decrypt = 0x00000159,
288 HMAC_Start = 0x0000015b,
289 SequenceUpdate = 0x0000015c,
290 Sign = 0x0000015d,
291 Unseal = 0x0000015e,
292 PolicySigned = 0x00000160,
293 ContextLoad = 0x00000161,
294 ContextSave = 0x00000162,
295 ECDH_KeyGen = 0x00000163,
296 EncryptDecrypt = 0x00000164,
297 FlushContext = 0x00000165,
298 LoadExternal = 0x00000167,
299 MakeCredential = 0x00000168,
300 NV_ReadPublic = 0x00000169,
301 PolicyAuthorize = 0x0000016a,
302 PolicyAuthValue = 0x0000016b,
303 PolicyCommandCode = 0x0000016c,
304 PolicyCounterTimer = 0x0000016d,
305 PolicyCpHash = 0x0000016e,
306 PolicyLocality = 0x0000016f,
307 PolicyNameHash = 0x00000170,
308 PolicyOR = 0x00000171,
309 PolicyTicket = 0x00000172,
310 ReadPublic = 0x00000173,
311 RSA_Encrypt = 0x00000174,
312 StartAuthSession = 0x00000176,
313 VerifySignature = 0x00000177,
314 ECC_Parameters = 0x00000178,
315 FirmwareRead = 0x00000179,
316 GetCapability = 0x0000017a,
317 GetRandom = 0x0000017b,
318 GetTestResult = 0x0000017c,
319 Hash = 0x0000017d,
320 PCR_Read = 0x0000017e,
321 PolicyPCR = 0x0000017f,
322 PolicyRestart = 0x00000180,
323 ReadClock = 0x00000181,
324 PCR_Extend = 0x00000182,
325 PCR_SetAuthValue = 0x00000183,
326 NV_Certify = 0x00000184,
327 EventSequenceComplete = 0x00000185,
328 HashSequenceStart = 0x00000186,
329 PolicyPhysicalPresence = 0x00000187,
330 PolicyDuplicationSelect = 0x00000188,
331 PolicyGetDigest = 0x00000189,
332 TestParms = 0x0000018a,
333 Commit = 0x0000018b,
334 PolicyPassword = 0x0000018c,
335 ZGen_2Phase = 0x0000018d,
336 EC_Ephemeral = 0x0000018e,
337 PolicyNvWritten = 0x0000018f,
338 PolicyTemplate = 0x00000190,
339 CreateLoaded = 0x00000191,
340 PolicyAuthorizeNV = 0x00000192,
341 EncryptDecrypt2 = 0x00000193,
342 AC_GetCapability = 0x00000194,
343 AC_Send = 0x00000195,
344 Policy_AC_SendSelect = 0x00000196,
345 CertifyX509 = 0x00000197,
346 ACT_SetTimeout = 0x00000198,
347}
348
349impl From<CommandCodeEnum> for CommandCode {
350 fn from(x: CommandCodeEnum) -> Self {
351 CommandCode::new(x as u32)
352 }
353}
354
355impl CommandCodeEnum {
356 pub fn from_u32(val: u32) -> Option<CommandCodeEnum> {
357 let ret = match val {
358 0x0000011f => Self::NV_UndefineSpaceSpecial,
359 0x00000120 => Self::EvictControl,
360 0x00000121 => Self::HierarchyControl,
361 0x00000122 => Self::NV_UndefineSpace,
362 0x00000124 => Self::ChangeEPS,
363 0x00000125 => Self::ChangePPS,
364 0x00000126 => Self::Clear,
365 0x00000127 => Self::ClearControl,
366 0x00000128 => Self::ClockSet,
367 0x00000129 => Self::HierarchyChangeAuth,
368 0x0000012a => Self::NV_DefineSpace,
369 0x0000012b => Self::PCR_Allocate,
370 0x0000012c => Self::PCR_SetAuthPolicy,
371 0x0000012d => Self::PP_Commands,
372 0x0000012e => Self::SetPrimaryPolicy,
373 0x0000012f => Self::FieldUpgradeStart,
374 0x00000130 => Self::ClockRateAdjust,
375 0x00000131 => Self::CreatePrimary,
376 0x00000132 => Self::NV_GlobalWriteLock,
377 0x00000133 => Self::GetCommandAuditDigest,
378 0x00000134 => Self::NV_Increment,
379 0x00000135 => Self::NV_SetBits,
380 0x00000136 => Self::NV_Extend,
381 0x00000137 => Self::NV_Write,
382 0x00000138 => Self::NV_WriteLock,
383 0x00000139 => Self::DictionaryAttackLockReset,
384 0x0000013a => Self::DictionaryAttackParameters,
385 0x0000013b => Self::NV_ChangeAuth,
386 0x0000013c => Self::PCR_Event,
387 0x0000013d => Self::PCR_Reset,
388 0x0000013e => Self::SequenceComplete,
389 0x0000013f => Self::SetAlgorithmSet,
390 0x00000140 => Self::SetCommandCodeAuditStatus,
391 0x00000141 => Self::FieldUpgradeData,
392 0x00000142 => Self::IncrementalSelfTest,
393 0x00000143 => Self::SelfTest,
394 0x00000144 => Self::Startup,
395 0x00000145 => Self::Shutdown,
396 0x00000146 => Self::StirRandom,
397 0x00000147 => Self::ActivateCredential,
398 0x00000148 => Self::Certify,
399 0x00000149 => Self::PolicyNV,
400 0x0000014a => Self::CertifyCreation,
401 0x0000014b => Self::Duplicate,
402 0x0000014c => Self::GetTime,
403 0x0000014d => Self::GetSessionAuditDigest,
404 0x0000014e => Self::NV_Read,
405 0x0000014f => Self::NV_ReadLock,
406 0x00000150 => Self::ObjectChangeAuth,
407 0x00000151 => Self::PolicySecret,
408 0x00000152 => Self::Rewrap,
409 0x00000153 => Self::Create,
410 0x00000154 => Self::ECDH_ZGen,
411 0x00000155 => Self::HMAC,
412 0x00000156 => Self::Import,
413 0x00000157 => Self::Load,
414 0x00000158 => Self::Quote,
415 0x00000159 => Self::RSA_Decrypt,
416 0x0000015b => Self::HMAC_Start,
417 0x0000015c => Self::SequenceUpdate,
418 0x0000015d => Self::Sign,
419 0x0000015e => Self::Unseal,
420 0x00000160 => Self::PolicySigned,
421 0x00000161 => Self::ContextLoad,
422 0x00000162 => Self::ContextSave,
423 0x00000163 => Self::ECDH_KeyGen,
424 0x00000164 => Self::EncryptDecrypt,
425 0x00000165 => Self::FlushContext,
426 0x00000167 => Self::LoadExternal,
427 0x00000168 => Self::MakeCredential,
428 0x00000169 => Self::NV_ReadPublic,
429 0x0000016a => Self::PolicyAuthorize,
430 0x0000016b => Self::PolicyAuthValue,
431 0x0000016c => Self::PolicyCommandCode,
432 0x0000016d => Self::PolicyCounterTimer,
433 0x0000016e => Self::PolicyCpHash,
434 0x0000016f => Self::PolicyLocality,
435 0x00000170 => Self::PolicyNameHash,
436 0x00000171 => Self::PolicyOR,
437 0x00000172 => Self::PolicyTicket,
438 0x00000173 => Self::ReadPublic,
439 0x00000174 => Self::RSA_Encrypt,
440 0x00000176 => Self::StartAuthSession,
441 0x00000177 => Self::VerifySignature,
442 0x00000178 => Self::ECC_Parameters,
443 0x00000179 => Self::FirmwareRead,
444 0x0000017a => Self::GetCapability,
445 0x0000017b => Self::GetRandom,
446 0x0000017c => Self::GetTestResult,
447 0x0000017d => Self::Hash,
448 0x0000017e => Self::PCR_Read,
449 0x0000017f => Self::PolicyPCR,
450 0x00000180 => Self::PolicyRestart,
451 0x00000181 => Self::ReadClock,
452 0x00000182 => Self::PCR_Extend,
453 0x00000183 => Self::PCR_SetAuthValue,
454 0x00000184 => Self::NV_Certify,
455 0x00000185 => Self::EventSequenceComplete,
456 0x00000186 => Self::HashSequenceStart,
457 0x00000187 => Self::PolicyPhysicalPresence,
458 0x00000188 => Self::PolicyDuplicationSelect,
459 0x00000189 => Self::PolicyGetDigest,
460 0x0000018a => Self::TestParms,
461 0x0000018b => Self::Commit,
462 0x0000018c => Self::PolicyPassword,
463 0x0000018d => Self::ZGen_2Phase,
464 0x0000018e => Self::EC_Ephemeral,
465 0x0000018f => Self::PolicyNvWritten,
466 0x00000190 => Self::PolicyTemplate,
467 0x00000191 => Self::CreateLoaded,
468 0x00000192 => Self::PolicyAuthorizeNV,
469 0x00000193 => Self::EncryptDecrypt2,
470 0x00000194 => Self::AC_GetCapability,
471 0x00000195 => Self::AC_Send,
472 0x00000196 => Self::Policy_AC_SendSelect,
473 0x00000197 => Self::CertifyX509,
474 0x00000198 => Self::ACT_SetTimeout,
475 _ => return None,
476 };
477
478 Some(ret)
479 }
480}
481
482const FLAG_FMT1: u32 = 0x0080;
483const FLAG_VER1: u32 = 0x0100;
484const FLAG_WARN: u32 = 0x0800 + FLAG_VER1;
485
486#[repr(u32)]
487pub enum ResponseCode {
488 Success = 0x000,
489 Value = FLAG_FMT1 + 0x004,
492 Hierarchy = FLAG_FMT1 + 0x0005,
494 Handle = FLAG_FMT1 + 0x000B,
496 AuthFail = FLAG_FMT1 + 0x000E,
498 Size = FLAG_FMT1 + 0x0015,
500 Insufficient = FLAG_FMT1 + 0x001A,
503 Integrity = FLAG_FMT1 + 0x001F,
505 Failure = FLAG_VER1 + 0x0001,
507 AuthContext = FLAG_VER1 + 0x0045,
509 NvUninitialized = FLAG_VER1 + 0x04A,
512 Sensitive = FLAG_VER1 + 0x055,
514 ContextGap = FLAG_WARN + 0x001,
516 ObjectMemory = FLAG_WARN + 0x002,
518 SessionMemory = FLAG_WARN + 0x003,
520 Memory = FLAG_WARN + 0x004,
523 SessionHandles = FLAG_WARN + 0x005,
526 ObjectHandles = FLAG_WARN + 0x006,
530 Yielded = FLAG_WARN + 0x008,
533 Cancelled = FLAG_WARN + 0x009,
535 Testing = FLAG_WARN + 0x00A,
537 NvRate = FLAG_WARN + 0x020,
539 Lockout = FLAG_WARN + 0x021,
542 Retry = FLAG_WARN + 0x022,
544 NvUnavailable = FLAG_WARN + 0x023,
547 NotUsed = FLAG_WARN + 0x07F,
549 Rc1 = 0x100,
551}
552
553impl ResponseCode {
554 pub fn from_u32(val: u32) -> Option<ResponseCode> {
555 let ret = match val {
556 x if x == ResponseCode::Success as u32 => ResponseCode::Success,
557 x if x == ResponseCode::Value as u32 => ResponseCode::Value,
558 x if x == ResponseCode::Hierarchy as u32 => ResponseCode::Hierarchy,
559 x if x == ResponseCode::Handle as u32 => ResponseCode::Handle,
560 x if x == ResponseCode::AuthFail as u32 => ResponseCode::AuthFail,
561 x if x == ResponseCode::Size as u32 => ResponseCode::Size,
562 x if x == ResponseCode::Insufficient as u32 => ResponseCode::Insufficient,
563 x if x == ResponseCode::Integrity as u32 => ResponseCode::Integrity,
564 x if x == ResponseCode::Failure as u32 => ResponseCode::Failure,
565 x if x == ResponseCode::AuthContext as u32 => ResponseCode::AuthContext,
566 x if x == ResponseCode::NvUninitialized as u32 => ResponseCode::NvUninitialized,
567 x if x == ResponseCode::Sensitive as u32 => ResponseCode::Sensitive,
568 x if x == ResponseCode::ContextGap as u32 => ResponseCode::ContextGap,
569 x if x == ResponseCode::ObjectMemory as u32 => ResponseCode::ObjectMemory,
570 x if x == ResponseCode::SessionMemory as u32 => ResponseCode::SessionMemory,
571 x if x == ResponseCode::Memory as u32 => ResponseCode::Memory,
572 x if x == ResponseCode::SessionHandles as u32 => ResponseCode::SessionHandles,
573 x if x == ResponseCode::ObjectHandles as u32 => ResponseCode::ObjectHandles,
574 x if x == ResponseCode::Yielded as u32 => ResponseCode::Yielded,
575 x if x == ResponseCode::Cancelled as u32 => ResponseCode::Cancelled,
576 x if x == ResponseCode::Testing as u32 => ResponseCode::Testing,
577 x if x == ResponseCode::NvRate as u32 => ResponseCode::NvRate,
578 x if x == ResponseCode::Lockout as u32 => ResponseCode::Lockout,
579 x if x == ResponseCode::Retry as u32 => ResponseCode::Retry,
580 x if x == ResponseCode::NvUnavailable as u32 => ResponseCode::NvUnavailable,
581 x if x == ResponseCode::NotUsed as u32 => ResponseCode::NotUsed,
582 _ => return None,
583 };
584 Some(ret)
585 }
586}
587
588#[repr(transparent)]
589#[derive(Debug, Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes, PartialEq)]
590pub struct AlgId(pub u16_be);
591
592impl PartialEq<AlgId> for u16 {
593 fn eq(&self, other: &AlgId) -> bool {
594 other.0.get() == *self
595 }
596}
597
598impl AlgId {
599 const fn new(val: u16) -> AlgId {
600 AlgId(new_u16_be(val))
601 }
602}
603
604#[allow(non_camel_case_types, clippy::upper_case_acronyms)]
605#[derive(Debug)]
606#[repr(u16)]
607pub enum AlgIdEnum {
608 RSA = 0x0001,
609 SHA = 0x0004,
610 AES = 0x0006,
611 SHA256 = 0x000b,
612 SHA384 = 0x000c,
613 SHA512 = 0x000d,
614 NULL = 0x0010,
615 SM3_256 = 0x0012,
616 RSASSA = 0x0014,
617 CFB = 0x0043,
618}
619
620impl From<AlgIdEnum> for AlgId {
621 fn from(x: AlgIdEnum) -> Self {
622 AlgId::new(x as u16)
623 }
624}
625
626impl AlgIdEnum {
627 pub fn from_u16(val: u16) -> Option<AlgIdEnum> {
628 let ret = match val {
629 0x0004 => Self::SHA,
630 0x000b => Self::SHA256,
631 0x000c => Self::SHA384,
632 0x000d => Self::SHA512,
633 0x0012 => Self::SM3_256,
634 _ => return None,
635 };
636
637 Some(ret)
638 }
639}
640
641#[repr(transparent)]
643#[derive(Debug, Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes, PartialEq)]
644pub struct TpmaObject(pub u32_be);
645
646impl TpmaObject {
647 const fn new(val: u32) -> Self {
648 Self(new_u32_be(val))
649 }
650}
651
652impl From<TpmaObjectBits> for TpmaObject {
653 fn from(x: TpmaObjectBits) -> Self {
654 let val: u32 = x.into();
655 Self::new(val)
656 }
657}
658
659impl From<u32> for TpmaObject {
660 fn from(x: u32) -> Self {
661 Self::new(x)
662 }
663}
664
665#[bitfield(u32)]
666pub struct TpmaObjectBits {
667 _reserved0: bool,
668 pub fixed_tpm: bool,
669 pub st_clear: bool,
670 _reserved1: bool,
671 pub fixed_parent: bool,
672 pub sensitive_data_origin: bool,
673 pub user_with_auth: bool,
674 pub admin_with_policy: bool,
675 #[bits(2)]
676 _reserved2: u8,
677 pub no_da: bool,
678 pub encrypted_duplication: bool,
679 #[bits(4)]
680 _reserved3: u8,
681 pub restricted: bool,
682 pub decrypt: bool,
683 pub sign_encrypt: bool,
684 #[bits(13)]
685 _reserved4: u16,
686}
687
688#[repr(transparent)]
690#[derive(Debug, Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes, PartialEq)]
691pub struct TpmaNv(pub u32_be);
692
693impl TpmaNv {
694 const fn new(val: u32) -> Self {
695 Self(new_u32_be(val))
696 }
697}
698
699impl From<TpmaNvBits> for TpmaNv {
700 fn from(x: TpmaNvBits) -> Self {
701 let val: u32 = x.into();
702 Self::new(val)
703 }
704}
705
706impl From<u32> for TpmaNv {
707 fn from(x: u32) -> Self {
708 Self::new(x)
709 }
710}
711
712#[bitfield(u32)]
713pub struct TpmaNvBits {
714 pub nv_ppwrite: bool,
715 pub nv_ownerwrite: bool,
716 pub nv_authwrite: bool,
717 pub nv_policywrite: bool,
718 pub nt_counter: bool,
721 pub nt_bits: bool,
723 pub nt_extend: bool,
725 _unused0: bool,
726 #[bits(2)]
728 _reserved1: u8,
729 pub nv_policy_delete: bool,
730 pub nv_writelocked: bool,
731 pub nv_writeall: bool,
732 pub nv_writedefine: bool,
733 pub nv_write_stclear: bool,
734 pub nv_globallock: bool,
735 pub nv_ppread: bool,
736 pub nv_ownerread: bool,
737 pub nv_authread: bool,
738 pub nv_policyread: bool,
739 #[bits(5)]
741 _reserved2: u8,
742 pub nv_no_da: bool,
743 pub nv_orderly: bool,
744 pub nv_clear_stclear: bool,
745 pub nv_readlocked: bool,
746 pub nv_written: bool,
747 pub nv_platformcreate: bool,
748 pub nv_read_stclear: bool,
749}
750
751const fn new_u64_be(val: u64) -> u64_be {
753 u64_be::from_bytes(val.to_be_bytes())
754}
755
756const fn new_u32_be(val: u32) -> u32_be {
758 u32_be::from_bytes(val.to_be_bytes())
759}
760
761const fn new_u16_be(val: u16) -> u16_be {
763 u16_be::from_bytes(val.to_be_bytes())
764}
765
766pub mod protocol {
768 use super::*;
769
770 pub mod common {
772 use super::*;
773
774 #[repr(C)]
775 #[derive(Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
776 pub struct CmdHeader {
777 pub session_tag: SessionTag,
778 pub size: u32_be,
779 pub command_code: CommandCode,
780 }
781
782 impl CmdHeader {
783 pub fn new<Cmd: Sized>(
785 session_tag: SessionTag,
786 command_code: CommandCode,
787 ) -> CmdHeader {
788 CmdHeader {
789 session_tag,
790 size: (size_of::<Cmd>() as u32).into(),
791 command_code,
792 }
793 }
794 }
795
796 #[repr(C)]
797 #[derive(Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
798 pub struct ReplyHeader {
799 pub session_tag: u16_be,
800 pub size: u32_be,
801 pub response_code: u32_be,
802 }
803
804 impl ReplyHeader {
805 pub fn base_validation(
813 &self,
814 session_tag: SessionTag,
815 expected_size: u32,
816 ) -> Result<bool, ResponseValidationError> {
817 let command_succeeded = ResponseCode::from_u32(self.response_code.get())
820 .map(|c| matches!(c, ResponseCode::Success))
821 .unwrap_or(false);
822
823 let (expected_tag, expected_size) = if command_succeeded {
824 (session_tag, expected_size as usize)
825 } else {
826 (SessionTagEnum::NoSessions.into(), size_of::<Self>())
833 };
834
835 if self.session_tag.get() != expected_tag {
836 Err(ResponseValidationError::HeaderSessionTagMismatch {
837 response_session_tag: self.session_tag.get(),
838 expected_session_tag: session_tag.0.get(),
839 command_succeeded,
840 })?
841 }
842
843 if (self.size.get() as usize) < expected_size {
846 Err(ResponseValidationError::HeaderResponseSizeMismatch {
847 size: self.size.get(),
848 expected_size,
849 command_succeeded,
850 })?
851 }
852
853 Ok(command_succeeded)
854 }
855 }
856
857 #[repr(C)]
858 #[derive(Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
859 pub struct CmdAuth {
860 handle: ReservedHandle,
861 nonce_2b: u16_be,
862 session: u8,
863 auth_2b: u16_be,
864 }
865
866 impl CmdAuth {
867 pub fn new(handle: ReservedHandle, nonce_2b: u16, session: u8, auth_2b: u16) -> Self {
868 CmdAuth {
869 handle,
870 nonce_2b: nonce_2b.into(),
871 session,
872 auth_2b: auth_2b.into(),
873 }
874 }
875 }
876
877 #[repr(C)]
878 #[derive(Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
879 pub struct ReplyAuth {
880 pub nonce_2b: u16_be,
881 pub session: u8,
882 pub auth_2b: u16_be,
883 }
884 }
885
886 use common::CmdHeader;
887 use common::ReplyHeader;
888
889 pub trait TpmCommand: IntoBytes + FromBytes + Sized + Immutable + KnownLayout {
891 type Reply: TpmReply;
892
893 fn base_validate_reply(
894 reply_buf: &[u8],
895 session_tag: impl Into<SessionTag>,
896 ) -> Result<(Self::Reply, bool), ResponseValidationError> {
897 let res = Self::Reply::deserialize(reply_buf)
898 .ok_or(ResponseValidationError::ResponseSizeTooSmall)?;
899 let succeeded = res.base_validation(session_tag.into())?;
900
901 Ok((res, succeeded))
902 }
903 }
904
905 pub trait TpmReply: IntoBytes + FromBytes + Sized + Immutable + KnownLayout {
907 type Command: TpmCommand;
908
909 fn base_validation(
910 &self,
911 session_tag: SessionTag,
912 ) -> Result<bool, ResponseValidationError> {
913 let header = ReplyHeader::ref_from_prefix(self.as_bytes())
915 .expect("unexpected response size")
916 .0; header.base_validation(session_tag, self.payload_size() as u32)
918 }
919 fn deserialize(bytes: &[u8]) -> Option<Self>;
920 fn payload_size(&self) -> usize;
921 }
922
923 #[repr(C)]
925 #[derive(Debug, Copy, Clone, FromBytes, IntoBytes, Immutable, KnownLayout)]
926 pub struct Tpm2bBuffer {
927 pub size: u16_be,
928 pub buffer: [u8; MAX_DIGEST_BUFFER_SIZE],
931 }
932
933 impl Tpm2bBuffer {
934 pub fn new(data: &[u8]) -> Result<Self, InvalidInput> {
936 let size = data.len();
937 if size > MAX_DIGEST_BUFFER_SIZE {
938 Err(InvalidInput::BufferSizeTooLarge(
939 size,
940 MAX_DIGEST_BUFFER_SIZE,
941 ))?
942 }
943
944 let mut buffer = [0u8; MAX_DIGEST_BUFFER_SIZE];
945 buffer[..size].copy_from_slice(data);
946
947 Ok(Self {
948 size: new_u16_be(size as u16),
949 buffer,
950 })
951 }
952
953 pub fn serialize(self) -> Vec<u8> {
954 let mut buffer = Vec::new();
955
956 buffer.extend_from_slice(self.size.as_bytes());
957 buffer.extend_from_slice(&self.buffer[..self.size.get() as usize]);
958
959 buffer
960 }
961
962 pub fn deserialize(bytes: &[u8]) -> Option<Self> {
963 let mut start = 0;
964 let mut end = size_of::<u16_be>();
965 if bytes.len() < end {
966 return None;
967 }
968
969 let size: u16 = u16_be::read_from_bytes(&bytes[start..end]).ok()?.into(); if size as usize > MAX_DIGEST_BUFFER_SIZE {
971 return None;
972 }
973
974 start = end;
975 end += size as usize;
976 if bytes.len() < end {
977 return None;
978 }
979 let mut buffer = [0u8; MAX_DIGEST_BUFFER_SIZE];
980 buffer[..size as usize].copy_from_slice(&bytes[start..end]);
981
982 Some(Self {
983 size: size.into(),
984 buffer,
985 })
986 }
987
988 pub fn payload_size(&self) -> usize {
989 let mut payload_size = 0;
990
991 payload_size += size_of_val(&self.size);
992 payload_size += self.size.get() as usize;
993
994 payload_size
995 }
996 }
997
998 #[repr(C)]
1000 #[derive(Debug, Copy, Clone, FromBytes, IntoBytes, Immutable, KnownLayout)]
1001 pub struct TpmlPcrSelection {
1002 pub count: u32_be,
1003 pub pcr_selections: [PcrSelection; 5],
1004 }
1005
1006 impl TpmlPcrSelection {
1007 pub fn new(pcr_selections: &[PcrSelection]) -> Result<Self, InvalidInput> {
1008 let count = pcr_selections.len();
1009 if count > 5 {
1010 Err(InvalidInput::PcrSelectionsLengthTooLong(count, 5))?
1011 }
1012
1013 let mut base = [PcrSelection::new_zeroed(); 5];
1014 base[..count].copy_from_slice(pcr_selections);
1015
1016 Ok(Self {
1017 count: new_u32_be(count as u32),
1018 pcr_selections: base,
1019 })
1020 }
1021
1022 pub fn serialize(self) -> Vec<u8> {
1023 let mut buffer = Vec::new();
1024
1025 buffer.extend_from_slice(self.count.as_bytes());
1026 for i in 0..self.count.get() {
1027 buffer.extend_from_slice(&self.pcr_selections[i as usize].serialize());
1028 }
1029
1030 buffer
1031 }
1032
1033 pub fn deserialize(bytes: &[u8]) -> Option<Self> {
1034 let mut start = 0;
1035 let mut end = size_of::<u32_be>();
1036
1037 if bytes.len() < end {
1038 return None;
1039 }
1040
1041 let count: u32 = u32_be::read_from_bytes(&bytes[start..end]).ok()?.into(); if count > 5 {
1043 return None;
1044 }
1045
1046 let mut pcr_selections = [PcrSelection::new_zeroed(); 5];
1047 for i in 0..count {
1048 start = end;
1049 pcr_selections[i as usize] = PcrSelection::deserialize(&bytes[start..])?;
1050 end += pcr_selections[i as usize].payload_size();
1051 }
1052
1053 Some(Self {
1054 count: count.into(),
1055 pcr_selections,
1056 })
1057 }
1058
1059 pub fn payload_size(&self) -> usize {
1060 let mut payload_size = 0;
1061 let count = self.count;
1062
1063 payload_size += size_of_val(&count);
1064 for i in 0..count.get() {
1065 payload_size += self.pcr_selections[i as usize].payload_size();
1066 }
1067
1068 payload_size
1069 }
1070 }
1071
1072 #[repr(C)]
1074 #[derive(Debug, Copy, Clone, FromBytes, IntoBytes, Immutable, KnownLayout)]
1075 pub struct TpmsSensitiveCreate {
1076 user_auth: Tpm2bBuffer,
1077 data: Tpm2bBuffer,
1078 }
1079
1080 impl TpmsSensitiveCreate {
1081 pub fn new(user_auth: &[u8], data: &[u8]) -> Result<Self, TpmProtoError> {
1082 let user_auth =
1083 Tpm2bBuffer::new(user_auth).map_err(TpmProtoError::TpmsSensitiveCreateUserAuth)?;
1084 let data = Tpm2bBuffer::new(data).map_err(TpmProtoError::TpmsSensitiveCreateData)?;
1085 Ok(Self { user_auth, data })
1086 }
1087
1088 pub fn serialize(self) -> Vec<u8> {
1089 let mut buffer = Vec::new();
1090
1091 buffer.extend_from_slice(&self.user_auth.serialize());
1092 buffer.extend_from_slice(&self.data.serialize());
1093
1094 buffer
1095 }
1096
1097 pub fn payload_size(&self) -> usize {
1098 let mut payload_size = 0;
1099
1100 payload_size += self.user_auth.payload_size();
1101 payload_size += self.data.payload_size();
1102
1103 payload_size
1104 }
1105 }
1106
1107 #[repr(C)]
1109 #[derive(Debug, Copy, Clone, FromBytes, IntoBytes, Immutable, KnownLayout)]
1110 pub struct Tpm2bSensitiveCreate {
1111 size: u16_be,
1112 sensitive: TpmsSensitiveCreate,
1113 }
1114
1115 impl Tpm2bSensitiveCreate {
1116 pub fn new(sensitive: TpmsSensitiveCreate) -> Self {
1117 let size = sensitive.payload_size() as u16;
1118 Self {
1119 size: size.into(),
1120 sensitive,
1121 }
1122 }
1123
1124 pub fn serialize(self) -> Vec<u8> {
1125 let mut buffer = Vec::new();
1126
1127 buffer.extend_from_slice(self.size.as_bytes());
1128 buffer.extend_from_slice(&self.sensitive.serialize());
1129
1130 buffer
1131 }
1132
1133 pub fn payload_size(&self) -> usize {
1134 let mut payload_size = 0;
1135 let size = self.size;
1136
1137 payload_size += size_of_val(&size);
1138 payload_size += self.sensitive.payload_size();
1139
1140 payload_size
1141 }
1142 }
1143
1144 #[repr(C)]
1146 #[derive(Debug, Copy, Clone, FromBytes, IntoBytes, Immutable, KnownLayout, PartialEq)]
1147 pub struct TpmtRsaScheme {
1148 scheme: AlgId,
1149 hash_alg: AlgId,
1150 }
1151
1152 impl TpmtRsaScheme {
1153 pub fn new(scheme: AlgId, hash_alg: Option<AlgId>) -> Self {
1154 let hash_alg = hash_alg.map_or_else(|| AlgId::new(0), |v| v);
1155
1156 Self { scheme, hash_alg }
1157 }
1158
1159 pub fn serialize(&self) -> Vec<u8> {
1160 let mut buffer = Vec::new();
1161
1162 buffer.extend_from_slice(self.scheme.as_bytes());
1163
1164 if self.scheme != AlgIdEnum::NULL.into() {
1166 buffer.extend_from_slice(self.hash_alg.as_bytes());
1168 }
1169
1170 buffer
1171 }
1172
1173 pub fn deserialize(bytes: &[u8]) -> Option<Self> {
1174 let mut start = 0;
1175 let mut end = size_of::<AlgId>();
1176
1177 if bytes.len() < end {
1178 return None;
1179 }
1180
1181 let scheme = AlgId::read_from_prefix(&bytes[start..end]).ok()?.0; let hash_alg = if scheme != AlgIdEnum::NULL.into() {
1184 start = end;
1185 end += size_of::<AlgId>();
1186 AlgId::read_from_prefix(&bytes[start..end]).ok()?.0 } else {
1188 AlgId::new(0)
1189 };
1190
1191 Some(Self { scheme, hash_alg })
1192 }
1193
1194 pub fn payload_size(&self) -> usize {
1195 let mut payload_size = 0;
1196
1197 payload_size += size_of_val(&self.scheme);
1198
1199 if self.scheme != AlgIdEnum::NULL.into() {
1200 payload_size += size_of_val(&self.hash_alg);
1201 }
1202
1203 payload_size
1204 }
1205 }
1206
1207 #[repr(C)]
1209 #[derive(Debug, Copy, Clone, FromBytes, IntoBytes, Immutable, KnownLayout, PartialEq)]
1210 pub struct TpmtSymDefObject {
1211 algorithm: AlgId,
1212 key_bits: u16_be,
1213 mode: AlgId,
1214 }
1215
1216 impl TpmtSymDefObject {
1217 pub fn new(algorithm: AlgId, key_bits: Option<u16>, mode: Option<AlgId>) -> Self {
1218 let key_bits = key_bits.map_or_else(|| new_u16_be(0), |v| v.into());
1219 let mode = mode.map_or_else(|| AlgId::new(0), |v| v);
1220
1221 Self {
1222 algorithm,
1223 key_bits,
1224 mode,
1225 }
1226 }
1227
1228 pub fn serialize(&self) -> Vec<u8> {
1229 let mut buffer = Vec::new();
1230
1231 buffer.extend_from_slice(self.algorithm.as_bytes());
1232
1233 if self.algorithm != AlgIdEnum::NULL.into() {
1235 buffer.extend_from_slice(self.key_bits.as_bytes());
1236 buffer.extend_from_slice(self.mode.as_bytes());
1237 }
1238
1239 buffer
1240 }
1241
1242 pub fn deserialize(bytes: &[u8]) -> Option<Self> {
1243 let mut start = 0;
1244 let mut end = size_of::<AlgId>();
1245
1246 if bytes.len() < end {
1247 return None;
1248 }
1249
1250 let algorithm = AlgId::read_from_prefix(&bytes[start..end]).ok()?.0; let (key_bits, mode) = if algorithm != AlgIdEnum::NULL.into() {
1253 start = end;
1254 end += size_of::<u16_be>();
1255 let key_bits = u16_be::read_from_bytes(&bytes[start..end]).ok()?; start = end;
1258 end += size_of::<AlgId>();
1259 let mode = AlgId::read_from_prefix(&bytes[start..end]).ok()?.0; (key_bits, mode)
1262 } else {
1263 (new_u16_be(0), AlgId::new(0))
1264 };
1265
1266 Some(Self {
1267 algorithm,
1268 key_bits,
1269 mode,
1270 })
1271 }
1272
1273 pub fn payload_size(&self) -> usize {
1274 let mut payload_size = 0;
1275
1276 payload_size += size_of_val(&self.algorithm);
1277
1278 if self.algorithm != AlgIdEnum::NULL.into() {
1279 payload_size += size_of_val(&self.key_bits);
1280 payload_size += size_of_val(&self.mode);
1281 }
1282
1283 payload_size
1284 }
1285 }
1286
1287 #[repr(C)]
1289 #[derive(Debug, Copy, Clone, FromBytes, IntoBytes, Immutable, KnownLayout, PartialEq)]
1290 pub struct TpmsRsaParams {
1291 symmetric: TpmtSymDefObject,
1292 scheme: TpmtRsaScheme,
1293 key_bits: u16_be,
1294 pub exponent: u32_be,
1295 }
1296
1297 impl TpmsRsaParams {
1298 pub fn new(
1299 symmetric: TpmtSymDefObject,
1300 scheme: TpmtRsaScheme,
1301 key_bits: u16,
1302 exponent: u32,
1303 ) -> Self {
1304 Self {
1305 symmetric,
1306 scheme,
1307 key_bits: key_bits.into(),
1308 exponent: exponent.into(),
1309 }
1310 }
1311
1312 pub fn serialize(&self) -> Vec<u8> {
1313 let mut buffer = Vec::new();
1314
1315 buffer.extend_from_slice(&self.symmetric.serialize());
1316 buffer.extend_from_slice(&self.scheme.serialize());
1317 buffer.extend_from_slice(self.key_bits.as_bytes());
1318 buffer.extend_from_slice(self.exponent.as_bytes());
1319
1320 buffer
1321 }
1322
1323 pub fn deserialize(bytes: &[u8]) -> Option<Self> {
1324 let mut start = 0;
1325 let mut end = 0;
1326
1327 let symmetric = TpmtSymDefObject::deserialize(&bytes[start..])?;
1328 end += symmetric.payload_size();
1329
1330 start = end;
1331 let scheme = TpmtRsaScheme::deserialize(&bytes[start..])?;
1332 end += scheme.payload_size();
1333
1334 start = end;
1337 end += size_of::<u16_be>();
1338 if bytes.len() < end {
1339 return None;
1340 }
1341 let key_bits = u16_be::read_from_bytes(&bytes[start..end]).ok()?;
1342
1343 start = end;
1346 end += size_of::<u32_be>();
1347 if bytes.len() < end {
1348 return None;
1349 }
1350 let exponent = u32_be::read_from_bytes(&bytes[start..end]).ok()?;
1351
1352 Some(Self {
1353 symmetric,
1354 scheme,
1355 key_bits,
1356 exponent,
1357 })
1358 }
1359
1360 pub fn payload_size(&self) -> usize {
1361 let mut payload_size = 0;
1362
1363 payload_size += self.symmetric.payload_size();
1364 payload_size += self.scheme.payload_size();
1365 payload_size += size_of_val(&self.key_bits);
1366 payload_size += size_of_val(&self.exponent);
1367
1368 payload_size
1369 }
1370 }
1371
1372 #[repr(C)]
1374 #[derive(Debug, Copy, Clone, FromBytes, IntoBytes, Immutable, KnownLayout)]
1375 pub struct TpmtPublic {
1376 my_type: AlgId,
1377 name_alg: AlgId,
1378 object_attributes: TpmaObject,
1379 auth_policy: Tpm2bBuffer,
1380 pub parameters: TpmsRsaParams,
1382 pub unique: Tpm2bBuffer,
1384 }
1385
1386 impl TpmtPublic {
1387 pub fn new(
1388 my_type: AlgId,
1389 name_alg: AlgId,
1390 object_attributes: TpmaObjectBits,
1391 auth_policy: &[u8],
1392 parameters: TpmsRsaParams,
1393 unique: &[u8],
1394 ) -> Result<Self, TpmProtoError> {
1395 let auth_policy =
1396 Tpm2bBuffer::new(auth_policy).map_err(TpmProtoError::TpmtPublicAuthPolicy)?;
1397 let unique = Tpm2bBuffer::new(unique).map_err(TpmProtoError::TpmtPublicUnique)?;
1398 Ok(Self {
1399 my_type,
1400 name_alg,
1401 object_attributes: object_attributes.into(),
1402 auth_policy,
1403 parameters,
1404 unique,
1405 })
1406 }
1407
1408 pub fn serialize(self) -> Vec<u8> {
1409 let mut buffer = Vec::new();
1410
1411 buffer.extend_from_slice(self.my_type.as_bytes());
1412 buffer.extend_from_slice(self.name_alg.as_bytes());
1413 buffer.extend_from_slice(self.object_attributes.as_bytes());
1414 buffer.extend_from_slice(&self.auth_policy.serialize());
1415 buffer.extend_from_slice(&self.parameters.serialize());
1416 buffer.extend_from_slice(&self.unique.serialize());
1417
1418 buffer
1419 }
1420
1421 pub fn deserialize(bytes: &[u8]) -> Option<Self> {
1422 let mut start = 0;
1423 let mut end = size_of::<AlgId>();
1424 if bytes.len() < end {
1425 return None;
1426 }
1427 let r#type = AlgId::read_from_prefix(&bytes[start..end]).ok()?.0; start = end;
1430 end += size_of::<AlgId>();
1431 if bytes.len() < end {
1432 return None;
1433 }
1434 let name_alg = AlgId::read_from_prefix(&bytes[start..end]).ok()?.0; start = end;
1437 end += size_of::<TpmaObject>();
1438 if bytes.len() < end {
1439 return None;
1440 }
1441 let object_attributes: u32 = u32_be::read_from_bytes(&bytes[start..end]).ok()?.into(); start = end;
1444 let auth_policy = Tpm2bBuffer::deserialize(&bytes[start..])?;
1445 end += auth_policy.payload_size();
1446 if bytes.len() < end {
1447 return None;
1448 }
1449
1450 start = end;
1451 let parameters = TpmsRsaParams::deserialize(&bytes[start..])?;
1452 end += parameters.payload_size();
1453
1454 start = end;
1455 let unique = Tpm2bBuffer::deserialize(&bytes[start..])?;
1456
1457 Some(Self {
1458 my_type: r#type,
1459 name_alg,
1460 object_attributes: object_attributes.into(),
1461 auth_policy,
1462 parameters,
1463 unique,
1464 })
1465 }
1466
1467 pub fn payload_size(&self) -> usize {
1468 let mut payload_size = 0;
1469
1470 payload_size += size_of_val(&self.my_type);
1471 payload_size += size_of_val(&self.name_alg);
1472 payload_size += size_of_val(&self.object_attributes);
1473 payload_size += self.auth_policy.payload_size();
1474 payload_size += self.parameters.payload_size();
1475 payload_size += self.unique.payload_size();
1476
1477 payload_size
1478 }
1479 }
1480
1481 #[repr(C)]
1483 #[derive(Debug, Copy, Clone, FromBytes, IntoBytes, Immutable, KnownLayout)]
1484 pub struct Tpm2bPublic {
1485 pub size: u16_be,
1486 pub public_area: TpmtPublic,
1487 }
1488
1489 impl Tpm2bPublic {
1490 pub fn new(public_area: TpmtPublic) -> Self {
1491 let size = public_area.payload_size() as u16;
1492 Self {
1493 size: size.into(),
1494 public_area,
1495 }
1496 }
1497
1498 pub fn serialize(self) -> Vec<u8> {
1499 let mut buffer = Vec::new();
1500
1501 buffer.extend_from_slice(self.size.as_bytes());
1502 buffer.extend_from_slice(&self.public_area.serialize());
1503
1504 buffer
1505 }
1506
1507 pub fn deserialize(bytes: &[u8]) -> Option<Self> {
1508 let mut start = 0;
1509 let end = size_of::<u16_be>();
1510
1511 if bytes.len() < end {
1512 return None;
1513 }
1514
1515 let size = u16_be::read_from_bytes(&bytes[start..end]).ok()?; start = end;
1518 let public_area = TpmtPublic::deserialize(&bytes[start..])?;
1519
1520 Some(Self { size, public_area })
1521 }
1522
1523 pub fn payload_size(&self) -> usize {
1524 let mut payload_size = 0;
1525
1526 payload_size += size_of_val(&self.size);
1527 payload_size += self.public_area.payload_size();
1528
1529 payload_size
1530 }
1531 }
1532
1533 #[repr(C)]
1535 #[derive(Debug, FromBytes, IntoBytes, Immutable, KnownLayout)]
1536 pub struct TpmsCreationData {
1537 pcr_select: TpmlPcrSelection,
1538 pcr_digest: Tpm2bBuffer,
1539 locality: u8,
1540 parent_name_alg: AlgId,
1541 parent_name: Tpm2bBuffer,
1542 parent_qualified_name: Tpm2bBuffer,
1543 outside_info: Tpm2bBuffer,
1544 }
1545
1546 impl TpmsCreationData {
1547 pub fn deserialize(bytes: &[u8]) -> Option<Self> {
1548 let mut start = 0;
1549 let mut end = 0;
1550
1551 let pcr_select = TpmlPcrSelection::deserialize(&bytes[start..])?;
1552 end += pcr_select.payload_size();
1553
1554 start = end;
1555 let pcr_digest = Tpm2bBuffer::deserialize(&bytes[start..])?;
1556 end += pcr_digest.payload_size();
1557
1558 start = end;
1559 end += size_of::<u8>();
1560 if bytes.len() < end {
1561 return None;
1562 }
1563 let locality = bytes[start];
1564
1565 start = end;
1566 end += size_of::<AlgId>();
1567 if bytes.len() < end {
1568 return None;
1569 }
1570 let parent_name_alg = AlgId::read_from_prefix(&bytes[start..end]).ok()?.0; start = end;
1573 let parent_name = Tpm2bBuffer::deserialize(&bytes[start..])?;
1574 end += parent_name.payload_size();
1575
1576 start = end;
1577 let parent_qualified_name = Tpm2bBuffer::deserialize(&bytes[start..])?;
1578 end += parent_qualified_name.payload_size();
1579
1580 start = end;
1581 let outside_info = Tpm2bBuffer::deserialize(&bytes[start..])?;
1582
1583 Some(Self {
1584 pcr_select,
1585 pcr_digest,
1586 locality,
1587 parent_name_alg,
1588 parent_name,
1589 parent_qualified_name,
1590 outside_info,
1591 })
1592 }
1593
1594 pub fn payload_size(&self) -> usize {
1595 let mut payload_size = 0;
1596
1597 payload_size += self.pcr_select.payload_size();
1598 payload_size += self.pcr_digest.payload_size();
1599 payload_size += size_of_val(&self.locality);
1600 payload_size += size_of_val(&self.parent_name_alg);
1601 payload_size += self.parent_name.payload_size();
1602 payload_size += self.parent_qualified_name.payload_size();
1603 payload_size += self.outside_info.payload_size();
1604
1605 payload_size
1606 }
1607 }
1608
1609 #[derive(Debug, FromBytes, IntoBytes, Immutable, KnownLayout)]
1611 #[repr(C)]
1612 pub struct Tpm2bCreationData {
1613 size: u16_be,
1614 creation_data: TpmsCreationData,
1615 }
1616
1617 impl Tpm2bCreationData {
1618 pub fn deserialize(bytes: &[u8]) -> Option<Self> {
1619 let mut start = 0;
1620 let end = size_of::<u16_be>();
1621
1622 if bytes.len() < end {
1623 return None;
1624 }
1625
1626 let size = u16_be::read_from_bytes(&bytes[start..end]).ok()?; start = end;
1629 let creation_data = TpmsCreationData::deserialize(&bytes[start..])?;
1630
1631 Some(Self {
1632 size,
1633 creation_data,
1634 })
1635 }
1636
1637 pub fn payload_size(&self) -> usize {
1638 let mut payload_size = 0;
1639
1640 payload_size += size_of_val(&self.size);
1641 payload_size += self.creation_data.payload_size();
1642
1643 payload_size
1644 }
1645 }
1646
1647 #[repr(C)]
1649 #[derive(Debug, FromBytes, IntoBytes, Immutable, KnownLayout)]
1650 pub struct TpmtTkCreation {
1651 tag: SessionTag,
1652 hierarchy: ReservedHandle,
1653 digest: Tpm2bBuffer,
1654 }
1655
1656 impl TpmtTkCreation {
1657 pub fn deserialize(bytes: &[u8]) -> Option<Self> {
1658 let mut start = 0;
1659 let mut end = size_of::<SessionTag>();
1660 if bytes.len() < end {
1661 return None;
1662 }
1663 let tag = SessionTag::read_from_prefix(&bytes[start..end]).ok()?.0; start = end;
1666 end += size_of::<ReservedHandle>();
1667 if bytes.len() < end {
1668 return None;
1669 }
1670 let hierarchy = ReservedHandle::read_from_prefix(&bytes[start..end]).ok()?.0; start = end;
1673 let digest = Tpm2bBuffer::deserialize(&bytes[start..])?;
1674
1675 Some(Self {
1676 tag,
1677 hierarchy,
1678 digest,
1679 })
1680 }
1681
1682 pub fn payload_size(&self) -> usize {
1683 let mut payload_size = 0;
1684
1685 payload_size += size_of_val(&self.tag);
1686 payload_size += size_of_val(&self.hierarchy);
1687 payload_size += self.digest.payload_size();
1688
1689 payload_size
1690 }
1691 }
1692
1693 #[repr(C)]
1695 #[derive(Debug, Copy, Clone, FromBytes, IntoBytes, Immutable, KnownLayout)]
1696 pub struct TpmsNvPublic {
1697 nv_index: u32_be,
1698 name_alg: AlgId,
1699 pub attributes: TpmaNv,
1700 auth_policy: Tpm2bBuffer,
1701 pub data_size: u16_be,
1702 }
1703
1704 impl TpmsNvPublic {
1705 pub fn new(
1706 nv_index: u32,
1707 name_alg: AlgId,
1708 attributes: TpmaNvBits,
1709 auth_policy: &[u8],
1710 data_size: u16,
1711 ) -> Result<Self, TpmProtoError> {
1712 let auth_policy =
1713 Tpm2bBuffer::new(auth_policy).map_err(TpmProtoError::TpmsNvPublicAuthPolicy)?;
1714
1715 Ok(Self {
1716 nv_index: nv_index.into(),
1717 name_alg,
1718 attributes: attributes.into(),
1719 auth_policy,
1720 data_size: data_size.into(),
1721 })
1722 }
1723
1724 pub fn serialize(self) -> Vec<u8> {
1725 let mut buffer = Vec::new();
1726
1727 buffer.extend_from_slice(self.nv_index.as_bytes());
1728 buffer.extend_from_slice(self.name_alg.as_bytes());
1729 buffer.extend_from_slice(self.attributes.as_bytes());
1730 buffer.extend_from_slice(&self.auth_policy.serialize());
1731 buffer.extend_from_slice(self.data_size.as_bytes());
1732
1733 buffer
1734 }
1735
1736 pub fn deserialize(bytes: &[u8]) -> Option<Self> {
1737 let mut start = 0;
1738 let mut end = size_of::<u32_be>();
1739 if bytes.len() < end {
1740 return None;
1741 }
1742 let nv_index: u32 = u32_be::read_from_bytes(&bytes[start..end]).ok()?.into(); start = end;
1745 end += size_of::<AlgId>();
1746 if bytes.len() < end {
1747 return None;
1748 }
1749 let name_alg = AlgId::read_from_prefix(&bytes[start..end]).ok()?.0; start = end;
1752 end += size_of::<TpmaNv>();
1753 if bytes.len() < end {
1754 return None;
1755 }
1756 let attributes: u32 = u32_be::read_from_bytes(&bytes[start..end]).ok()?.into(); start = end;
1759 let auth_policy = Tpm2bBuffer::deserialize(&bytes[start..])?;
1760 end += auth_policy.payload_size();
1761
1762 start = end;
1763 end += size_of::<u16_be>();
1764 if bytes.len() < end {
1765 return None;
1766 }
1767 let data_size = u16_be::read_from_bytes(&bytes[start..end]).ok()?; Some(Self {
1770 nv_index: nv_index.into(),
1771 name_alg,
1772 attributes: attributes.into(),
1773 auth_policy,
1774 data_size,
1775 })
1776 }
1777
1778 pub fn payload_size(&self) -> usize {
1779 let mut payload_size = 0;
1780
1781 payload_size += size_of_val(&self.nv_index);
1782 payload_size += size_of_val(&self.name_alg);
1783 payload_size += size_of_val(&self.attributes);
1784 payload_size += self.auth_policy.payload_size();
1785 payload_size += size_of_val(&self.data_size);
1786
1787 payload_size
1788 }
1789 }
1790
1791 #[repr(C)]
1793 #[derive(Debug, Copy, Clone, FromBytes, IntoBytes, Immutable, KnownLayout)]
1794 pub struct Tpm2bNvPublic {
1795 size: u16_be,
1796 pub nv_public: TpmsNvPublic,
1797 }
1798
1799 impl Tpm2bNvPublic {
1800 pub fn new(nv_public: TpmsNvPublic) -> Result<Self, InvalidInput> {
1801 let size = nv_public.payload_size();
1802 if size > u16::MAX.into() {
1803 Err(InvalidInput::NvPublicPayloadTooLarge(size, u16::MAX.into()))?
1804 }
1805
1806 Ok(Self {
1807 size: (size as u16).into(),
1808 nv_public,
1809 })
1810 }
1811
1812 pub fn serialize(self) -> Vec<u8> {
1813 let mut buffer = Vec::new();
1814
1815 buffer.extend_from_slice(self.size.as_bytes());
1816 buffer.extend_from_slice(&self.nv_public.serialize());
1817
1818 buffer
1819 }
1820
1821 pub fn deserialize(bytes: &[u8]) -> Option<Self> {
1822 let mut start = 0;
1823 let end = size_of::<u16_be>();
1824
1825 if bytes.len() < end {
1826 return None;
1827 }
1828
1829 let size = u16_be::read_from_bytes(&bytes[start..end]).ok()?; start = end;
1832 let nv_public = TpmsNvPublic::deserialize(&bytes[start..])?;
1833
1834 Some(Self { size, nv_public })
1835 }
1836
1837 pub fn payload_size(&self) -> usize {
1838 let mut payload_size = 0;
1839
1840 payload_size += size_of_val(&self.size);
1841 payload_size += self.nv_public.payload_size();
1842
1843 payload_size
1844 }
1845 }
1846
1847 #[repr(C)]
1850 #[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
1851 pub struct ClearControlCmd {
1852 header: CmdHeader,
1853 auth_handle: ReservedHandle,
1854 auth_size: u32_be,
1855 auth: common::CmdAuth,
1856 disable: u8,
1857 }
1858
1859 impl ClearControlCmd {
1860 pub fn new(
1861 session: SessionTag,
1862 auth_handle: ReservedHandle,
1863 auth: common::CmdAuth,
1864 disable: bool,
1865 ) -> Self {
1866 Self {
1867 header: CmdHeader::new::<Self>(session, CommandCodeEnum::ClearControl.into()),
1868 auth_handle,
1869 auth_size: (size_of::<common::CmdAuth>() as u32).into(),
1870 auth,
1871 disable: disable as u8,
1872 }
1873 }
1874 }
1875
1876 #[repr(C)]
1877 #[derive(Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
1878 pub struct ClearControlReply {
1879 pub header: ReplyHeader,
1880 pub param_size: u32_be,
1881 pub auth: common::ReplyAuth,
1882 }
1883
1884 impl TpmCommand for ClearControlCmd {
1885 type Reply = ClearControlReply;
1886 }
1887
1888 impl TpmReply for ClearControlReply {
1889 type Command = ClearControlCmd;
1890
1891 fn deserialize(bytes: &[u8]) -> Option<Self> {
1892 Some(Self::read_from_prefix(bytes).ok()?.0) }
1894
1895 fn payload_size(&self) -> usize {
1896 size_of::<Self>()
1897 }
1898 }
1899
1900 #[repr(C)]
1903 #[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
1904 pub struct ClearCmd {
1905 header: CmdHeader,
1906
1907 auth_handle: ReservedHandle,
1908 auth_size: u32_be,
1909 auth: common::CmdAuth,
1910 }
1911
1912 impl ClearCmd {
1913 pub fn new(
1914 session: SessionTag,
1915 auth_handle: ReservedHandle,
1916 auth: common::CmdAuth,
1917 ) -> Self {
1918 Self {
1919 header: CmdHeader::new::<Self>(session, CommandCodeEnum::Clear.into()),
1920 auth_handle,
1921 auth_size: (size_of::<common::CmdAuth>() as u32).into(),
1922 auth,
1923 }
1924 }
1925 }
1926
1927 #[repr(C)]
1928 #[derive(Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
1929 pub struct ClearReply {
1930 pub header: ReplyHeader,
1931 pub param_size: u32_be,
1932 pub auth: common::ReplyAuth,
1933 }
1934
1935 impl TpmCommand for ClearCmd {
1936 type Reply = ClearReply;
1937 }
1938
1939 impl TpmReply for ClearReply {
1940 type Command = ClearCmd;
1941
1942 fn deserialize(bytes: &[u8]) -> Option<Self> {
1943 Some(Self::read_from_prefix(bytes).ok()?.0) }
1945
1946 fn payload_size(&self) -> usize {
1947 size_of::<Self>()
1948 }
1949 }
1950
1951 #[expect(dead_code)]
1954 pub enum StartupType {
1955 Clear,
1956 State,
1957 }
1958
1959 #[repr(C)]
1960 #[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
1961 pub struct StartupCmd {
1962 header: CmdHeader,
1963 startup_type: u16_be,
1964 }
1965
1966 impl StartupCmd {
1967 pub fn new(session_tag: SessionTag, startup_type: StartupType) -> StartupCmd {
1968 StartupCmd {
1969 header: CmdHeader::new::<Self>(session_tag, CommandCodeEnum::Startup.into()),
1970 startup_type: match startup_type {
1971 StartupType::Clear => 0,
1972 StartupType::State => 1,
1973 }
1974 .into(),
1975 }
1976 }
1977 }
1978
1979 #[repr(C)]
1980 #[derive(Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
1981 pub struct StartupReply {
1982 pub header: ReplyHeader,
1983 }
1984
1985 impl TpmCommand for StartupCmd {
1986 type Reply = StartupReply;
1987 }
1988
1989 impl TpmReply for StartupReply {
1990 type Command = StartupCmd;
1991
1992 fn deserialize(bytes: &[u8]) -> Option<Self> {
1993 Some(Self::read_from_prefix(bytes).ok()?.0) }
1995
1996 fn payload_size(&self) -> usize {
1997 size_of::<Self>()
1998 }
1999 }
2000
2001 #[repr(C)]
2004 #[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
2005 pub struct SelfTestCmd {
2006 header: CmdHeader,
2007 full_test: u8,
2008 }
2009
2010 impl SelfTestCmd {
2011 pub fn new(session_tag: SessionTag, full_test: bool) -> SelfTestCmd {
2012 SelfTestCmd {
2013 header: CmdHeader::new::<Self>(session_tag, CommandCodeEnum::SelfTest.into()),
2014 full_test: full_test as u8,
2015 }
2016 }
2017 }
2018
2019 #[repr(C)]
2020 #[derive(Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
2021 pub struct SelfTestReply {
2022 pub header: ReplyHeader,
2023 }
2024
2025 impl TpmCommand for SelfTestCmd {
2026 type Reply = SelfTestReply;
2027 }
2028
2029 impl TpmReply for SelfTestReply {
2030 type Command = SelfTestCmd;
2031
2032 fn deserialize(bytes: &[u8]) -> Option<Self> {
2033 Some(Self::read_from_prefix(bytes).ok()?.0) }
2035
2036 fn payload_size(&self) -> usize {
2037 size_of::<Self>()
2038 }
2039 }
2040
2041 #[repr(C)]
2044 #[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
2045 pub struct HierarchyControlCmd {
2046 header: CmdHeader,
2047
2048 auth_handle: ReservedHandle,
2049 auth_size: u32_be,
2050 auth: common::CmdAuth,
2051
2052 hierarchy: ReservedHandle,
2053 state: u8,
2054 }
2055
2056 impl HierarchyControlCmd {
2057 pub fn new(
2058 session: SessionTag,
2059 auth_handle: ReservedHandle,
2060 auth: common::CmdAuth,
2061 hierarchy: ReservedHandle,
2062 state: bool,
2063 ) -> Self {
2064 Self {
2065 header: CmdHeader::new::<Self>(session, CommandCodeEnum::HierarchyControl.into()),
2066 auth_handle,
2067 auth_size: (size_of::<common::CmdAuth>() as u32).into(),
2068 auth,
2069 hierarchy,
2070 state: state as u8,
2071 }
2072 }
2073 }
2074
2075 #[repr(C)]
2076 #[derive(Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
2077 pub struct HierarchyControlReply {
2078 pub header: ReplyHeader,
2079 pub param_size: u32_be,
2080 pub auth: common::ReplyAuth,
2081 }
2082
2083 impl TpmCommand for HierarchyControlCmd {
2084 type Reply = HierarchyControlReply;
2085 }
2086
2087 impl TpmReply for HierarchyControlReply {
2088 type Command = HierarchyControlCmd;
2089
2090 fn deserialize(bytes: &[u8]) -> Option<Self> {
2091 Some(Self::read_from_prefix(bytes).ok()?.0) }
2093
2094 fn payload_size(&self) -> usize {
2095 size_of::<Self>()
2096 }
2097 }
2098
2099 #[repr(C)]
2102 #[derive(Debug, Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
2103 pub struct PcrSelection {
2104 pub hash: AlgId,
2105 pub size_of_select: u8,
2106 pub bitmap: [u8; 3],
2107 }
2108
2109 impl PcrSelection {
2110 pub fn serialize(self) -> Vec<u8> {
2111 let mut buffer = Vec::new();
2112
2113 buffer.extend_from_slice(self.hash.as_bytes());
2114 buffer.extend_from_slice(self.size_of_select.as_bytes());
2115 buffer.extend_from_slice(&self.bitmap[..self.size_of_select as usize]);
2116
2117 buffer
2118 }
2119
2120 pub fn deserialize(bytes: &[u8]) -> Option<Self> {
2121 let mut start = 0;
2122 let mut end = size_of::<AlgId>();
2123 if bytes.len() < end {
2124 return None;
2125 }
2126 let hash = AlgId::read_from_prefix(&bytes[start..end]).ok()?.0; start = end;
2129 end += size_of::<u8>();
2130 if bytes.len() < end {
2131 return None;
2132 }
2133 let size_of_select = bytes[start];
2134 if size_of_select > 3 {
2135 return None;
2136 }
2137
2138 start = end;
2139 end += size_of_select as usize;
2140 if bytes.len() < end {
2141 return None;
2142 }
2143 let mut bitmap = [0u8; 3];
2144 bitmap[..size_of_select as usize].copy_from_slice(&bytes[start..end]);
2145
2146 Some(Self {
2147 hash,
2148 size_of_select,
2149 bitmap,
2150 })
2151 }
2152
2153 pub fn payload_size(&self) -> usize {
2154 let mut payload_size = 0;
2155
2156 payload_size += size_of_val(&self.hash);
2157 payload_size += size_of_val(&self.size_of_select);
2158 payload_size += self.size_of_select as usize;
2159
2160 payload_size
2161 }
2162 }
2163
2164 #[repr(C)]
2165 #[derive(Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
2166 pub struct PcrAllocateCmd {
2167 header: CmdHeader,
2168 auth_handle: ReservedHandle,
2169 auth_size: u32_be,
2171 auth: common::CmdAuth,
2172 pcr_allocation: TpmlPcrSelection,
2174 }
2175
2176 impl PcrAllocateCmd {
2177 pub const HASH_ALG_TO_ID: [(u32, AlgId); 5] = [
2178 (1 << 0, AlgId::new(AlgIdEnum::SHA as u16)),
2179 (1 << 1, AlgId::new(AlgIdEnum::SHA256 as u16)),
2180 (1 << 2, AlgId::new(AlgIdEnum::SHA384 as u16)),
2181 (1 << 3, AlgId::new(AlgIdEnum::SHA512 as u16)),
2182 (1 << 4, AlgId::new(AlgIdEnum::SM3_256 as u16)),
2183 ];
2184
2185 pub fn new(
2189 session: SessionTag,
2190 auth_handle: ReservedHandle,
2191 auth: common::CmdAuth,
2192 pcr_selections: &[PcrSelection],
2193 ) -> Result<Self, TpmProtoError> {
2194 let pcr_allocation = TpmlPcrSelection::new(pcr_selections)
2195 .map_err(TpmProtoError::PcrAllocatePcrAllocation)?;
2196
2197 let mut cmd = Self {
2198 header: CmdHeader::new::<Self>(session, CommandCodeEnum::PCR_Allocate.into()),
2199 auth_handle,
2200 auth_size: (size_of::<common::CmdAuth>() as u32).into(),
2201 auth,
2202 pcr_allocation,
2203 };
2204
2205 cmd.header.size = new_u32_be(cmd.payload_size() as u32);
2206
2207 Ok(cmd)
2208 }
2209
2210 pub fn serialize(&self) -> Vec<u8> {
2211 let mut buffer = Vec::new();
2212
2213 buffer.extend_from_slice(self.header.as_bytes());
2214 buffer.extend_from_slice(self.auth_handle.as_bytes());
2215 buffer.extend_from_slice(self.auth_size.as_bytes());
2216 buffer.extend_from_slice(self.auth.as_bytes());
2217 buffer.extend_from_slice(&self.pcr_allocation.serialize());
2218
2219 buffer
2220 }
2221
2222 pub fn payload_size(&self) -> usize {
2223 let mut payload_size = 0;
2224
2225 payload_size += size_of_val(&self.header);
2226 payload_size += size_of_val(&self.auth_handle);
2227 payload_size += size_of_val(&self.auth_size);
2228 payload_size += size_of_val(&self.auth);
2229 payload_size += self.pcr_allocation.payload_size();
2230
2231 payload_size
2232 }
2233 }
2234
2235 #[repr(C)]
2236 #[derive(Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
2237 pub struct PcrAllocateReply {
2238 pub header: ReplyHeader,
2239 pub auth_size: u32_be,
2240 pub allocation_success: u8,
2241 pub max_pcr: u32_be,
2242 pub size_needed: u32_be,
2243 pub size_available: u32_be,
2244
2245 pub auth: common::ReplyAuth,
2246 }
2247
2248 impl TpmCommand for PcrAllocateCmd {
2249 type Reply = PcrAllocateReply;
2250 }
2251
2252 impl TpmReply for PcrAllocateReply {
2253 type Command = PcrAllocateCmd;
2254
2255 fn deserialize(bytes: &[u8]) -> Option<Self> {
2256 Some(Self::read_from_prefix(bytes).ok()?.0) }
2258
2259 fn payload_size(&self) -> usize {
2260 size_of::<Self>()
2261 }
2262 }
2263
2264 #[repr(C)]
2267 #[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
2268 pub struct ChangeSeedCmd {
2269 header: CmdHeader,
2270 auth_handle: ReservedHandle,
2271 auth_size: u32_be,
2272 auth: common::CmdAuth,
2273 }
2274
2275 impl ChangeSeedCmd {
2276 pub fn new(
2277 session: SessionTag,
2278 auth_handle: ReservedHandle,
2279 auth: common::CmdAuth,
2280 command_code: CommandCodeEnum,
2281 ) -> Self {
2282 Self {
2283 header: CmdHeader::new::<Self>(session, command_code.into()),
2284 auth_handle,
2285 auth_size: (size_of::<common::CmdAuth>() as u32).into(),
2286 auth,
2287 }
2288 }
2289 }
2290
2291 #[repr(C)]
2292 #[derive(Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
2293 pub struct ChangeSeedReply {
2294 pub header: ReplyHeader,
2295 pub param_size: u32_be,
2296
2297 pub auth: common::ReplyAuth,
2298 }
2299
2300 impl TpmCommand for ChangeSeedCmd {
2301 type Reply = ChangeSeedReply;
2302 }
2303
2304 impl TpmReply for ChangeSeedReply {
2305 type Command = ChangeSeedCmd;
2306
2307 fn deserialize(bytes: &[u8]) -> Option<Self> {
2308 Some(Self::read_from_prefix(bytes).ok()?.0) }
2310
2311 fn payload_size(&self) -> usize {
2312 size_of::<Self>()
2313 }
2314 }
2315
2316 #[repr(C)]
2319 #[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
2320 pub struct CreatePrimaryCmd {
2321 pub header: CmdHeader,
2322 primary_handle: ReservedHandle,
2323 auth_size: u32_be,
2325 auth: common::CmdAuth,
2326 in_sensitive: Tpm2bSensitiveCreate,
2328 in_public: Tpm2bPublic,
2329 outside_info: Tpm2bBuffer,
2330 creation_pcr: TpmlPcrSelection,
2331 }
2332
2333 impl CreatePrimaryCmd {
2334 pub fn new(
2335 session: SessionTag,
2336 primary_handle: ReservedHandle,
2337 auth: common::CmdAuth,
2338 in_sensitive_user_auth: &[u8],
2339 in_sensitive_data: &[u8],
2340 in_public: TpmtPublic,
2341 outside_info: &[u8],
2342 creation_pcr: &[PcrSelection],
2343 ) -> Result<Self, TpmProtoError> {
2344 let sensitive_create =
2345 TpmsSensitiveCreate::new(in_sensitive_user_auth, in_sensitive_data)?;
2346 let in_sensitive = Tpm2bSensitiveCreate::new(sensitive_create);
2347 let in_public = Tpm2bPublic::new(in_public);
2348 let outside_info =
2349 Tpm2bBuffer::new(outside_info).map_err(TpmProtoError::CreatePrimaryOutsideInfo)?;
2350 let creation_pcr = TpmlPcrSelection::new(creation_pcr)
2351 .map_err(TpmProtoError::CreatePrimaryCreationPcr)?;
2352
2353 let mut cmd = Self {
2354 header: CmdHeader::new::<Self>(session, CommandCodeEnum::CreatePrimary.into()),
2355 primary_handle,
2356 auth_size: (size_of::<common::CmdAuth>() as u32).into(),
2357 auth,
2358 in_sensitive,
2359 in_public,
2360 outside_info,
2361 creation_pcr,
2362 };
2363
2364 cmd.header.size = new_u32_be(cmd.payload_size() as u32);
2365
2366 Ok(cmd)
2367 }
2368
2369 pub fn serialize(&self) -> Vec<u8> {
2370 let mut buffer = Vec::new();
2371
2372 buffer.extend_from_slice(self.header.as_bytes());
2373 buffer.extend_from_slice(self.primary_handle.as_bytes());
2374 buffer.extend_from_slice(self.auth_size.as_bytes());
2375 buffer.extend_from_slice(self.auth.as_bytes());
2376 buffer.extend_from_slice(&self.in_sensitive.serialize());
2377 buffer.extend_from_slice(&self.in_public.serialize());
2378 buffer.extend_from_slice(&self.outside_info.serialize());
2379 buffer.extend_from_slice(&self.creation_pcr.serialize());
2380
2381 buffer
2382 }
2383
2384 pub fn payload_size(&self) -> usize {
2385 let mut payload_size = 0;
2386
2387 payload_size += size_of_val(&self.header);
2388 payload_size += size_of_val(&self.primary_handle);
2389 payload_size += size_of_val(&self.auth_size);
2390 payload_size += size_of_val(&self.auth);
2391 payload_size += self.in_sensitive.payload_size();
2392 payload_size += self.in_public.payload_size();
2393 payload_size += self.outside_info.payload_size();
2394 payload_size += self.creation_pcr.payload_size();
2395
2396 payload_size
2397 }
2398 }
2399
2400 #[repr(C)]
2401 #[derive(Debug, FromBytes, IntoBytes, Immutable, KnownLayout)]
2402 pub struct CreatePrimaryReply {
2403 pub header: ReplyHeader,
2404 pub object_handle: ReservedHandle,
2405 param_size: u32_be,
2407 pub out_public: Tpm2bPublic,
2409 creation_data: Tpm2bCreationData,
2410 creation_hash: Tpm2bBuffer,
2411 creation_ticket: TpmtTkCreation,
2412 name: Tpm2bBuffer,
2413 auth: common::ReplyAuth,
2415 }
2416
2417 impl TpmCommand for CreatePrimaryCmd {
2418 type Reply = CreatePrimaryReply;
2419 }
2420
2421 impl TpmReply for CreatePrimaryReply {
2422 type Command = CreatePrimaryCmd;
2423
2424 fn deserialize(bytes: &[u8]) -> Option<Self> {
2425 let mut start = 0;
2426 let mut end = size_of::<ReplyHeader>();
2427 let header = ReplyHeader::read_from_prefix(&bytes[start..end]).ok()?.0; if header.size.get() as usize == end {
2431 let mut cmd = CreatePrimaryReply::new_zeroed();
2432 cmd.header = header;
2433 return Some(cmd);
2434 }
2435
2436 start = end;
2437 end += size_of::<ReservedHandle>();
2438 let object_handle = ReservedHandle::read_from_prefix(&bytes[start..end]).ok()?.0; start = end;
2441 end += size_of::<u32_be>();
2442 let param_size = u32_be::read_from_bytes(&bytes[start..end]).ok()?; start = end;
2445 let out_public = Tpm2bPublic::deserialize(&bytes[start..])?;
2446 end += out_public.payload_size();
2447
2448 start = end;
2449 let creation_data = Tpm2bCreationData::deserialize(&bytes[start..])?;
2450 end += creation_data.payload_size();
2451
2452 start = end;
2453 let creation_hash = Tpm2bBuffer::deserialize(&bytes[start..])?;
2454 end += creation_hash.payload_size();
2455
2456 start = end;
2457 let creation_ticket = TpmtTkCreation::deserialize(&bytes[start..])?;
2458 end += creation_ticket.payload_size();
2459
2460 start = end;
2461 let name = Tpm2bBuffer::deserialize(&bytes[start..])?;
2462 end += name.payload_size();
2463
2464 start = end;
2465 end += size_of::<common::ReplyAuth>();
2466 let auth = common::ReplyAuth::read_from_prefix(&bytes[start..end])
2467 .ok()?
2468 .0; if header.size.get() as usize != end {
2471 return None;
2472 }
2473
2474 Some(Self {
2475 header,
2476 object_handle,
2477 param_size,
2478 out_public,
2479 creation_data,
2480 creation_hash,
2481 creation_ticket,
2482 name,
2483 auth,
2484 })
2485 }
2486
2487 fn payload_size(&self) -> usize {
2488 let mut payload_size = 0;
2489
2490 payload_size += size_of_val(&self.header);
2491 payload_size += size_of_val(&self.object_handle);
2492 payload_size += size_of_val(&self.param_size);
2493 payload_size += self.out_public.payload_size();
2494 payload_size += self.creation_data.payload_size();
2495 payload_size += self.creation_hash.payload_size();
2496 payload_size += self.creation_ticket.payload_size();
2497 payload_size += self.name.payload_size();
2498 payload_size += size_of_val(&self.auth);
2499
2500 payload_size
2501 }
2502 }
2503
2504 #[repr(C)]
2507 #[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
2508 pub struct FlushContextCmd {
2509 pub header: CmdHeader,
2510 flush_handle: ReservedHandle,
2512 }
2513
2514 impl FlushContextCmd {
2515 pub fn new(flush_handle: ReservedHandle) -> Self {
2516 Self {
2517 header: CmdHeader::new::<Self>(
2518 SessionTagEnum::NoSessions.into(),
2519 CommandCodeEnum::FlushContext.into(),
2520 ),
2521 flush_handle,
2522 }
2523 }
2524 }
2525
2526 #[repr(C)]
2527 #[derive(Debug, FromBytes, IntoBytes, Immutable, KnownLayout)]
2528 pub struct FlushContextReply {
2529 pub header: ReplyHeader,
2530 }
2531
2532 impl TpmCommand for FlushContextCmd {
2533 type Reply = FlushContextReply;
2534 }
2535
2536 impl TpmReply for FlushContextReply {
2537 type Command = FlushContextCmd;
2538
2539 fn deserialize(bytes: &[u8]) -> Option<Self> {
2540 Some(Self::read_from_prefix(bytes).ok()?.0) }
2542
2543 fn payload_size(&self) -> usize {
2544 size_of::<Self>()
2545 }
2546 }
2547
2548 #[repr(C)]
2551 #[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
2552 pub struct EvictControlCmd {
2553 header: CmdHeader,
2554 auth_handle: ReservedHandle,
2555 object_handle: ReservedHandle,
2556 auth_size: u32_be,
2558 auth: common::CmdAuth,
2559 persistent_handle: ReservedHandle,
2561 }
2562
2563 impl EvictControlCmd {
2564 pub fn new(
2565 session: SessionTag,
2566 auth_handle: ReservedHandle,
2567 object_handle: ReservedHandle,
2568 auth: common::CmdAuth,
2569 persistent_handle: ReservedHandle,
2570 ) -> Self {
2571 Self {
2572 header: CmdHeader::new::<Self>(session, CommandCodeEnum::EvictControl.into()),
2573 auth_handle,
2574 object_handle,
2575 auth_size: (size_of::<common::CmdAuth>() as u32).into(),
2576 auth,
2577 persistent_handle,
2578 }
2579 }
2580 }
2581
2582 #[repr(C)]
2583 #[derive(Debug, FromBytes, IntoBytes, Immutable, KnownLayout)]
2584 pub struct EvictControlReply {
2585 pub header: ReplyHeader,
2586 }
2587
2588 impl TpmCommand for EvictControlCmd {
2589 type Reply = EvictControlReply;
2590 }
2591
2592 impl TpmReply for EvictControlReply {
2593 type Command = EvictControlCmd;
2594
2595 fn deserialize(bytes: &[u8]) -> Option<Self> {
2596 Some(Self::read_from_prefix(bytes).ok()?.0) }
2598
2599 fn payload_size(&self) -> usize {
2600 size_of::<Self>()
2601 }
2602 }
2603
2604 #[repr(C)]
2607 #[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
2608 pub struct ReadPublicCmd {
2609 header: CmdHeader,
2610 object_handle: ReservedHandle,
2611 }
2612
2613 impl ReadPublicCmd {
2614 pub fn new(session: SessionTag, object_handle: ReservedHandle) -> Self {
2615 Self {
2616 header: CmdHeader::new::<Self>(session, CommandCodeEnum::ReadPublic.into()),
2617 object_handle,
2618 }
2619 }
2620 }
2621
2622 #[repr(C)]
2623 #[derive(Debug, FromBytes, IntoBytes, Immutable, KnownLayout)]
2624 pub struct ReadPublicReply {
2625 pub header: ReplyHeader,
2626 pub out_public: Tpm2bPublic,
2627 name: Tpm2bBuffer,
2628 qualified_name: Tpm2bBuffer,
2629 }
2630
2631 impl TpmCommand for ReadPublicCmd {
2632 type Reply = ReadPublicReply;
2633 }
2634
2635 impl TpmReply for ReadPublicReply {
2636 type Command = ReadPublicCmd;
2637
2638 fn deserialize(bytes: &[u8]) -> Option<Self> {
2639 let mut start = 0;
2640 let mut end = size_of::<ReplyHeader>();
2641
2642 let header = ReplyHeader::read_from_prefix(&bytes[start..end]).ok()?.0; if header.size.get() as usize == end {
2646 return Some(Self {
2647 header,
2648 out_public: Tpm2bPublic::new_zeroed(),
2649 name: Tpm2bBuffer::new_zeroed(),
2650 qualified_name: Tpm2bBuffer::new_zeroed(),
2651 });
2652 }
2653
2654 start = end;
2655 let out_public = Tpm2bPublic::deserialize(&bytes[start..])?;
2656 end += out_public.payload_size();
2657
2658 start = end;
2659 let name = Tpm2bBuffer::deserialize(&bytes[start..])?;
2660 end += name.payload_size();
2661
2662 start = end;
2663 let qualified_name = Tpm2bBuffer::deserialize(&bytes[start..])?;
2664 end += qualified_name.payload_size();
2665
2666 if header.size.get() as usize != end {
2667 return None;
2668 }
2669
2670 Some(Self {
2671 header,
2672 out_public,
2673 name,
2674 qualified_name,
2675 })
2676 }
2677
2678 fn payload_size(&self) -> usize {
2679 let mut payload_size = 0;
2680
2681 payload_size += size_of::<ReplyHeader>();
2682 payload_size += self.out_public.payload_size();
2683 payload_size += self.name.payload_size();
2684 payload_size += self.qualified_name.payload_size();
2685
2686 payload_size
2687 }
2688 }
2689
2690 #[repr(C)]
2693 #[derive(FromBytes, IntoBytes, Immutable, KnownLayout)]
2694 pub struct NvDefineSpaceCmd {
2695 header: CmdHeader,
2696 auth_handle: ReservedHandle,
2697 auth_size: u32_be,
2699 auth_cmd: common::CmdAuth,
2700 auth: Tpm2bBuffer,
2702 public_info: Tpm2bNvPublic,
2703 }
2704
2705 impl NvDefineSpaceCmd {
2706 pub fn new(
2707 session: SessionTag,
2708 auth_handle: ReservedHandle,
2709 auth_cmd: common::CmdAuth,
2710 auth: u64,
2711 public_info: TpmsNvPublic,
2712 ) -> Result<Self, TpmProtoError> {
2713 let auth = new_u64_be(auth);
2714 let auth =
2715 Tpm2bBuffer::new(auth.as_bytes()).map_err(TpmProtoError::NvDefineSpaceAuth)?;
2716 let public_info =
2717 Tpm2bNvPublic::new(public_info).map_err(TpmProtoError::NvDefineSpacePublicInfo)?;
2718
2719 let mut cmd = Self {
2720 header: CmdHeader::new::<Self>(session, CommandCodeEnum::NV_DefineSpace.into()),
2721 auth_handle,
2722 auth_size: (size_of::<common::CmdAuth>() as u32).into(),
2723 auth_cmd,
2724 auth,
2725 public_info,
2726 };
2727
2728 cmd.header.size = new_u32_be(cmd.payload_size() as u32);
2729
2730 Ok(cmd)
2731 }
2732
2733 pub fn serialize(&self) -> Vec<u8> {
2734 let mut buffer = Vec::new();
2735
2736 buffer.extend_from_slice(self.header.as_bytes());
2737 buffer.extend_from_slice(self.auth_handle.as_bytes());
2738 buffer.extend_from_slice(self.auth_size.as_bytes());
2739 buffer.extend_from_slice(self.auth_cmd.as_bytes());
2740 buffer.extend_from_slice(&self.auth.serialize());
2741 buffer.extend_from_slice(&self.public_info.serialize());
2742
2743 buffer
2744 }
2745
2746 pub fn payload_size(&self) -> usize {
2747 let mut payload_size = 0;
2748
2749 payload_size += size_of_val(&self.header);
2750 payload_size += size_of_val(&self.auth_handle);
2751 payload_size += size_of_val(&self.auth_size);
2752 payload_size += size_of_val(&self.auth_cmd);
2753 payload_size += self.auth.payload_size();
2754 payload_size += self.public_info.payload_size();
2755
2756 payload_size
2757 }
2758 }
2759
2760 #[repr(C)]
2761 #[derive(Debug, FromBytes, IntoBytes, Immutable, KnownLayout)]
2762 pub struct NvDefineSpaceReply {
2763 pub header: ReplyHeader,
2764 }
2765
2766 impl TpmCommand for NvDefineSpaceCmd {
2767 type Reply = NvDefineSpaceReply;
2768 }
2769
2770 impl TpmReply for NvDefineSpaceReply {
2771 type Command = NvDefineSpaceCmd;
2772
2773 fn deserialize(bytes: &[u8]) -> Option<Self> {
2774 Some(Self::read_from_prefix(bytes).ok()?.0) }
2776
2777 fn payload_size(&self) -> usize {
2778 size_of::<Self>()
2779 }
2780 }
2781
2782 #[repr(C)]
2785 #[derive(FromBytes, IntoBytes, Immutable, KnownLayout)]
2786 pub struct NvUndefineSpaceCmd {
2787 header: CmdHeader,
2788 auth_handle: ReservedHandle,
2789 nv_index: u32_be,
2790 auth_size: u32_be,
2792 auth: common::CmdAuth,
2793 }
2794
2795 impl NvUndefineSpaceCmd {
2796 pub fn new(
2797 session: SessionTag,
2798 auth_handle: ReservedHandle,
2799 auth: common::CmdAuth,
2800 nv_index: u32,
2801 ) -> Self {
2802 Self {
2803 header: CmdHeader::new::<Self>(session, CommandCodeEnum::NV_UndefineSpace.into()),
2804 auth_handle,
2805 nv_index: nv_index.into(),
2806 auth_size: (size_of::<common::CmdAuth>() as u32).into(),
2807 auth,
2808 }
2809 }
2810 }
2811
2812 #[repr(C)]
2813 #[derive(Debug, FromBytes, IntoBytes, Immutable, KnownLayout)]
2814 pub struct NvUndefineSpaceReply {
2815 pub header: ReplyHeader,
2816 }
2817
2818 impl TpmCommand for NvUndefineSpaceCmd {
2819 type Reply = NvUndefineSpaceReply;
2820 }
2821
2822 impl TpmReply for NvUndefineSpaceReply {
2823 type Command = NvUndefineSpaceCmd;
2824
2825 fn deserialize(bytes: &[u8]) -> Option<Self> {
2826 Some(Self::read_from_prefix(bytes).ok()?.0) }
2828
2829 fn payload_size(&self) -> usize {
2830 size_of::<Self>()
2831 }
2832 }
2833
2834 #[repr(C)]
2837 #[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
2838 pub struct NvReadPublicCmd {
2839 header: CmdHeader,
2840 nv_index: u32_be,
2841 }
2842
2843 impl NvReadPublicCmd {
2844 pub fn new(session: SessionTag, nv_index: u32) -> Self {
2845 Self {
2846 header: CmdHeader::new::<Self>(session, CommandCodeEnum::NV_ReadPublic.into()),
2847 nv_index: nv_index.into(),
2848 }
2849 }
2850 }
2851
2852 #[repr(C)]
2853 #[derive(Debug, FromBytes, IntoBytes, Immutable, KnownLayout)]
2854 pub struct NvReadPublicReply {
2855 pub header: ReplyHeader,
2856 pub nv_public: Tpm2bNvPublic,
2858 nv_name: Tpm2bBuffer,
2859 }
2860
2861 impl TpmCommand for NvReadPublicCmd {
2862 type Reply = NvReadPublicReply;
2863 }
2864
2865 impl TpmReply for NvReadPublicReply {
2866 type Command = NvReadPublicCmd;
2867
2868 fn deserialize(bytes: &[u8]) -> Option<Self> {
2869 let mut start = 0;
2870 let mut end = size_of::<ReplyHeader>();
2871
2872 let header = ReplyHeader::read_from_prefix(&bytes[start..end]).ok()?.0; if header.size.get() as usize == end {
2876 return Some(Self {
2877 header,
2878 nv_public: Tpm2bNvPublic::new_zeroed(),
2879 nv_name: Tpm2bBuffer::new_zeroed(),
2880 });
2881 }
2882
2883 start = end;
2884 let nv_public = Tpm2bNvPublic::deserialize(&bytes[start..])?;
2885 end += nv_public.payload_size();
2886
2887 start = end;
2888 let nv_name = Tpm2bBuffer::deserialize(&bytes[start..])?;
2889 end += nv_name.payload_size();
2890
2891 if header.size.get() as usize != end {
2892 return None;
2893 }
2894
2895 Some(Self {
2896 header,
2897 nv_public,
2898 nv_name,
2899 })
2900 }
2901
2902 fn payload_size(&self) -> usize {
2903 let mut size = 0;
2904
2905 size += size_of::<ReplyHeader>();
2906 size += self.nv_public.payload_size();
2907 size += self.nv_name.payload_size();
2908
2909 size
2910 }
2911 }
2912
2913 #[repr(C)]
2916 #[derive(FromBytes, IntoBytes, Immutable, KnownLayout)]
2917 pub struct NvWriteCmd {
2918 header: CmdHeader,
2919 auth_handle: ReservedHandle,
2920 pub nv_index: u32_be,
2921 auth_size: u32_be,
2923 auth: common::CmdAuth,
2924 auth_value: u64_be,
2925 pub data: Tpm2bBuffer,
2927 pub offset: u16_be,
2928 }
2929
2930 impl NvWriteCmd {
2931 pub fn new(
2932 session: SessionTag,
2933 auth_handle: ReservedHandle,
2934 auth: common::CmdAuth,
2935 auth_value: u64,
2936 nv_index: u32,
2937 data: &[u8],
2938 offset: u16,
2939 ) -> Result<Self, TpmProtoError> {
2940 let data = Tpm2bBuffer::new(data).map_err(TpmProtoError::NvWriteData)?;
2941 let auth_value_size = if auth_handle != TPM20_RH_OWNER {
2943 size_of::<u64_be>() as u32
2944 } else {
2945 0
2946 };
2947
2948 let mut cmd = Self {
2949 header: CmdHeader::new::<Self>(session, CommandCodeEnum::NV_Write.into()),
2950 auth_handle,
2951 nv_index: nv_index.into(),
2952 auth_size: (size_of::<common::CmdAuth>() as u32 + auth_value_size).into(),
2953 auth,
2954 auth_value: auth_value.into(),
2955 data,
2956 offset: offset.into(),
2957 };
2958
2959 cmd.header.size = new_u32_be(cmd.payload_size() as u32);
2960
2961 Ok(cmd)
2962 }
2963
2964 pub fn update_write_data(&mut self, data: &[u8], offset: u16) -> Result<(), TpmProtoError> {
2965 let data = Tpm2bBuffer::new(data).map_err(TpmProtoError::NvWriteData)?;
2966
2967 self.data = data;
2968 self.offset = offset.into();
2969 self.header.size = new_u32_be(self.payload_size() as u32);
2970
2971 Ok(())
2972 }
2973
2974 pub fn serialize(&self) -> Vec<u8> {
2975 let mut buffer = Vec::new();
2976
2977 buffer.extend_from_slice(self.header.as_bytes());
2978 buffer.extend_from_slice(self.auth_handle.as_bytes());
2979 buffer.extend_from_slice(self.nv_index.as_bytes());
2980 buffer.extend_from_slice(self.auth_size.as_bytes());
2981 buffer.extend_from_slice(self.auth.as_bytes());
2982 if self.auth_handle != TPM20_RH_OWNER {
2983 buffer.extend_from_slice(self.auth_value.as_bytes());
2984 }
2985 buffer.extend_from_slice(&self.data.serialize());
2986 buffer.extend_from_slice(self.offset.as_bytes());
2987
2988 buffer
2989 }
2990
2991 pub fn payload_size(&self) -> usize {
2992 let mut payload_size = 0;
2993
2994 payload_size += size_of_val(&self.header);
2995 payload_size += size_of_val(&self.auth_handle);
2996 payload_size += size_of_val(&self.nv_index);
2997 payload_size += size_of_val(&self.auth_size);
2998 payload_size += size_of_val(&self.auth);
2999 if self.auth_handle != TPM20_RH_OWNER {
3000 payload_size += size_of_val(&self.auth_value);
3001 }
3002 payload_size += self.data.payload_size();
3003 payload_size += size_of_val(&self.offset);
3004
3005 payload_size
3006 }
3007 }
3008
3009 #[repr(C)]
3010 #[derive(Debug, FromBytes, IntoBytes, Immutable, KnownLayout)]
3011 pub struct NvWriteReply {
3012 pub header: ReplyHeader,
3013 }
3014
3015 impl TpmCommand for NvWriteCmd {
3016 type Reply = NvWriteReply;
3017 }
3018
3019 impl TpmReply for NvWriteReply {
3020 type Command = NvWriteCmd;
3021
3022 fn deserialize(bytes: &[u8]) -> Option<Self> {
3023 Some(Self::read_from_prefix(bytes).ok()?.0) }
3025
3026 fn payload_size(&self) -> usize {
3027 size_of::<Self>()
3028 }
3029 }
3030
3031 #[repr(C)]
3034 #[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
3035 pub struct NvReadCmd {
3036 header: CmdHeader,
3037 auth_handle: ReservedHandle,
3038 pub nv_index: u32_be,
3039 auth_size: u32_be,
3041 auth: common::CmdAuth,
3042 size: u16_be,
3044 pub offset: u16_be,
3045 }
3046
3047 impl NvReadCmd {
3048 pub fn new(
3049 session: SessionTag,
3050 auth_handle: ReservedHandle,
3051 nv_index: u32,
3052 auth: common::CmdAuth,
3053 size: u16,
3054 offset: u16,
3055 ) -> Self {
3056 Self {
3057 header: CmdHeader::new::<Self>(session, CommandCodeEnum::NV_Read.into()),
3058 auth_handle,
3059 nv_index: nv_index.into(),
3060 auth_size: (size_of::<common::CmdAuth>() as u32).into(),
3061 auth,
3062 size: size.into(),
3063 offset: offset.into(),
3064 }
3065 }
3066
3067 pub fn update_read_parameters(&mut self, size: u16, offset: u16) {
3068 self.size = size.into();
3069 self.offset = offset.into();
3070 }
3071
3072 pub fn deserialize(bytes: &[u8]) -> Option<Self> {
3073 let mut start = 0;
3074 let mut end = size_of::<CmdHeader>();
3075 if bytes.len() < end {
3076 return None;
3077 }
3078 let header = CmdHeader::read_from_prefix(&bytes[start..end]).ok()?.0; if header.command_code != CommandCodeEnum::NV_Read.into() {
3081 return None;
3082 }
3083
3084 start = end;
3085 end += size_of::<ReservedHandle>();
3086 if bytes.len() < end {
3087 return None;
3088 }
3089 let auth_handle = ReservedHandle::read_from_prefix(&bytes[start..end]).ok()?.0; start = end;
3092 end += size_of::<u32_be>();
3093 if bytes.len() < end {
3094 return None;
3095 }
3096 let nv_index = u32_be::read_from_prefix(&bytes[start..end]).ok()?.0; start = end;
3099 end += size_of::<u32_be>();
3100 if bytes.len() < end {
3101 return None;
3102 }
3103 let auth_size = u32_be::read_from_prefix(&bytes[start..end]).ok()?.0; end += auth_size.get() as usize;
3107
3108 start = end;
3109 end += size_of::<u16_be>();
3110 if bytes.len() < end {
3111 return None;
3112 }
3113 let size = u16_be::read_from_prefix(&bytes[start..end]).ok()?.0; start = end;
3116 end += size_of::<u16_be>();
3117 if bytes.len() < end {
3118 return None;
3119 }
3120 let offset = u16_be::read_from_prefix(&bytes[start..end]).ok()?.0; Some(Self {
3123 header,
3124 auth_handle,
3125 nv_index,
3126 auth_size,
3127 auth: common::CmdAuth::new(ReservedHandle(0.into()), 0, 0, 0),
3128 size,
3129 offset,
3130 })
3131 }
3132 }
3133
3134 #[repr(C)]
3135 #[derive(Debug, FromBytes, IntoBytes, Immutable, KnownLayout)]
3136 pub struct NvReadReply {
3137 pub header: ReplyHeader,
3138 pub parameter_size: u32_be,
3139 pub data: Tpm2bBuffer,
3141 pub auth: common::ReplyAuth,
3143 }
3144
3145 impl TpmCommand for NvReadCmd {
3146 type Reply = NvReadReply;
3147 }
3148
3149 impl TpmReply for NvReadReply {
3150 type Command = NvReadCmd;
3151
3152 fn deserialize(bytes: &[u8]) -> Option<Self> {
3153 let mut start = 0;
3154 let mut end = size_of::<ReplyHeader>();
3155
3156 let header = ReplyHeader::read_from_prefix(&bytes[start..end]).ok()?.0; if header.size.get() as usize == end {
3160 return Some(Self {
3161 header,
3162 parameter_size: 0.into(),
3163 data: Tpm2bBuffer::new_zeroed(),
3164 auth: common::ReplyAuth::new_zeroed(),
3165 });
3166 }
3167
3168 start = end;
3169 end += size_of::<u32_be>();
3170 if bytes.len() < end {
3171 return None;
3172 }
3173 let parameter_size = u32_be::read_from_prefix(&bytes[start..end]).ok()?.0; start = end;
3176 let data = Tpm2bBuffer::deserialize(&bytes[start..])?;
3177 end += data.payload_size();
3178
3179 start = end;
3180 end += size_of::<common::ReplyAuth>();
3181 if bytes.len() < end {
3182 return None;
3183 }
3184 let auth = common::ReplyAuth::read_from_prefix(&bytes[start..end])
3185 .ok()?
3186 .0; if header.size.get() as usize != end {
3189 return None;
3190 }
3191
3192 Some(Self {
3193 header,
3194 parameter_size,
3195 data,
3196 auth,
3197 })
3198 }
3199
3200 fn payload_size(&self) -> usize {
3201 let mut size = 0;
3202
3203 size += size_of::<ReplyHeader>();
3204 size += self.data.payload_size();
3205
3206 size
3207 }
3208 }
3209
3210 #[repr(C)]
3213 #[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
3214 pub struct ImportCmd {
3215 pub header: CmdHeader,
3216 pub auth_handle: ReservedHandle,
3217 pub auth_size: u32_be,
3219 pub auth: common::CmdAuth,
3220 pub encryption_key: Tpm2bBuffer,
3223 pub object_public: Tpm2bPublic,
3225 pub duplicate: Tpm2bBuffer,
3227 pub in_sym_seed: Tpm2bBuffer,
3229 pub symmetric_alg: TpmtSymDefObject,
3231 }
3232
3233 impl ImportCmd {
3234 pub fn new(
3235 session: SessionTag,
3236 auth_handle: ReservedHandle,
3237 auth: common::CmdAuth,
3238 encryption_key: &Tpm2bBuffer,
3239 object_public: &Tpm2bPublic,
3240 duplicate: &Tpm2bBuffer,
3241 in_sym_seed: &Tpm2bBuffer,
3242 symmetric_alg: &TpmtSymDefObject,
3243 ) -> Self {
3244 let mut cmd = Self {
3245 header: CmdHeader::new::<Self>(session, CommandCodeEnum::Import.into()),
3246 auth_handle,
3247 auth_size: (size_of::<common::CmdAuth>() as u32).into(),
3248 auth,
3249 encryption_key: *encryption_key,
3250 object_public: *object_public,
3251 duplicate: *duplicate,
3252 in_sym_seed: *in_sym_seed,
3253 symmetric_alg: *symmetric_alg,
3254 };
3255
3256 cmd.header.size = new_u32_be(cmd.payload_size() as u32);
3257
3258 cmd
3259 }
3260
3261 pub fn deserialize_no_wrapping_key(bytes: &[u8]) -> Option<Self> {
3263 let mut start = 0;
3264 let mut end = 0;
3265
3266 let encryption_key = Tpm2bBuffer::new_zeroed();
3270 let symmetric_alg = TpmtSymDefObject::new(AlgIdEnum::NULL.into(), None, None);
3271
3272 let object_public = Tpm2bPublic::deserialize(&bytes[start..])?;
3273 end += object_public.payload_size();
3274
3275 start = end;
3276 let duplicate = Tpm2bBuffer::deserialize(&bytes[start..])?;
3277 end += duplicate.payload_size();
3278
3279 start = end;
3280 let in_sym_seed = Tpm2bBuffer::deserialize(&bytes[start..])?;
3281 end += in_sym_seed.payload_size();
3282
3283 if bytes.len() < end {
3285 return None;
3286 }
3287
3288 Some(Self {
3289 header: CmdHeader::new_zeroed(),
3290 auth_handle: ReservedHandle(0.into()),
3291 auth_size: 0.into(),
3292 auth: common::CmdAuth::new_zeroed(),
3293 encryption_key,
3294 object_public,
3295 duplicate,
3296 in_sym_seed,
3297 symmetric_alg,
3298 })
3299 }
3300
3301 pub fn serialize(&self) -> Vec<u8> {
3302 let mut buffer = Vec::new();
3303
3304 buffer.extend_from_slice(self.header.as_bytes());
3305 buffer.extend_from_slice(self.auth_handle.as_bytes());
3306 buffer.extend_from_slice(self.auth_size.as_bytes());
3307 buffer.extend_from_slice(self.auth.as_bytes());
3308 buffer.extend_from_slice(&self.encryption_key.serialize());
3309 buffer.extend_from_slice(&self.object_public.serialize());
3310 buffer.extend_from_slice(&self.duplicate.serialize());
3311 buffer.extend_from_slice(&self.in_sym_seed.serialize());
3312 buffer.extend_from_slice(&self.symmetric_alg.serialize());
3313
3314 buffer
3315 }
3316
3317 pub fn payload_size(&self) -> usize {
3318 let mut payload_size = 0;
3319
3320 payload_size += size_of_val(&self.header);
3321 payload_size += size_of_val(&self.auth_handle);
3322 payload_size += size_of_val(&self.auth_size);
3323 payload_size += size_of_val(&self.auth);
3324 payload_size += self.encryption_key.payload_size();
3325 payload_size += self.object_public.payload_size();
3326 payload_size += self.duplicate.payload_size();
3327 payload_size += self.in_sym_seed.payload_size();
3328 payload_size += self.symmetric_alg.payload_size();
3329
3330 payload_size
3331 }
3332 }
3333
3334 #[repr(C)]
3335 #[derive(Debug, FromBytes, IntoBytes, Immutable, KnownLayout)]
3336 pub struct ImportReply {
3337 pub header: ReplyHeader,
3338 pub parameter_size: u32_be,
3339 pub out_private: Tpm2bBuffer,
3342 pub auth: common::ReplyAuth,
3344 }
3345
3346 impl TpmCommand for ImportCmd {
3347 type Reply = ImportReply;
3348 }
3349
3350 impl TpmReply for ImportReply {
3351 type Command = ImportCmd;
3352
3353 fn deserialize(bytes: &[u8]) -> Option<Self> {
3354 let mut start = 0;
3355 let mut end = size_of::<ReplyHeader>();
3356
3357 let header = ReplyHeader::read_from_prefix(&bytes[start..end]).ok()?.0; if header.size.get() as usize == end {
3361 return Some(Self {
3362 header,
3363 parameter_size: 0.into(),
3364 out_private: Tpm2bBuffer::new_zeroed(),
3365 auth: common::ReplyAuth::new_zeroed(),
3366 });
3367 }
3368
3369 start = end;
3370 end += size_of::<u32_be>();
3371 if bytes.len() < end {
3372 return None;
3373 }
3374 let parameter_size = u32_be::read_from_prefix(&bytes[start..end]).ok()?.0; let expected_auth_start = end + parameter_size.get() as usize;
3376
3377 start = end;
3378 let out_private = Tpm2bBuffer::deserialize(&bytes[start..])?;
3379 end += out_private.payload_size();
3380
3381 start = end;
3382 if start != expected_auth_start {
3383 return None;
3384 }
3385 end += size_of::<common::ReplyAuth>();
3386 if bytes.len() < end {
3387 return None;
3388 }
3389 let auth = common::ReplyAuth::read_from_prefix(&bytes[start..end])
3390 .ok()?
3391 .0; if header.size.get() as usize != end {
3394 return None;
3395 }
3396
3397 Some(Self {
3398 header,
3399 parameter_size,
3400 out_private,
3401 auth,
3402 })
3403 }
3404
3405 fn payload_size(&self) -> usize {
3406 let mut size = 0;
3407
3408 size += size_of::<ReplyHeader>();
3409 size += self.out_private.payload_size();
3410
3411 size
3412 }
3413 }
3414
3415 #[repr(C)]
3418 #[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
3419 pub struct LoadCmd {
3420 header: CmdHeader,
3421 auth_handle: ReservedHandle,
3422 auth_size: u32_be,
3424 auth: common::CmdAuth,
3425 in_private: Tpm2bBuffer,
3428 in_public: Tpm2bPublic,
3430 }
3431
3432 impl LoadCmd {
3433 pub fn new(
3434 session: SessionTag,
3435 auth_handle: ReservedHandle,
3436 auth: common::CmdAuth,
3437 in_private: &Tpm2bBuffer,
3438 in_public: &Tpm2bPublic,
3439 ) -> Self {
3440 let mut cmd = Self {
3441 header: CmdHeader::new::<Self>(session, CommandCodeEnum::Load.into()),
3442 auth_handle,
3443 auth_size: (size_of::<common::CmdAuth>() as u32).into(),
3444 auth,
3445 in_private: *in_private,
3446 in_public: *in_public,
3447 };
3448
3449 cmd.header.size = new_u32_be(cmd.payload_size() as u32);
3450
3451 cmd
3452 }
3453
3454 pub fn serialize(&self) -> Vec<u8> {
3455 let mut buffer = Vec::new();
3456
3457 buffer.extend_from_slice(self.header.as_bytes());
3458 buffer.extend_from_slice(self.auth_handle.as_bytes());
3459 buffer.extend_from_slice(self.auth_size.as_bytes());
3460 buffer.extend_from_slice(self.auth.as_bytes());
3461 buffer.extend_from_slice(&self.in_private.serialize());
3462 buffer.extend_from_slice(&self.in_public.serialize());
3463
3464 buffer
3465 }
3466
3467 pub fn payload_size(&self) -> usize {
3468 let mut payload_size = 0;
3469
3470 payload_size += size_of_val(&self.header);
3471 payload_size += size_of_val(&self.auth_handle);
3472 payload_size += size_of_val(&self.auth_size);
3473 payload_size += size_of_val(&self.auth);
3474 payload_size += self.in_private.payload_size();
3475 payload_size += self.in_public.payload_size();
3476
3477 payload_size
3478 }
3479 }
3480
3481 #[repr(C)]
3482 #[derive(Debug, FromBytes, IntoBytes, Immutable, KnownLayout)]
3483 pub struct LoadReply {
3484 pub header: ReplyHeader,
3485 pub object_handle: ReservedHandle,
3486 pub parameter_size: u32_be,
3487 pub name: Tpm2bBuffer,
3490 pub auth: common::ReplyAuth,
3492 }
3493
3494 impl TpmCommand for LoadCmd {
3495 type Reply = LoadReply;
3496 }
3497
3498 impl TpmReply for LoadReply {
3499 type Command = LoadCmd;
3500
3501 fn deserialize(bytes: &[u8]) -> Option<Self> {
3502 let mut start = 0;
3503 let mut end = size_of::<ReplyHeader>();
3504
3505 let header = ReplyHeader::read_from_prefix(&bytes[start..end]).ok()?.0; if header.size.get() as usize == end {
3509 return Some(Self {
3510 header,
3511 object_handle: ReservedHandle::new_zeroed(),
3512 parameter_size: 0.into(),
3513 name: Tpm2bBuffer::new_zeroed(),
3514 auth: common::ReplyAuth::new_zeroed(),
3515 });
3516 }
3517
3518 start = end;
3519 end += size_of::<ReservedHandle>();
3520 if bytes.len() < end {
3521 return None;
3522 }
3523 let object_handle = ReservedHandle::read_from_prefix(&bytes[start..end]).ok()?.0; start = end;
3526 end += size_of::<u32_be>();
3527 if bytes.len() < end {
3528 return None;
3529 }
3530 let parameter_size = u32_be::read_from_prefix(&bytes[start..end]).ok()?.0; let expected_auth_start = end + parameter_size.get() as usize;
3532
3533 start = end;
3534 let name = Tpm2bBuffer::deserialize(&bytes[start..])?;
3535 end += name.payload_size();
3536
3537 start = end;
3538 if start != expected_auth_start {
3539 return None;
3540 }
3541 end += size_of::<common::ReplyAuth>();
3542 if bytes.len() < end {
3543 return None;
3544 }
3545 let auth = common::ReplyAuth::read_from_prefix(&bytes[start..end])
3546 .ok()?
3547 .0; if header.size.get() as usize != end {
3550 return None;
3551 }
3552
3553 Some(Self {
3554 header,
3555 object_handle,
3556 parameter_size,
3557 name,
3558 auth,
3559 })
3560 }
3561
3562 fn payload_size(&self) -> usize {
3563 let mut size = 0;
3564
3565 size += size_of::<ReplyHeader>();
3566 size += size_of::<ReservedHandle>();
3567 size += self.name.payload_size();
3568
3569 size
3570 }
3571 }
3572}
3573
3574#[cfg(test)]
3575mod tests {
3576 use super::protocol::common::*;
3577 use super::protocol::*;
3578 use super::*;
3579
3580 #[test]
3581 fn test_create_primary() {
3582 const AK_PUB_EXPECTED_CMD: [u8; 321] = [
3583 0x80, 0x02, 0x00, 0x00, 0x01, 0x41, 0x00, 0x00, 0x01, 0x31, 0x40, 0x00, 0x00, 0x0b,
3584 0x00, 0x00, 0x00, 0x09, 0x40, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3585 0x04, 0x00, 0x00, 0x00, 0x00, 0x01, 0x18, 0x00, 0x01, 0x00, 0x0b, 0x00, 0x05, 0x04,
3586 0x72, 0x00, 0x00, 0x00, 0x10, 0x00, 0x14, 0x00, 0x0b, 0x08, 0x00, 0x00, 0x00, 0x00,
3587 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3588 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3589 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3590 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3591 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3592 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3593 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3594 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3595 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3596 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3597 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3598 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3599 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3600 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3601 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3602 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3603 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3604 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3605 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3606 ];
3607
3608 const AK_PUB_REPLY_SUCCEED: [u8; 488] = [
3609 0x80, 0x02, 0x00, 0x00, 0x01, 0xe8, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
3610 0x00, 0x00, 0x01, 0xd1, 0x01, 0x18, 0x00, 0x01, 0x00, 0x0b, 0x00, 0x05, 0x04, 0x72,
3611 0x00, 0x00, 0x00, 0x10, 0x00, 0x14, 0x00, 0x0b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
3612 0x01, 0x00, 0xc8, 0x38, 0xd1, 0x52, 0x00, 0x00, 0xe9, 0x3c, 0x89, 0x4c, 0x52, 0xfb,
3613 0x79, 0x7b, 0xc4, 0x14, 0x28, 0x5f, 0xaa, 0x50, 0x78, 0x9a, 0x31, 0x2b, 0x4d, 0xfe,
3614 0xad, 0xad, 0x97, 0x28, 0x49, 0xb2, 0x39, 0x77, 0x5e, 0x06, 0x49, 0xb7, 0x93, 0xf5,
3615 0x2f, 0x84, 0x85, 0x2e, 0x17, 0x87, 0x52, 0x96, 0x36, 0x74, 0x76, 0x21, 0x5f, 0xc2,
3616 0x90, 0x81, 0xf7, 0xe9, 0xd8, 0xac, 0x07, 0x60, 0xaf, 0x83, 0xa2, 0x08, 0xda, 0x94,
3617 0x77, 0x2c, 0x73, 0x9c, 0xd4, 0x80, 0x47, 0x43, 0xa6, 0x4e, 0x36, 0xc3, 0x7e, 0xe2,
3618 0x9c, 0xfb, 0xf1, 0x7e, 0x36, 0x8e, 0x7a, 0x86, 0xde, 0x3d, 0x4e, 0x8a, 0x3a, 0xce,
3619 0x7a, 0xa1, 0x58, 0xf6, 0xdb, 0x49, 0x3e, 0xc2, 0x2e, 0xcb, 0x4a, 0xbc, 0x19, 0x81,
3620 0xd5, 0x5d, 0x4f, 0x57, 0x39, 0xf5, 0x9e, 0x02, 0x56, 0x91, 0x37, 0xc2, 0x87, 0x96,
3621 0x26, 0xd8, 0x4a, 0x45, 0x16, 0x01, 0xe0, 0x2e, 0x20, 0x95, 0x75, 0xb8, 0x20, 0x6d,
3622 0x83, 0x54, 0x65, 0x3d, 0x66, 0xf4, 0x8a, 0x43, 0x84, 0x9f, 0xa6, 0xc5, 0x2c, 0x08,
3623 0xe7, 0x59, 0x8e, 0x1f, 0x6d, 0xea, 0x32, 0x5b, 0x36, 0x8e, 0xd1, 0xf3, 0x09, 0x60,
3624 0x86, 0xdb, 0x55, 0xc9, 0xf0, 0xf9, 0x79, 0x87, 0x71, 0x1c, 0x7c, 0x98, 0xa4, 0xc8,
3625 0x91, 0x77, 0xa7, 0x95, 0x82, 0x19, 0xcc, 0x9d, 0xde, 0x4d, 0x7b, 0xf7, 0xc1, 0x31,
3626 0x5b, 0xae, 0x45, 0x6e, 0x6b, 0xf1, 0xaf, 0x89, 0x07, 0x91, 0x80, 0x9d, 0xe5, 0x49,
3627 0xfc, 0x5e, 0xb2, 0x15, 0x67, 0xcf, 0x05, 0xbb, 0xb3, 0x98, 0x54, 0x34, 0x45, 0x2c,
3628 0xc3, 0x3d, 0x09, 0x8e, 0x8d, 0x60, 0xba, 0x67, 0xd9, 0xbe, 0x1c, 0x2a, 0x2c, 0x2a,
3629 0xfa, 0xed, 0x26, 0x81, 0x96, 0x48, 0x17, 0xb3, 0xa6, 0x90, 0x9a, 0x78, 0xa5, 0xac,
3630 0x80, 0xb2, 0xbe, 0xff, 0x3d, 0x35, 0x00, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20,
3631 0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f,
3632 0xb9, 0x24, 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, 0xa4, 0x95, 0x99, 0x1b,
3633 0x78, 0x52, 0xb8, 0x55, 0x01, 0x00, 0x10, 0x00, 0x04, 0x40, 0x00, 0x00, 0x0b, 0x00,
3634 0x04, 0x40, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x20, 0x28, 0xd0, 0x26, 0xfa, 0xfd,
3635 0x74, 0x91, 0x06, 0x74, 0x3e, 0x27, 0xc4, 0x28, 0x05, 0x51, 0x58, 0x5e, 0x5d, 0x17,
3636 0x66, 0x8e, 0xb5, 0x21, 0x83, 0x5e, 0xd6, 0x01, 0x27, 0xef, 0xfc, 0x05, 0xd4, 0x80,
3637 0x21, 0x40, 0x00, 0x00, 0x0b, 0x00, 0x30, 0xfb, 0xfe, 0xd4, 0xe7, 0x9f, 0xc5, 0x2f,
3638 0xfd, 0x7c, 0xe0, 0x4a, 0x97, 0xb5, 0xec, 0x61, 0x59, 0x4d, 0x43, 0x19, 0x29, 0xc0,
3639 0x4f, 0xef, 0xda, 0xdc, 0xe1, 0x48, 0x4d, 0xbd, 0x3d, 0x47, 0x0e, 0xe3, 0x2f, 0xd4,
3640 0xf9, 0x57, 0x4f, 0x77, 0x0f, 0x58, 0x5c, 0x73, 0x58, 0xc2, 0x2d, 0xd7, 0x4a, 0x00,
3641 0x22, 0x00, 0x0b, 0x92, 0x57, 0x64, 0x38, 0x21, 0xf9, 0x68, 0xe9, 0xfc, 0x47, 0xfa,
3642 0xbf, 0x9c, 0x56, 0x49, 0x7a, 0x63, 0xc2, 0xc0, 0x8a, 0x12, 0x80, 0x49, 0x73, 0xc3,
3643 0x8b, 0x00, 0x06, 0x99, 0xe9, 0xfc, 0x22, 0x00, 0x00, 0x01, 0x00, 0x00,
3644 ];
3645
3646 const EK_PUB_EXPECTED_CMD: [u8; 355] = [
3647 0x80, 0x02, 0x00, 0x00, 0x01, 0x63, 0x00, 0x00, 0x01, 0x31, 0x40, 0x00, 0x00, 0x0b,
3648 0x00, 0x00, 0x00, 0x09, 0x40, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3649 0x04, 0x00, 0x00, 0x00, 0x00, 0x01, 0x3a, 0x00, 0x01, 0x00, 0x0b, 0x00, 0x03, 0x00,
3650 0xb2, 0x00, 0x20, 0x83, 0x71, 0x97, 0x67, 0x44, 0x84, 0xb3, 0xf8, 0x1a, 0x90, 0xcc,
3651 0x8d, 0x46, 0xa5, 0xd7, 0x24, 0xfd, 0x52, 0xd7, 0x6e, 0x06, 0x52, 0x0b, 0x64, 0xf2,
3652 0xa1, 0xda, 0x1b, 0x33, 0x14, 0x69, 0xaa, 0x00, 0x06, 0x00, 0x80, 0x00, 0x43, 0x00,
3653 0x10, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3654 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3655 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3656 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3657 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3658 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3659 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3660 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3661 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3662 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3663 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3664 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3665 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3666 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3667 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3668 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3669 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3670 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3671 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3672 0x00, 0x00, 0x00, 0x00, 0x00,
3673 ];
3674
3675 const EK_PUB_REPLY_SUCCEED: [u8; 522] = [
3676 0x80, 0x02, 0x00, 0x00, 0x02, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
3677 0x00, 0x00, 0x01, 0xf3, 0x01, 0x3a, 0x00, 0x01, 0x00, 0x0b, 0x00, 0x03, 0x00, 0xb2,
3678 0x00, 0x20, 0x83, 0x71, 0x97, 0x67, 0x44, 0x84, 0xb3, 0xf8, 0x1a, 0x90, 0xcc, 0x8d,
3679 0x46, 0xa5, 0xd7, 0x24, 0xfd, 0x52, 0xd7, 0x6e, 0x06, 0x52, 0x0b, 0x64, 0xf2, 0xa1,
3680 0xda, 0x1b, 0x33, 0x14, 0x69, 0xaa, 0x00, 0x06, 0x00, 0x80, 0x00, 0x43, 0x00, 0x10,
3681 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x9e, 0x9c, 0x1b, 0x40, 0x00, 0x00,
3682 0xea, 0x2f, 0xd5, 0xd7, 0xde, 0x9b, 0x18, 0x83, 0x55, 0x00, 0x09, 0x53, 0x13, 0xa8,
3683 0x88, 0x10, 0x24, 0x46, 0x44, 0xa8, 0x2d, 0x62, 0xd3, 0x24, 0xe5, 0xf9, 0xcd, 0xca,
3684 0x61, 0xb7, 0xd8, 0x15, 0x98, 0xf8, 0x56, 0x64, 0x14, 0x7b, 0x40, 0x5a, 0x47, 0xbd,
3685 0xd1, 0xc8, 0x7d, 0x1f, 0x93, 0x72, 0x3f, 0x03, 0xe0, 0x29, 0x38, 0x08, 0x03, 0xae,
3686 0x62, 0x13, 0x10, 0xf5, 0x88, 0x5f, 0x86, 0x84, 0x82, 0xfb, 0xda, 0xd8, 0x78, 0xfd,
3687 0x02, 0x9e, 0x88, 0x5c, 0xaf, 0x30, 0xd4, 0x3d, 0x41, 0xb2, 0xb7, 0x7a, 0x36, 0xa5,
3688 0x95, 0x37, 0x08, 0x44, 0x20, 0x10, 0xb3, 0x6c, 0xd0, 0x6d, 0xe9, 0xab, 0xce, 0x35,
3689 0xc0, 0x82, 0x52, 0x06, 0x41, 0x4c, 0xc5, 0x48, 0x5b, 0xe6, 0x22, 0x00, 0x7e, 0x1d,
3690 0x4b, 0x68, 0x80, 0x34, 0xe9, 0xea, 0x6e, 0xf9, 0xf7, 0xf7, 0x84, 0xbe, 0x56, 0xdf,
3691 0xea, 0x85, 0x97, 0x1b, 0x03, 0x5c, 0x5c, 0x9f, 0xf4, 0x72, 0xef, 0xe7, 0xfe, 0x5e,
3692 0x73, 0x2f, 0xf1, 0xdd, 0x40, 0x80, 0x16, 0x8d, 0x1b, 0x95, 0xee, 0xec, 0x21, 0x1c,
3693 0x30, 0x84, 0x25, 0x08, 0x8d, 0x0e, 0xda, 0x5b, 0x00, 0x9c, 0x49, 0x8b, 0xc8, 0xb3,
3694 0x48, 0x9a, 0xc9, 0x19, 0x0f, 0x68, 0xc7, 0x0a, 0x7a, 0x65, 0x35, 0xa0, 0x09, 0x23,
3695 0x88, 0x3f, 0x97, 0x53, 0x4e, 0xbc, 0x08, 0xc0, 0x5b, 0x69, 0x94, 0xcc, 0xd9, 0xb9,
3696 0xea, 0x8c, 0x20, 0x9e, 0x1a, 0xf9, 0x57, 0x08, 0x1a, 0xe0, 0x2d, 0x88, 0x56, 0x1f,
3697 0x9f, 0x50, 0x2e, 0x12, 0xf2, 0x69, 0x9a, 0xdf, 0x30, 0x56, 0xc1, 0xf0, 0x31, 0xef,
3698 0x64, 0xd5, 0x34, 0x02, 0x15, 0xf4, 0xd7, 0x7b, 0x76, 0xd9, 0x99, 0x24, 0x83, 0x99,
3699 0xa5, 0x05, 0xc1, 0xcd, 0xa6, 0xbd, 0xc3, 0x3d, 0x7c, 0x1e, 0x94, 0xdd, 0x00, 0x37,
3700 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14,
3701 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24, 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b,
3702 0x93, 0x4c, 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55, 0x01, 0x00, 0x10, 0x00,
3703 0x04, 0x40, 0x00, 0x00, 0x0b, 0x00, 0x04, 0x40, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
3704 0x20, 0x28, 0xd0, 0x26, 0xfa, 0xfd, 0x74, 0x91, 0x06, 0x74, 0x3e, 0x27, 0xc4, 0x28,
3705 0x05, 0x51, 0x58, 0x5e, 0x5d, 0x17, 0x66, 0x8e, 0xb5, 0x21, 0x83, 0x5e, 0xd6, 0x01,
3706 0x27, 0xef, 0xfc, 0x05, 0xd4, 0x80, 0x21, 0x40, 0x00, 0x00, 0x0b, 0x00, 0x30, 0xe2,
3707 0xf2, 0x64, 0xc3, 0xd7, 0x9e, 0xc1, 0x07, 0xbb, 0x49, 0x74, 0x67, 0xd3, 0xc7, 0xf6,
3708 0xb7, 0x8c, 0xe3, 0x2e, 0x28, 0x36, 0xa6, 0x1f, 0x6f, 0x0b, 0xbd, 0xe3, 0x8e, 0x77,
3709 0xa1, 0x8c, 0x50, 0xe4, 0xaa, 0xa4, 0x01, 0x61, 0xb4, 0x7a, 0x4a, 0x3b, 0x5d, 0xac,
3710 0xe1, 0xd1, 0x65, 0x69, 0x1e, 0x00, 0x22, 0x00, 0x0b, 0xe5, 0x6f, 0x0f, 0xae, 0x8d,
3711 0x0f, 0x91, 0xb9, 0x84, 0x17, 0xc3, 0x86, 0x13, 0xa6, 0x12, 0xbe, 0xec, 0x85, 0xf9,
3712 0x0b, 0xd3, 0xfe, 0x4f, 0x3d, 0x79, 0x7d, 0x6d, 0x3c, 0xc5, 0xcc, 0xb1, 0x5b, 0x00,
3713 0x00, 0x01, 0x00, 0x00,
3714 ];
3715
3716 const REPLY_FAIL: [u8; 10] = [0x80, 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x02, 0xda];
3717
3718 let symmetric = TpmtSymDefObject::new(AlgIdEnum::NULL.into(), None, None);
3720 let scheme = TpmtRsaScheme::new(AlgIdEnum::RSASSA.into(), Some(AlgIdEnum::SHA256.into()));
3721 let rsa_params = TpmsRsaParams::new(symmetric, scheme, 2048, 0);
3722
3723 let object_attributes = TpmaObjectBits::new()
3724 .with_fixed_tpm(true)
3725 .with_fixed_parent(true)
3726 .with_sensitive_data_origin(true)
3727 .with_user_with_auth(true)
3728 .with_no_da(true)
3729 .with_restricted(true)
3730 .with_sign_encrypt(true);
3731
3732 let result = TpmtPublic::new(
3733 AlgIdEnum::RSA.into(),
3734 AlgIdEnum::SHA256.into(),
3735 object_attributes,
3736 &[],
3737 rsa_params,
3738 &[0u8; 256],
3739 );
3740 assert!(result.is_ok());
3741 let in_public = result.unwrap();
3742
3743 let result = CreatePrimaryCmd::new(
3744 SessionTagEnum::Sessions.into(),
3745 TPM20_RH_ENDORSEMENT,
3746 CmdAuth::new(TPM20_RS_PW, 0, 0, 0),
3747 &[],
3748 &[],
3749 in_public,
3750 &[],
3751 &[],
3752 );
3753 assert!(result.is_ok());
3754 let cmd = result.unwrap();
3755
3756 let bytes = cmd.serialize();
3757
3758 assert_eq!(bytes, AK_PUB_EXPECTED_CMD);
3759
3760 let mut reply = [0u8; 4096];
3761 reply[..AK_PUB_REPLY_SUCCEED.len()].copy_from_slice(&AK_PUB_REPLY_SUCCEED);
3762
3763 let response = CreatePrimaryReply::deserialize(&reply);
3764 assert!(response.is_some());
3765 let response = response.unwrap();
3766 assert_eq!(response.header.response_code.get(), 0x0);
3767 assert_eq!(response.object_handle.0.get(), 0x80000000);
3768
3769 reply[..REPLY_FAIL.len()].copy_from_slice(&REPLY_FAIL);
3770
3771 let response = CreatePrimaryReply::deserialize(&reply);
3772 assert!(response.is_some());
3773 let response = response.unwrap();
3774 assert_eq!(response.header.response_code.get(), 0x2da);
3775
3776 const AUTH_POLICY_A_SHA_256: [u8; 32] = [
3778 0x83, 0x71, 0x97, 0x67, 0x44, 0x84, 0xB3, 0xF8, 0x1A, 0x90, 0xCC, 0x8D, 0x46, 0xA5,
3779 0xD7, 0x24, 0xFD, 0x52, 0xD7, 0x6E, 0x06, 0x52, 0x0B, 0x64, 0xF2, 0xA1, 0xDA, 0x1B,
3780 0x33, 0x14, 0x69, 0xAA,
3781 ];
3782 let symmetric = TpmtSymDefObject::new(
3783 AlgIdEnum::AES.into(),
3784 Some(128),
3785 Some(AlgIdEnum::CFB.into()),
3786 );
3787 let scheme = TpmtRsaScheme::new(AlgIdEnum::NULL.into(), None);
3788 let rsa_params = TpmsRsaParams::new(symmetric, scheme, 2048, 0);
3789
3790 let object_attributes = TpmaObjectBits::new()
3791 .with_fixed_tpm(true)
3792 .with_fixed_parent(true)
3793 .with_sensitive_data_origin(true)
3794 .with_admin_with_policy(true)
3795 .with_restricted(true)
3796 .with_decrypt(true);
3797
3798 let result = TpmtPublic::new(
3799 AlgIdEnum::RSA.into(),
3800 AlgIdEnum::SHA256.into(),
3801 object_attributes,
3802 &AUTH_POLICY_A_SHA_256,
3803 rsa_params,
3804 &[0u8; 256],
3805 );
3806 assert!(result.is_ok());
3807 let in_public = result.unwrap();
3808
3809 let result = CreatePrimaryCmd::new(
3810 SessionTagEnum::Sessions.into(),
3811 TPM20_RH_ENDORSEMENT,
3812 CmdAuth::new(TPM20_RS_PW, 0, 0, 0),
3813 &[],
3814 &[],
3815 in_public,
3816 &[],
3817 &[],
3818 );
3819 assert!(result.is_ok());
3820 let cmd = result.unwrap();
3821
3822 let bytes = cmd.serialize();
3823
3824 assert_eq!(bytes, EK_PUB_EXPECTED_CMD);
3825
3826 reply[..EK_PUB_REPLY_SUCCEED.len()].copy_from_slice(&EK_PUB_REPLY_SUCCEED);
3827
3828 let response = CreatePrimaryReply::deserialize(&reply);
3829 assert!(response.is_some());
3830 let response = response.unwrap();
3831 assert_eq!(response.header.response_code.get(), 0x0);
3832 assert_eq!(response.object_handle.0.get(), 0x80000000);
3833 }
3834
3835 #[test]
3836 fn test_read_public() {
3837 const REPLY_SUCCEED: [u8; 364] = [
3838 0x80, 0x01, 0x00, 0x00, 0x01, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x01, 0x18, 0x00, 0x01,
3839 0x00, 0x0b, 0x00, 0x05, 0x04, 0x72, 0x00, 0x00, 0x00, 0x10, 0x00, 0x14, 0x00, 0x0b,
3840 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xa6, 0xaf, 0x71, 0xec, 0x00, 0x00,
3841 0xe0, 0x69, 0xa5, 0xc5, 0xcd, 0x94, 0x59, 0x3b, 0x79, 0xe6, 0xee, 0x14, 0xd3, 0x50,
3842 0xfb, 0x0b, 0xa9, 0x03, 0x51, 0xbf, 0x23, 0xc5, 0x15, 0xdc, 0xbc, 0x4a, 0x3b, 0xaa,
3843 0xef, 0x12, 0x3c, 0x24, 0x47, 0xf2, 0x81, 0xf6, 0x85, 0xf4, 0x8c, 0x16, 0x14, 0x10,
3844 0x3c, 0x3b, 0x2e, 0x7b, 0x04, 0x5e, 0x25, 0x66, 0xcd, 0x8d, 0x86, 0x0b, 0x8c, 0x2b,
3845 0x5f, 0xca, 0x36, 0x1d, 0x5f, 0xff, 0xbf, 0x70, 0x63, 0x79, 0x5b, 0x7f, 0x93, 0x94,
3846 0x6d, 0xbd, 0x6e, 0x4f, 0x22, 0x94, 0x93, 0x87, 0xe1, 0x63, 0x4d, 0xa4, 0x9a, 0x2f,
3847 0xad, 0x90, 0x4c, 0xc9, 0x37, 0x14, 0x59, 0xd3, 0x03, 0x6d, 0x37, 0x98, 0xd4, 0x85,
3848 0x19, 0x9b, 0x93, 0x7e, 0x61, 0x93, 0x6d, 0x1c, 0xe0, 0xe6, 0x72, 0x71, 0x81, 0x45,
3849 0xe0, 0xea, 0x5f, 0xb4, 0x6a, 0x9a, 0x3e, 0x86, 0x60, 0x86, 0xaf, 0xfc, 0x86, 0x0f,
3850 0x0d, 0xe8, 0x81, 0x46, 0x59, 0xad, 0xeb, 0x6f, 0xef, 0x38, 0x5e, 0x53, 0xea, 0x91,
3851 0xcb, 0xa9, 0xf8, 0x31, 0xcd, 0x52, 0x85, 0x55, 0xa8, 0x91, 0x68, 0xd8, 0xdd, 0x20,
3852 0x67, 0x21, 0x30, 0x03, 0xcd, 0x48, 0x3b, 0xb0, 0x33, 0x16, 0xb4, 0xf0, 0x06, 0x55,
3853 0xdf, 0x15, 0xd2, 0x65, 0x55, 0x2f, 0xec, 0xec, 0xc5, 0x74, 0xea, 0xd8, 0x0f, 0x29,
3854 0xac, 0x24, 0x38, 0x32, 0x34, 0x1f, 0xb3, 0x20, 0x28, 0xf6, 0x55, 0xfb, 0x51, 0xf1,
3855 0x22, 0xa3, 0x5e, 0x38, 0xc6, 0xa5, 0xa4, 0xe0, 0xc2, 0xa3, 0x50, 0x27, 0xf6, 0x1d,
3856 0x55, 0x8e, 0x95, 0xe9, 0x95, 0x26, 0x8e, 0x70, 0x35, 0x7b, 0x73, 0xbb, 0x8e, 0xf2,
3857 0xdc, 0x37, 0x30, 0x99, 0x20, 0x2e, 0x1f, 0x09, 0xbd, 0x85, 0x24, 0x44, 0x05, 0x8f,
3858 0x11, 0xc4, 0xb5, 0x71, 0xc1, 0x2e, 0x52, 0xf6, 0x2e, 0x6f, 0x9a, 0x11, 0x00, 0x22,
3859 0x00, 0x0b, 0x61, 0xca, 0x8b, 0xec, 0x0f, 0x9e, 0xc1, 0x38, 0x35, 0xd3, 0x43, 0x58,
3860 0x77, 0xdf, 0x53, 0x82, 0xe7, 0xb2, 0xff, 0x7b, 0xe4, 0x6c, 0xfb, 0x34, 0xa4, 0x28,
3861 0xdd, 0xda, 0xcb, 0xe9, 0x50, 0x50, 0x00, 0x22, 0x00, 0x0b, 0x51, 0xfa, 0x43, 0xbd,
3862 0x35, 0x01, 0xd6, 0x66, 0xa0, 0x4d, 0xc8, 0x03, 0x4f, 0xa1, 0x64, 0xa0, 0x91, 0x63,
3863 0x3c, 0x27, 0xd5, 0x90, 0xa3, 0x7a, 0xae, 0xbc, 0x52, 0xcc, 0x4e, 0x9a, 0xa3, 0x66,
3864 ];
3865
3866 const REPLY_FAIL: [u8; 10] = [0x80, 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x01, 0x8b];
3867
3868 let mut reply = [0u8; 4096];
3869 reply[..REPLY_SUCCEED.len()].copy_from_slice(&REPLY_SUCCEED);
3870
3871 let response: Option<ReadPublicReply> = ReadPublicReply::deserialize(&reply);
3872 assert!(response.is_some());
3873 let response = response.unwrap();
3874 assert_eq!(response.header.response_code.get(), 0x0);
3875
3876 reply[..REPLY_FAIL.len()].copy_from_slice(&REPLY_FAIL);
3877
3878 let response = ReadPublicReply::deserialize(&reply);
3879 assert!(response.is_some());
3880 let response = response.unwrap();
3881 assert_eq!(response.header.response_code.get(), 0x18b);
3882 }
3883
3884 #[test]
3885 fn test_nv_read_public() {
3886 const REPLY_SUCCEED: [u8; 62] = [
3887 0x80, 0x01, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x01, 0x40,
3888 0x00, 0x01, 0x00, 0x0b, 0x42, 0x06, 0x00, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x22,
3889 0x00, 0x0b, 0xc1, 0x0f, 0x8d, 0x61, 0x77, 0xea, 0xd0, 0x29, 0x52, 0xa6, 0x2d, 0x3a,
3890 0x39, 0xc7, 0x22, 0x0b, 0xb9, 0xa1, 0xe1, 0xfe, 0x08, 0x68, 0xa8, 0x6f, 0x5f, 0x10,
3891 0xd6, 0x86, 0x83, 0x28, 0x79, 0x3e,
3892 ];
3893
3894 const REPLY_FAIL: [u8; 10] = [0x80, 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x01, 0x8b];
3895
3896 let mut reply = [0u8; 4096];
3897 reply[..REPLY_SUCCEED.len()].copy_from_slice(&REPLY_SUCCEED);
3898
3899 let response = NvReadPublicReply::deserialize(&reply);
3900 assert!(response.is_some());
3901 let response = response.unwrap();
3902 assert_eq!(response.header.response_code.get(), 0x0);
3903
3904 reply[..REPLY_FAIL.len()].copy_from_slice(&REPLY_FAIL);
3905
3906 let response = NvReadPublicReply::deserialize(&reply);
3907 assert!(response.is_some());
3908 let response = response.unwrap();
3909 assert_eq!(response.header.response_code.get(), 0x18b);
3910 }
3911
3912 #[test]
3913 fn test_define_space() {
3914 const EXPECTED_CMD: [u8; 53] = [
3915 0x80, 0x02, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x01, 0x2a, 0x40, 0x00, 0x00, 0x0c,
3916 0x00, 0x00, 0x00, 0x09, 0x40, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3917 0x08, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0x00, 0x00, 0x0e, 0x01, 0xc1, 0x01,
3918 0xd0, 0x00, 0x0b, 0x42, 0x06, 0x00, 0x04, 0x00, 0x00, 0x10, 0x00,
3919 ];
3920
3921 let auth_value: u64 = 0x7766554433221100;
3922
3923 let attributes = TpmaNvBits::new()
3924 .with_nv_authread(true)
3925 .with_nv_authwrite(true)
3926 .with_nv_ownerread(true)
3927 .with_nv_platformcreate(true)
3928 .with_nv_no_da(true);
3929
3930 let result = TpmsNvPublic::new(0x1c101d0, AlgIdEnum::SHA256.into(), attributes, &[], 4096);
3931 assert!(result.is_ok());
3932 let nv_public = result.unwrap();
3933
3934 let result = NvDefineSpaceCmd::new(
3935 SessionTagEnum::Sessions.into(),
3936 TPM20_RH_PLATFORM,
3937 CmdAuth::new(TPM20_RS_PW, 0, 0, 0),
3938 auth_value,
3939 nv_public,
3940 );
3941 assert!(result.is_ok());
3942 let cmd = result.unwrap();
3943
3944 let bytes = cmd.serialize();
3945 assert_eq!(bytes, EXPECTED_CMD);
3946 }
3947
3948 #[test]
3949 fn test_nv_write_authwrite() {
3950 const EXPECTED_CMD: [u8; 171] = [
3951 0x80, 0x02, 0x00, 0x00, 0x00, 0xab, 0x00, 0x00, 0x01, 0x37, 0x01, 0xc1, 0x01, 0xd0,
3952 0x01, 0xc1, 0x01, 0xd0, 0x00, 0x00, 0x00, 0x11, 0x40, 0x00, 0x00, 0x09, 0x00, 0x00,
3953 0x00, 0x00, 0x08, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0x00, 0x00, 0x80, 0x01,
3954 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
3955 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
3956 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
3957 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
3958 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
3959 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
3960 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
3961 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
3962 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
3963 0x01, 0x00, 0x00,
3964 ];
3965 let auth_value: u64 = 0x7766554433221100;
3966
3967 let result = NvWriteCmd::new(
3968 SessionTagEnum::Sessions.into(),
3969 ReservedHandle(0x1c101d0.into()),
3970 CmdAuth::new(TPM20_RS_PW, 0, 0, size_of_val(&auth_value) as u16),
3971 auth_value,
3972 0x1c101d0,
3973 &[1u8; 128],
3974 0,
3975 );
3976 assert!(result.is_ok());
3977 let cmd = result.unwrap();
3978
3979 let bytes = cmd.serialize();
3980 assert_eq!(bytes, EXPECTED_CMD);
3981 }
3982
3983 #[test]
3984 fn test_nv_write_ownerwrite() {
3985 const EXPECTED_CMD: [u8; 163] = [
3986 0x80, 0x02, 0x00, 0x00, 0x00, 0xa3, 0x00, 0x00, 0x01, 0x37, 0x40, 0x00, 0x00, 0x01,
3987 0x01, 0xc1, 0x01, 0xd0, 0x00, 0x00, 0x00, 0x09, 0x40, 0x00, 0x00, 0x09, 0x00, 0x00,
3988 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
3989 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
3990 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
3991 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
3992 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
3993 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
3994 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
3995 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
3996 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
3997 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00,
3998 ];
3999
4000 let result = NvWriteCmd::new(
4001 SessionTagEnum::Sessions.into(),
4002 TPM20_RH_OWNER,
4003 CmdAuth::new(TPM20_RS_PW, 0, 0, 0),
4004 0,
4005 0x1c101d0,
4006 &[1u8; 128],
4007 0,
4008 );
4009 assert!(result.is_ok());
4010 let cmd = result.unwrap();
4011
4012 let bytes = cmd.serialize();
4013 assert_eq!(bytes, EXPECTED_CMD);
4014 }
4015
4016 #[test]
4017 fn test_nv_read() {
4018 const REPLY_SUCCEED: [u8; 85] = [
4019 0x80, 0x02, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42,
4020 0x00, 0x40, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc,
4021 0xdd, 0xee, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4022 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4023 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4024 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
4025 0x00,
4026 ];
4027
4028 const EXPECTED_DATA: [u8; 64] = [
4029 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee,
4030 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4031 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4032 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4033 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4034 ];
4035
4036 let mut reply = [0u8; 4096];
4037 reply[..REPLY_SUCCEED.len()].copy_from_slice(&REPLY_SUCCEED);
4038
4039 let response = NvReadReply::deserialize(&reply);
4040 assert!(response.is_some());
4041 let response = response.unwrap();
4042 assert_eq!(response.header.response_code.get(), 0x0);
4043 assert_eq!(response.data.buffer[..EXPECTED_DATA.len()], EXPECTED_DATA);
4044 }
4045}