1#[cfg(any(feature = "openssl", feature = "crypto_nossl"))]
4use crate::certs::snp::{Certificate, Chain, Verifiable};
5
6use crate::{
7 certs::snp::ecdsa::Signature,
8 error::AttestationReportError,
9 firmware::host::TcbVersion,
10 parser::{ByteParser, Decoder, Encoder},
11 util::{
12 hexline::HexLine,
13 parser_helper::{ReadExt, WriteExt},
14 },
15 Generation,
16};
17
18#[cfg(feature = "serde")]
19use serde::{Deserialize, Serialize};
20#[cfg(feature = "serde")]
21use serde_big_array::BigArray;
22
23use std::{
24 fmt::Display,
25 io::{Cursor, Read, Write},
26 ops::Range,
27};
28
29#[cfg(any(feature = "openssl", feature = "crypto_nossl"))]
30use std::convert::TryFrom;
31
32#[cfg(feature = "openssl")]
33use std::io::Error;
34
35use bitfield::bitfield;
36
37#[cfg(feature = "openssl")]
38use openssl::{ecdsa::EcdsaSig, sha::Sha384};
39
40const ATT_REP_FW_LEN: usize = 1184;
41const CHIP_ID_RANGE: Range<usize> = 0x1A0..0x1E0;
42const CPUID_FAMILY_ID_BYTES: usize = 0x188;
43const CPUID_MODEL_ID_BYTES: usize = 0x189;
44
45#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
47pub struct DerivedKey {
48 root_key_select: u32,
52
53 _reserved_0: u32,
55
56 pub guest_field_select: GuestFieldSelect,
58
59 pub vmpl: u32,
62
63 pub guest_svn: u32,
66
67 pub tcb_version: u64,
70
71 pub launch_mit_vector: Option<u64>,
74}
75
76impl DerivedKey {
77 pub fn new(
79 root_key_select: bool,
80 guest_field_select: GuestFieldSelect,
81 vmpl: u32,
82 guest_svn: u32,
83 tcb_version: u64,
84 launch_mit_vector: Option<u64>,
85 ) -> Self {
86 Self {
87 root_key_select: u32::from(root_key_select),
88 _reserved_0: Default::default(),
89 guest_field_select,
90 vmpl,
91 guest_svn,
92 tcb_version,
93 launch_mit_vector,
94 }
95 }
96
97 pub fn get_root_key_select(&self) -> u32 {
99 self.root_key_select
100 }
101}
102
103bitfield! {
104 #[repr(C)]
117 #[derive(Default, Copy, Clone,PartialEq, Eq, PartialOrd, Ord)]
118 pub struct GuestFieldSelect(u64);
119 impl Debug;
120 pub get_guest_policy, set_guest_policy: 0;
122 pub get_image_id, set_image_id: 1;
124 pub get_family_id, set_family_id: 2;
126 pub get_measurement, set_measurement: 3;
128 pub get_svn, set_svn: 4;
130 pub get_tcb_version, set_tcb_version: 5;
132 pub get_launch_mit_vector, set_launch_mit_vector: 6;
134}
135
136#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
137#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
138pub struct Version {
140 pub major: u8,
142 pub minor: u8,
144 pub build: u8,
146}
147
148impl Version {
149 pub fn new(major: u8, minor: u8, build: u8) -> Self {
151 Self {
152 major,
153 minor,
154 build,
155 }
156 }
157}
158
159impl std::fmt::Display for Version {
160 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
161 write!(f, "{}.{}.{}", self.major, self.minor, self.build)
162 }
163}
164
165impl Encoder<()> for Version {
166 fn encode(&self, writer: &mut impl Write, _: ()) -> Result<(), std::io::Error> {
167 writer.write_bytes(self.build, ())?;
168 writer.write_bytes(self.minor, ())?;
169 writer.write_bytes(self.major, ())?;
170 Ok(())
171 }
172}
173
174impl Decoder<()> for Version {
175 fn decode(reader: &mut impl Read, _: ()) -> Result<Self, std::io::Error> {
176 let build = reader.read_bytes()?;
177 let minor = reader.read_bytes()?;
178 let major = reader.read_bytes()?;
179 Ok(Self {
180 major,
181 minor,
182 build,
183 })
184 }
185}
186
187impl ByteParser<()> for Version {
188 type Bytes = [u8; 3];
189 const EXPECTED_LEN: Option<usize> = Some(3);
190}
191
192pub enum ReportVariant {
194 V2,
196
197 V3,
199
200 V5,
202}
203
204impl Encoder<()> for ReportVariant {
205 fn encode(&self, writer: &mut impl Write, _: ()) -> Result<(), std::io::Error> {
206 match self {
207 ReportVariant::V2 => writer.write_bytes(2u32, ())?,
208 ReportVariant::V3 => writer.write_bytes(3u32, ())?,
209 ReportVariant::V5 => writer.write_bytes(5u32, ())?,
210 };
211 Ok(())
212 }
213}
214
215impl Decoder<()> for ReportVariant {
216 fn decode(reader: &mut impl Read, _: ()) -> Result<Self, std::io::Error> {
217 let version: u32 = reader.read_bytes()?;
218 Ok(match version {
219 0 | 1 => return Err(std::io::ErrorKind::Unsupported.into()),
220 2 => Self::V2,
221 3 | 4 => Self::V3,
222 5 => Self::V5,
223 _ => Self::V5,
224 })
225 }
226}
227
228impl ByteParser<()> for ReportVariant {
229 type Bytes = [u8; 4];
230 const EXPECTED_LEN: Option<usize> = Some(4);
231}
232
233#[repr(C)]
253#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
254#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
255pub struct AttestationReport {
256 pub version: u32,
258 pub guest_svn: u32,
260 pub policy: GuestPolicy,
262 pub family_id: [u8; 16],
264 pub image_id: [u8; 16],
266 pub vmpl: u32,
268 pub sig_algo: u32,
270 pub current_tcb: TcbVersion,
272 pub plat_info: PlatformInfo,
274 pub key_info: KeyInfo,
276
277 #[cfg_attr(feature = "serde", serde(with = "BigArray"))]
279 pub report_data: [u8; 64],
280
281 #[cfg_attr(feature = "serde", serde(with = "BigArray"))]
283 pub measurement: [u8; 48],
284
285 pub host_data: [u8; 32],
287
288 #[cfg_attr(feature = "serde", serde(with = "BigArray"))]
291 pub id_key_digest: [u8; 48],
292
293 #[cfg_attr(feature = "serde", serde(with = "BigArray"))]
296 pub author_key_digest: [u8; 48],
297 pub report_id: [u8; 32],
299 pub report_id_ma: [u8; 32],
301 pub reported_tcb: TcbVersion,
303 pub cpuid_fam_id: Option<u8>,
305 pub cpuid_mod_id: Option<u8>,
307 pub cpuid_step: Option<u8>,
309
310 #[cfg_attr(feature = "serde", serde(with = "BigArray"))]
313 pub chip_id: [u8; 64],
314 pub committed_tcb: TcbVersion,
316 pub current: Version,
318 pub committed: Version,
320 pub launch_tcb: TcbVersion,
322 pub launch_mit_vector: Option<u64>,
324 pub current_mit_vector: Option<u64>,
326 pub signature: Signature,
329}
330
331impl Default for AttestationReport {
332 fn default() -> Self {
333 Self {
334 version: Default::default(),
335 guest_svn: Default::default(),
336 policy: Default::default(),
337 family_id: Default::default(),
338 image_id: Default::default(),
339 vmpl: Default::default(),
340 sig_algo: Default::default(),
341 current_tcb: Default::default(),
342 plat_info: Default::default(),
343 key_info: Default::default(),
344 report_data: [0u8; 64],
345 measurement: [0u8; 48],
346 host_data: Default::default(),
347 id_key_digest: [0u8; 48],
348 author_key_digest: [0u8; 48],
349 report_id: Default::default(),
350 report_id_ma: Default::default(),
351 reported_tcb: Default::default(),
352 cpuid_fam_id: Default::default(),
353 cpuid_mod_id: Default::default(),
354 cpuid_step: Default::default(),
355 chip_id: [0u8; 64],
356 committed_tcb: Default::default(),
357 current: Default::default(),
358 committed: Default::default(),
359 launch_tcb: Default::default(),
360 launch_mit_vector: Default::default(),
361 current_mit_vector: Default::default(),
362 signature: Default::default(),
363 }
364 }
365}
366
367impl Encoder<()> for AttestationReport {
368 fn encode(&self, writer: &mut impl Write, _: ()) -> Result<(), std::io::Error> {
369 let variant = match self.version {
371 2 => ReportVariant::V2,
372 3 | 4 => ReportVariant::V3,
373 _ => ReportVariant::V5,
374 };
375
376 let generation = match variant {
377 ReportVariant::V2 => {
378 if Self::chip_id_is_turin_like(&self.chip_id)? {
379 Generation::Turin
380 } else {
381 Generation::Genoa
382 }
383 }
384 _ => {
385 let family = self.cpuid_fam_id.unwrap_or(0);
386 let model = self.cpuid_mod_id.unwrap_or(0);
387 Generation::identify_cpu(family, model)?
388 }
389 };
390
391 writer.write_bytes(self.version, ())?;
393 writer.write_bytes(self.guest_svn, ())?;
394 writer.write_bytes(self.policy, ())?;
395 writer.write_bytes(self.family_id, ())?;
396 writer.write_bytes(self.image_id, ())?;
397 writer.write_bytes(self.vmpl, ())?;
398 writer.write_bytes(self.sig_algo, ())?;
399 writer.write_bytes(self.current_tcb, generation)?;
400 writer.write_bytes(self.plat_info, ())?;
401 writer.write_bytes(self.key_info, ())?;
402 writer
403 .skip_bytes::<4>()?
404 .write_bytes(self.report_data, ())?;
405 writer.write_bytes(self.measurement, ())?;
406 writer.write_bytes(self.host_data, ())?;
407 writer.write_bytes(self.id_key_digest, ())?;
408 writer.write_bytes(self.author_key_digest, ())?;
409 writer.write_bytes(self.report_id, ())?;
410 writer.write_bytes(self.report_id_ma, ())?;
411 writer.write_bytes(self.reported_tcb, generation)?;
412
413 match variant {
415 ReportVariant::V2 => {
416 writer.skip_bytes::<24>()?.write_bytes(self.chip_id, ())?;
418 }
419 _ => {
420 writer.write_bytes(self.cpuid_fam_id.unwrap_or(0), ())?;
422 writer.write_bytes(self.cpuid_mod_id.unwrap_or(0), ())?;
423 writer.write_bytes(self.cpuid_step.unwrap_or(0), ())?;
424 writer.skip_bytes::<21>()?.write_bytes(self.chip_id, ())?;
425 }
426 }
427
428 writer.write_bytes(self.committed_tcb, generation)?;
430 writer.write_bytes(self.current, ())?;
431 writer.skip_bytes::<1>()?.write_bytes(self.committed, ())?;
432 writer
433 .skip_bytes::<1>()?
434 .write_bytes(self.launch_tcb, generation)?;
435
436 match variant {
438 ReportVariant::V2 | ReportVariant::V3 => {
439 writer
440 .skip_bytes::<168>()?
441 .write_bytes(self.signature, ())?;
442 }
443 _ => {
444 writer.write_bytes(self.launch_mit_vector.unwrap_or(0), ())?;
445 writer.write_bytes(self.current_mit_vector.unwrap_or(0), ())?;
446 writer
447 .skip_bytes::<152>()?
448 .write_bytes(self.signature, ())?;
449 }
450 }
451
452 Ok(())
453 }
454}
455
456impl Decoder<()> for AttestationReport {
457 fn decode(reader: &mut impl Read, _: ()) -> Result<Self, std::io::Error> {
458 let mut bytes = vec![0u8; ATT_REP_FW_LEN];
459 reader.read_exact(&mut bytes)?;
460
461 let variant = ReportVariant::from_bytes(&bytes[0..4])?;
462
463 let generation = match variant {
464 ReportVariant::V2 => {
465 if Self::chip_id_is_turin_like(&bytes[CHIP_ID_RANGE])? {
466 Generation::Turin
467 } else {
468 Generation::Genoa
469 }
470 }
471 _ => {
472 let family = &bytes[CPUID_FAMILY_ID_BYTES];
473 let model = &bytes[CPUID_MODEL_ID_BYTES];
474 Generation::identify_cpu(*family, *model)?
475 }
476 };
477
478 let mut stepper = Cursor::new(&bytes[..]);
479
480 let version = stepper.read_bytes()?;
481 let guest_svn = stepper.read_bytes()?;
482 let policy = stepper.read_bytes()?;
483 let family_id = stepper.read_bytes()?;
484 let image_id = stepper.read_bytes()?;
485 let vmpl = stepper.read_bytes()?;
486 let sig_algo = stepper.read_bytes()?;
487
488 let current_tcb = stepper.read_bytes_with(generation)?;
489 let plat_info = stepper.read_bytes()?;
490 let key_info = stepper.read_bytes()?;
491 let report_data = stepper.skip_bytes::<4>()?.read_bytes()?;
492 let measurement = stepper.read_bytes()?;
493 let host_data = stepper.read_bytes()?;
494 let id_key_digest = stepper.read_bytes()?;
495 let author_key_digest = stepper.read_bytes()?;
496 let report_id = stepper.read_bytes()?;
497 let report_id_ma = stepper.read_bytes()?;
498 let reported_tcb = stepper.read_bytes_with(generation)?;
499
500 let (cpuid_fam_id, cpuid_mod_id, cpuid_step, chip_id) = match variant {
502 ReportVariant::V2 => (None, None, None, stepper.skip_bytes::<24>()?.read_bytes()?),
503 _ => (
504 Some(stepper.read_bytes()?),
505 Some(stepper.read_bytes()?),
506 Some(stepper.read_bytes()?),
507 stepper.skip_bytes::<21>()?.read_bytes()?,
508 ),
509 };
510
511 let committed_tcb = stepper.read_bytes_with(generation)?;
512 let current = stepper.read_bytes()?;
513 let committed = stepper.skip_bytes::<1>()?.read_bytes()?;
514 let launch_tcb = stepper.skip_bytes::<1>()?.read_bytes_with(generation)?;
515
516 let (launch_mit_vector, current_mit_vector, signature) = match variant {
518 ReportVariant::V2 | ReportVariant::V3 => {
519 (None, None, stepper.skip_bytes::<168>()?.read_bytes()?)
520 }
521 _ => (
522 Some(stepper.read_bytes()?),
523 Some(stepper.read_bytes()?),
524 stepper.skip_bytes::<152>()?.read_bytes()?,
525 ),
526 };
527
528 Ok(Self {
529 version,
530 guest_svn,
531 policy,
532 family_id,
533 image_id,
534 vmpl,
535 sig_algo,
536 current_tcb,
537 plat_info,
538 key_info,
539 report_data,
540 measurement,
541 host_data,
542 id_key_digest,
543 author_key_digest,
544 report_id,
545 report_id_ma,
546 reported_tcb,
547 cpuid_fam_id,
548 cpuid_mod_id,
549 cpuid_step,
550 chip_id,
551 committed_tcb,
552 current,
553 committed,
554 launch_tcb,
555 launch_mit_vector,
556 current_mit_vector,
557 signature,
558 })
559 }
560}
561
562impl ByteParser<()> for AttestationReport {
563 type Bytes = [u8; ATT_REP_FW_LEN];
564 const EXPECTED_LEN: Option<usize> = Some(ATT_REP_FW_LEN);
565}
566
567impl AttestationReport {
568 #[inline(always)]
569 fn chip_id_is_turin_like(bytes: &[u8]) -> Result<bool, AttestationReportError> {
572 if bytes == [0; 64] {
574 return Err(AttestationReportError::MaskedChipId);
575 }
576
577 Ok(bytes[8..] == [0; 56])
579 }
580}
581
582impl Display for AttestationReport {
583 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
584 write!(
585 f,
586 r#"Attestation Report:
587
588Version: {}
589
590Guest SVN: {}
591
592{}
593
594Family ID:{}
595
596Image ID:{}
597
598VMPL: {}
599
600Signature Algorithm: {}
601
602Current TCB:
603
604{}
605
606{}
607
608{}
609
610Report Data:{}
611
612Measurement:{}
613
614Host Data:{}
615
616ID Key Digest:{}
617
618Author Key Digest:{}
619
620Report ID:{}
621
622Report ID Migration Agent:{}
623
624Reported TCB:
625
626{}
627
628CPUID Family ID: {}
629
630CPUID Model ID: {}
631
632CPUID Stepping: {}
633
634Chip ID:{}
635
636Committed TCB:
637
638{}
639
640Current Version: {}
641
642Committed Version: {}
643
644Launch TCB:
645
646{}
647
648Launch Mitigation Vector: {}
649
650Current Mitigation Vector: {}
651
652{}"#,
653 self.version,
654 self.guest_svn,
655 self.policy,
656 HexLine(&self.family_id),
657 HexLine(&self.image_id),
658 self.vmpl,
659 self.sig_algo,
660 self.current_tcb,
661 self.plat_info,
662 self.key_info,
663 HexLine(&self.report_data),
664 HexLine(&self.measurement),
665 HexLine(&self.host_data),
666 HexLine(&self.id_key_digest),
667 HexLine(&self.author_key_digest),
668 HexLine(&self.report_id),
669 HexLine(&self.report_id_ma),
670 self.reported_tcb,
671 self.cpuid_fam_id
672 .map_or("None".to_string(), |fam| fam.to_string()),
673 self.cpuid_mod_id
674 .map_or("None".to_string(), |model| model.to_string()),
675 self.cpuid_step
676 .map_or("None".to_string(), |step| step.to_string()),
677 HexLine(&self.chip_id),
678 self.committed_tcb,
679 self.current,
680 self.committed,
681 self.launch_tcb,
682 self.launch_mit_vector
683 .map_or("None".to_string(), |lmv| lmv.to_string()),
684 self.current_mit_vector
685 .map_or("None".to_string(), |cmv| cmv.to_string()),
686 self.signature
687 )
688 }
689}
690
691#[cfg(feature = "openssl")]
692impl Verifiable for (&Chain, &AttestationReport) {
693 type Output = ();
694
695 fn verify(self) -> std::io::Result<Self::Output> {
696 let vek = self.0.verify()?;
697
698 let sig = EcdsaSig::try_from(&self.1.signature)?;
699
700 let raw_report_bytes = self.1.to_bytes()?;
701
702 let measurable_bytes: &[u8] = &raw_report_bytes[..0x2a0];
703
704 let mut hasher = Sha384::new();
705 hasher.update(measurable_bytes);
706 let base_digest = hasher.finish();
707
708 let ec = vek.public_key()?.ec_key()?;
709 let signed = sig.verify(&base_digest, &ec)?;
710 match signed {
711 true => Ok(()),
712 false => Err(Error::other("VEK does not sign the attestation report")),
713 }
714 }
715}
716
717#[cfg(feature = "openssl")]
718impl Verifiable for (&Certificate, &AttestationReport) {
719 type Output = ();
720
721 fn verify(self) -> std::io::Result<Self::Output> {
722 let vek = self.0;
723
724 let sig = EcdsaSig::try_from(&self.1.signature)?;
725 let raw_report_bytes = self.1.to_bytes()?;
726
727 let measurable_bytes: &[u8] = &raw_report_bytes[..0x2a0];
728
729 let mut hasher = Sha384::new();
730 hasher.update(measurable_bytes);
731 let base_digest = hasher.finish();
732
733 let ec = vek.public_key()?.ec_key()?;
734 let signed = sig.verify(&base_digest, &ec)?;
735 match signed {
736 true => Ok(()),
737 false => Err(Error::other("VEK does not sign the attestation report")),
738 }
739 }
740}
741
742#[cfg(feature = "crypto_nossl")]
743impl Verifiable for (&Chain, &AttestationReport) {
744 type Output = ();
745
746 fn verify(self) -> std::io::Result<Self::Output> {
747 let vek = self.0.verify()?;
752
753 let sig = p384::ecdsa::Signature::try_from(&self.1.signature)?;
754
755 let raw_report_bytes = self.1.to_bytes()?;
756
757 let measurable_bytes: &[u8] = &raw_report_bytes[..0x2a0];
758
759 use sha2::Digest;
760 let base_digest = sha2::Sha384::new_with_prefix(measurable_bytes);
761 let verifying_key = p384::ecdsa::VerifyingKey::from_sec1_bytes(vek.public_key_sec1())
762 .map_err(|e| {
763 std::io::Error::other(format!(
764 "failed to deserialize public key from sec1 bytes: {e:?}"
765 ))
766 })?;
767 use p384::ecdsa::signature::DigestVerifier;
768 verifying_key.verify_digest(base_digest, &sig).map_err(|e| {
769 std::io::Error::other(format!("VEK does not sign the attestation report: {e:?}"))
770 })
771 }
772}
773
774#[cfg(feature = "crypto_nossl")]
775impl Verifiable for (&Certificate, &AttestationReport) {
776 type Output = ();
777
778 fn verify(self) -> std::io::Result<Self::Output> {
779 let vek = self.0;
785
786 let sig = p384::ecdsa::Signature::try_from(&self.1.signature)?;
787
788 let raw_report_bytes = self.1.to_bytes()?;
789
790 let measurable_bytes: &[u8] = &raw_report_bytes[..0x2a0];
791
792 use sha2::Digest;
793 let base_digest = sha2::Sha384::new_with_prefix(measurable_bytes);
794 let verifying_key = p384::ecdsa::VerifyingKey::from_sec1_bytes(vek.public_key_sec1())
795 .map_err(|e| {
796 std::io::Error::other(format!(
797 "failed to deserialize public key from sec1 bytes: {e:?}"
798 ))
799 })?;
800 use p384::ecdsa::signature::DigestVerifier;
801 verifying_key.verify_digest(base_digest, &sig).map_err(|e| {
802 std::io::Error::other(format!("VEK does not sign the attestation report: {e:?}"))
803 })
804 }
805}
806
807bitfield! {
808 #[repr(C)]
833 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
834 #[derive(Default, Clone, Copy, Eq, PartialEq, PartialOrd, Ord)]
835 pub struct GuestPolicy(u64);
836 impl Debug;
837 pub abi_minor, set_abi_minor: 7, 0;
839 pub abi_major, set_abi_major: 15, 8;
841 pub smt_allowed, set_smt_allowed: 16;
843 pub migrate_ma_allowed, set_migrate_ma_allowed: 18;
846 pub debug_allowed, set_debug_allowed: 19;
848 pub single_socket_required, set_single_socket_required: 20;
850 pub cxl_allowed, set_cxl_allowed: 21;
852 pub mem_aes_256_xts, set_mem_aes_256_xts: 22;
854 pub rapl_dis, set_rapl_dis: 23;
856 pub ciphertext_hiding, set_ciphertext_hiding: 24;
858 pub page_swap_disabled, set_page_swap_disabled: 25;
863}
864
865impl Encoder<()> for GuestPolicy {
866 fn encode(&self, writer: &mut impl Write, _: ()) -> Result<(), std::io::Error> {
867 writer.write_bytes(self.0, ())?;
868 Ok(())
869 }
870}
871
872impl Decoder<()> for GuestPolicy {
873 fn decode(reader: &mut impl Read, _: ()) -> Result<Self, std::io::Error> {
874 let policy = reader.read_bytes()?;
875 Ok(Self(policy))
876 }
877}
878
879impl ByteParser<()> for GuestPolicy {
880 type Bytes = [u8; 8];
881 const EXPECTED_LEN: Option<usize> = Some(8);
882}
883
884impl Display for GuestPolicy {
885 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
886 write!(
887 f,
888 r#"Guest Policy (0x{:x}):
889 ABI Major: {}
890 ABI Minor: {}
891 SMT Allowed: {}
892 Migrate MA: {}
893 Debug Allowed: {}
894 Single Socket: {}
895 CXL Allowed: {}
896 AEX 256 XTS: {}
897 RAPL Allowed: {}
898 Ciphertext hiding: {}
899 Page Swap Disable: {}"#,
900 self.0,
901 self.abi_major(),
902 self.abi_minor(),
903 self.smt_allowed(),
904 self.migrate_ma_allowed(),
905 self.debug_allowed(),
906 self.single_socket_required(),
907 self.cxl_allowed(),
908 self.mem_aes_256_xts(),
909 self.rapl_dis(),
910 self.ciphertext_hiding(),
911 self.page_swap_disabled()
912 )
913 }
914}
915
916impl From<GuestPolicy> for u64 {
917 fn from(value: GuestPolicy) -> Self {
918 let reserved: u64 = 1 << 17;
920
921 value.0 | reserved
922 }
923}
924
925impl From<u64> for GuestPolicy {
926 fn from(value: u64) -> Self {
927 let reserved: u64 = 1 << 17;
929
930 GuestPolicy(value | reserved)
931 }
932}
933
934bitfield! {
935 #[repr(C)]
947 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
948 #[derive(Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
949 pub struct PlatformInfo(u64);
950 impl Debug;
951 pub smt_enabled, _: 0;
953 pub tsme_enabled, _: 1;
955 pub ecc_enabled, _: 2;
957 pub rapl_disabled, _: 3;
959 pub ciphertext_hiding_enabled, _: 4;
961 pub alias_check_complete, _: 5;
963 pub tio_enabled, _ : 7
965
966}
967
968impl Display for PlatformInfo {
969 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
970 write!(
971 f,
972 r#"Platform Info ({}):
973 SMT Enabled: {}
974 TSME Enabled: {}
975 ECC Enabled: {}
976 RAPL Disabled: {}
977 Ciphertext Hiding Enabled: {}
978 Alias Check Complete: {}
979 SEV-TIO Enabled: {}"#,
980 self.0,
981 self.smt_enabled(),
982 self.tsme_enabled(),
983 self.ecc_enabled(),
984 self.rapl_disabled(),
985 self.ciphertext_hiding_enabled(),
986 self.alias_check_complete(),
987 self.tio_enabled()
988 )
989 }
990}
991
992impl From<u64> for PlatformInfo {
993 fn from(value: u64) -> Self {
994 PlatformInfo(value)
995 }
996}
997
998impl From<PlatformInfo> for u64 {
999 fn from(value: PlatformInfo) -> Self {
1000 value.0
1001 }
1002}
1003
1004impl Encoder<()> for PlatformInfo {
1005 fn encode(&self, writer: &mut impl Write, _: ()) -> Result<(), std::io::Error> {
1006 writer.write_bytes(self.0, ())?;
1007 Ok(())
1008 }
1009}
1010
1011impl Decoder<()> for PlatformInfo {
1012 fn decode(reader: &mut impl Read, _: ()) -> Result<Self, std::io::Error> {
1013 let info = reader.read_bytes()?;
1014 Ok(Self(info))
1015 }
1016}
1017
1018impl ByteParser<()> for PlatformInfo {
1019 type Bytes = [u8; 8];
1020 const EXPECTED_LEN: Option<usize> = Some(8);
1021}
1022
1023bitfield! {
1024 #[repr(C)]
1034 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1035 #[derive(Default, Clone, Copy, Eq, PartialEq, PartialOrd, Ord)]
1036 pub struct KeyInfo(u32);
1037 impl Debug;
1038 pub author_key_en, _: 0;
1040 pub mask_chip_key, _: 1;
1044 pub signing_key, _: 4,2;
1050
1051}
1052
1053impl Encoder<()> for KeyInfo {
1054 fn encode(&self, writer: &mut impl Write, _: ()) -> Result<(), std::io::Error> {
1055 writer.write_bytes(self.0.to_le_bytes(), ())?;
1056 Ok(())
1057 }
1058}
1059
1060impl Decoder<()> for KeyInfo {
1061 fn decode(reader: &mut impl Read, _: ()) -> Result<Self, std::io::Error> {
1062 let info = reader.read_bytes()?;
1063 Ok(Self(info))
1064 }
1065}
1066
1067impl ByteParser<()> for KeyInfo {
1068 type Bytes = [u8; 4];
1069 const EXPECTED_LEN: Option<usize> = Some(4);
1070}
1071
1072impl From<u32> for KeyInfo {
1073 fn from(value: u32) -> Self {
1074 KeyInfo(value)
1075 }
1076}
1077
1078impl From<KeyInfo> for u32 {
1079 fn from(value: KeyInfo) -> Self {
1080 value.0
1081 }
1082}
1083
1084impl Display for KeyInfo {
1085 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1086 let signing_key = match self.signing_key() {
1087 0 => "vcek",
1088 1 => "vlek",
1089 7 => "none",
1090 _ => "unknown",
1091 };
1092
1093 write!(
1094 f,
1095 r#"Key Information:
1096 author key enabled: {}
1097 mask chip key: {}
1098 signing key: {}"#,
1099 self.author_key_en(),
1100 self.mask_chip_key(),
1101 signing_key
1102 )
1103 }
1104}
1105
1106#[cfg(test)]
1107mod tests {
1108
1109 use super::*;
1110 use std::{convert::TryInto, io::Write};
1111
1112 #[test]
1113 fn test_derive_key_new() {
1114 let expected: DerivedKey = DerivedKey {
1115 root_key_select: 0,
1116 _reserved_0: 0,
1117 guest_field_select: GuestFieldSelect(0),
1118 vmpl: 0,
1119 guest_svn: 0,
1120 tcb_version: 0,
1121 launch_mit_vector: None,
1122 };
1123
1124 let guest_field: GuestFieldSelect = GuestFieldSelect(0);
1125
1126 let actual: DerivedKey = DerivedKey::new(false, guest_field, 0, 0, 0, None);
1127
1128 assert_eq!(actual, expected);
1129 }
1130
1131 #[test]
1132 fn test_derive_key_get_root_key_select() {
1133 let dk_struct: DerivedKey = DerivedKey {
1134 root_key_select: 0,
1135 _reserved_0: 0,
1136 guest_field_select: GuestFieldSelect(0),
1137 vmpl: 0,
1138 guest_svn: 0,
1139 tcb_version: 0,
1140 launch_mit_vector: None,
1141 };
1142
1143 let expected: u32 = 0;
1144 let actual: u32 = dk_struct.get_root_key_select();
1145
1146 assert_eq!(actual, expected);
1147 }
1148
1149 #[test]
1150 fn test_guest_field_select_all_on() {
1151 let actual: GuestFieldSelect = GuestFieldSelect(0b111111);
1152
1153 assert!(actual.get_guest_policy());
1154 assert!(actual.get_image_id());
1155 assert!(actual.get_family_id());
1156 assert!(actual.get_measurement());
1157 assert!(actual.get_svn());
1158 assert!(actual.get_tcb_version());
1159 }
1160
1161 #[test]
1162 fn test_guest_field_select_all_off() {
1163 let actual: GuestFieldSelect = GuestFieldSelect(0);
1164
1165 assert!(!actual.get_guest_policy());
1166 assert!(!actual.get_image_id());
1167 assert!(!actual.get_family_id());
1168 assert!(!actual.get_measurement());
1169 assert!(!actual.get_svn());
1170 assert!(!actual.get_tcb_version());
1171 }
1172
1173 #[test]
1174 fn test_attestation_report_fmt() {
1175 let expected: &str = r#"Attestation Report:
1176
1177Version: 0
1178
1179Guest SVN: 0
1180
1181Guest Policy (0x0):
1182 ABI Major: 0
1183 ABI Minor: 0
1184 SMT Allowed: false
1185 Migrate MA: false
1186 Debug Allowed: false
1187 Single Socket: false
1188 CXL Allowed: false
1189 AEX 256 XTS: false
1190 RAPL Allowed: false
1191 Ciphertext hiding: false
1192 Page Swap Disable: false
1193
1194Family ID:
119500 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1196
1197Image ID:
119800 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1199
1200VMPL: 0
1201
1202Signature Algorithm: 0
1203
1204Current TCB:
1205
1206TCB Version:
1207 Microcode: 0
1208 SNP: 0
1209 TEE: 0
1210 Boot Loader: 0
1211 FMC: None
1212
1213Platform Info (0):
1214 SMT Enabled: false
1215 TSME Enabled: false
1216 ECC Enabled: false
1217 RAPL Disabled: false
1218 Ciphertext Hiding Enabled: false
1219 Alias Check Complete: false
1220 SEV-TIO Enabled: false
1221
1222Key Information:
1223 author key enabled: false
1224 mask chip key: false
1225 signing key: vcek
1226
1227Report Data:
122800 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
122900 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
123000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
123100 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1232
1233Measurement:
123400 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
123500 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
123600 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1237
1238Host Data:
123900 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
124000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1241
1242ID Key Digest:
124300 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
124400 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
124500 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1246
1247Author Key Digest:
124800 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
124900 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
125000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1251
1252Report ID:
125300 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
125400 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1255
1256Report ID Migration Agent:
125700 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
125800 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1259
1260Reported TCB:
1261
1262TCB Version:
1263 Microcode: 0
1264 SNP: 0
1265 TEE: 0
1266 Boot Loader: 0
1267 FMC: None
1268
1269CPUID Family ID: None
1270
1271CPUID Model ID: None
1272
1273CPUID Stepping: None
1274
1275Chip ID:
127600 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
127700 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
127800 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
127900 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1280
1281Committed TCB:
1282
1283TCB Version:
1284 Microcode: 0
1285 SNP: 0
1286 TEE: 0
1287 Boot Loader: 0
1288 FMC: None
1289
1290Current Version: 0.0.0
1291
1292Committed Version: 0.0.0
1293
1294Launch TCB:
1295
1296TCB Version:
1297 Microcode: 0
1298 SNP: 0
1299 TEE: 0
1300 Boot Loader: 0
1301 FMC: None
1302
1303Launch Mitigation Vector: None
1304
1305Current Mitigation Vector: None
1306
1307Signature:
1308 R:
130900 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
131000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
131100 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
131200 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
131300 00 00 00 00 00 00 00
1314 S:
131500 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
131600 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
131700 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
131800 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
131900 00 00 00 00 00 00 00"#;
1320 assert_eq!(expected, AttestationReport::default().to_string())
1321 }
1322
1323 #[test]
1324 fn test_attestation_report_copy() {
1325 let expected: AttestationReport = AttestationReport::default();
1326
1327 let copy: AttestationReport = expected;
1328
1329 assert_eq!(expected, copy);
1330 }
1331
1332 #[test]
1333 fn test_guest_policy_zeroed() {
1334 let gp: GuestPolicy = GuestPolicy(0);
1335
1336 assert_eq!(gp.abi_minor(), 0);
1337 assert_eq!(gp.abi_major(), 0);
1338 assert!(!gp.smt_allowed());
1339 assert!(!gp.migrate_ma_allowed());
1340 assert!(!gp.debug_allowed());
1341 assert!(!gp.single_socket_required());
1342 assert!(!gp.cxl_allowed());
1343 assert!(!gp.mem_aes_256_xts());
1344 assert!(!gp.rapl_dis());
1345 assert!(!gp.ciphertext_hiding());
1346 }
1347
1348 #[test]
1349 fn test_guest_policy_max() {
1350 let gp: GuestPolicy = GuestPolicy(0b1111111111111111111111111);
1351
1352 assert_eq!(gp.abi_minor(), 0b11111111);
1353 assert_eq!(gp.abi_major(), 0b11111111);
1354 assert!(gp.smt_allowed());
1355 assert!(gp.migrate_ma_allowed());
1356 assert!(gp.debug_allowed());
1357 assert!(gp.single_socket_required());
1358 assert!(gp.cxl_allowed());
1359 assert!(gp.mem_aes_256_xts());
1360 assert!(gp.rapl_dis());
1361 assert!(gp.ciphertext_hiding());
1362 }
1363
1364 #[test]
1365 fn test_set_guest_policy_max() {
1366 let mut gp: GuestPolicy = Default::default();
1367
1368 assert_eq!(gp.abi_minor(), 0);
1369 gp.set_abi_minor(1);
1370 assert_eq!(gp.abi_minor(), 0b1);
1371
1372 assert_eq!(gp.abi_major(), 0);
1373 gp.set_abi_major(1);
1374 assert_eq!(gp.abi_major(), 0b1);
1375
1376 assert!(!gp.smt_allowed());
1377 gp.set_smt_allowed(true);
1378 assert!(gp.smt_allowed());
1379
1380 assert!(!gp.migrate_ma_allowed());
1381 gp.set_migrate_ma_allowed(true);
1382 assert!(gp.migrate_ma_allowed());
1383
1384 assert!(!gp.debug_allowed());
1385 gp.set_debug_allowed(true);
1386 assert!(gp.debug_allowed());
1387
1388 assert!(!gp.single_socket_required());
1389 gp.set_single_socket_required(true);
1390 assert!(gp.single_socket_required());
1391
1392 assert!(!gp.cxl_allowed());
1393 gp.set_cxl_allowed(true);
1394 assert!(gp.cxl_allowed());
1395
1396 assert!(!gp.mem_aes_256_xts());
1397 gp.set_mem_aes_256_xts(true);
1398 assert!(gp.mem_aes_256_xts());
1399
1400 assert!(!gp.rapl_dis());
1401 gp.set_rapl_dis(true);
1402 assert!(gp.rapl_dis());
1403
1404 assert!(!gp.ciphertext_hiding());
1405 gp.set_ciphertext_hiding(true);
1406 assert!(gp.ciphertext_hiding());
1407 }
1408
1409 #[test]
1410 fn test_guest_policy_from_u64() {
1411 let gp: GuestPolicy = GuestPolicy(5);
1412
1413 let expected: u64 = (1 << 17) | 5;
1415
1416 assert_eq!(u64::from(gp), expected);
1417 }
1418
1419 #[test]
1420 fn test_platform_info_zeroed() {
1421 let expected: PlatformInfo = PlatformInfo(0);
1422
1423 assert!(!expected.smt_enabled());
1424 assert!(!expected.tsme_enabled());
1425 assert!(!expected.ecc_enabled());
1426 assert!(!expected.rapl_disabled());
1427 assert!(!expected.ciphertext_hiding_enabled());
1428 assert!(!expected.alias_check_complete());
1429 }
1430
1431 #[test]
1432 fn test_platform_info_full() {
1433 let expected: PlatformInfo = PlatformInfo(0b111111);
1434
1435 assert!(expected.smt_enabled());
1436 assert!(expected.tsme_enabled());
1437 assert!(expected.ecc_enabled());
1438 assert!(expected.rapl_disabled());
1439 assert!(expected.ciphertext_hiding_enabled());
1440 assert!(expected.alias_check_complete());
1441 }
1442
1443 #[test]
1444 fn test_platform_info_fmt() {
1445 let expected: &str = r#"Platform Info (0):
1446 SMT Enabled: false
1447 TSME Enabled: false
1448 ECC Enabled: false
1449 RAPL Disabled: false
1450 Ciphertext Hiding Enabled: false
1451 Alias Check Complete: false
1452 SEV-TIO Enabled: false"#;
1453 let actual: PlatformInfo = PlatformInfo(0);
1454
1455 assert_eq!(expected, actual.to_string());
1456 }
1457
1458 #[test]
1459 fn test_key_info_zeroed() {
1460 let expected: KeyInfo = KeyInfo(0);
1461
1462 assert!(!expected.author_key_en());
1463 assert!(!expected.mask_chip_key());
1464
1465 assert_eq!(expected.signing_key(), 0);
1466 }
1467
1468 #[test]
1469 fn test_key_info_max() {
1470 let expected: KeyInfo = KeyInfo(0b11111);
1471
1472 assert!(expected.author_key_en());
1473 assert!(expected.mask_chip_key());
1474 assert_eq!(expected.signing_key(), 0b111);
1475 }
1476
1477 #[test]
1478 fn test_key_info_fmt_vcek() {
1479 let expected: &str = r#"Key Information:
1480 author key enabled: false
1481 mask chip key: false
1482 signing key: vcek"#;
1483 let actual: KeyInfo = KeyInfo(0);
1484
1485 assert_eq!(expected, actual.to_string());
1486 }
1487
1488 #[test]
1489 fn test_key_info_fmt_vlek() {
1490 let expected: &str = r#"Key Information:
1491 author key enabled: false
1492 mask chip key: false
1493 signing key: vlek"#;
1494 let actual: KeyInfo = KeyInfo(0b100);
1495
1496 assert_eq!(expected, actual.to_string());
1497 }
1498
1499 #[test]
1500 fn test_key_info_fmt_none() {
1501 let expected: &str = r#"Key Information:
1502 author key enabled: false
1503 mask chip key: false
1504 signing key: none"#;
1505 let actual: KeyInfo = KeyInfo(0b11100);
1506
1507 assert_eq!(expected, actual.to_string());
1508 }
1509
1510 #[test]
1511 fn test_key_info_fmt_unknown() {
1512 let expected: &str = r#"Key Information:
1513 author key enabled: false
1514 mask chip key: false
1515 signing key: unknown"#;
1516 let actual: KeyInfo = KeyInfo(0b11000);
1517
1518 assert_eq!(expected, actual.to_string());
1519 }
1520
1521 #[test]
1522 fn test_platform_info_v2_serialization() {
1523 let original = PlatformInfo(0b11111);
1524 let buffer = original.to_bytes().unwrap();
1526 let decoded = PlatformInfo::from_bytes(&buffer).unwrap();
1527
1528 assert_eq!(original, decoded);
1529 }
1530
1531 #[test]
1532 fn test_key_info_serialization() {
1533 let original = KeyInfo(0b11111);
1534
1535 let buffer = original.to_bytes().unwrap();
1537 let decoded = KeyInfo::from_bytes(&buffer).unwrap();
1538
1539 assert_eq!(original, decoded);
1540 assert!(decoded.author_key_en());
1541 assert!(decoded.mask_chip_key());
1542 assert_eq!(decoded.signing_key(), 0b111);
1543 }
1544
1545 #[test]
1546 fn test_guest_policy_serialization() {
1547 let mut original: GuestPolicy = Default::default();
1548 original.set_abi_major(2);
1549 original.set_abi_minor(1);
1550 original.set_smt_allowed(true);
1551 original.set_debug_allowed(true);
1552
1553 let buffer = original.to_bytes().unwrap();
1555 let decoded = GuestPolicy::from_bytes(&buffer).unwrap();
1556 assert_eq!(original, decoded);
1557 }
1558
1559 #[test]
1560 fn test_version_extraction() {
1561 let raw_v2 = [2, 0, 0, 0]; let version = u32::from_le_bytes([raw_v2[0], raw_v2[1], raw_v2[2], raw_v2[3]]);
1563 assert_eq!(version, 2);
1564
1565 let raw_v3 = [3, 0, 0, 0]; let version = u32::from_le_bytes([raw_v3[0], raw_v3[1], raw_v3[2], raw_v3[3]]);
1567 assert_eq!(version, 3);
1568 }
1569
1570 #[test]
1571 fn test_boundary_value_serialization() {
1572 let platform_info = PlatformInfo(u64::MAX);
1574 let key_info = KeyInfo(u32::MAX);
1575 let guest_policy = GuestPolicy(u64::MAX);
1576
1577 assert_eq!(
1579 platform_info,
1580 PlatformInfo::from_bytes(&platform_info.to_bytes().unwrap()).unwrap()
1581 );
1582 assert_eq!(
1583 key_info,
1584 KeyInfo::from_bytes(&key_info.to_bytes().unwrap()).unwrap()
1585 );
1586 assert_eq!(
1587 guest_policy,
1588 GuestPolicy::from_bytes(&guest_policy.to_bytes().unwrap()).unwrap()
1589 );
1590 }
1591
1592 #[test]
1593 fn test_guest_field_select_operations() {
1594 let mut field = GuestFieldSelect::default();
1595
1596 field.set_guest_policy(true);
1597 assert!(field.get_guest_policy());
1598
1599 field.set_image_id(true);
1600 assert!(field.get_image_id());
1601
1602 field.set_family_id(true);
1603 assert!(field.get_family_id());
1604
1605 field.set_measurement(true);
1606 assert!(field.get_measurement());
1607 }
1608
1609 #[test]
1610 fn test_derived_key_fields() {
1611 let key = DerivedKey::new(true, GuestFieldSelect(0xFF), 2, 3, 0x1234, None);
1612 assert_eq!(key.get_root_key_select(), 1);
1613 assert_eq!(key.vmpl, 2);
1614 assert_eq!(key.guest_svn, 3);
1615 assert_eq!(key.tcb_version, 0x1234);
1616 }
1617
1618 #[test]
1619 fn test_key_info_all_combinations() {
1620 let mut info = KeyInfo(0);
1621
1622 assert_eq!(info.signing_key(), 0);
1624 assert!(!info.author_key_en());
1625
1626 info = KeyInfo(0b100);
1628 assert_eq!(info.signing_key(), 1);
1629
1630 info = KeyInfo(0b11100);
1632 assert_eq!(info.signing_key(), 7);
1633 }
1634
1635 #[test]
1636 fn test_attestation_report_fields() {
1637 let report: AttestationReport = AttestationReport {
1638 version: 2,
1639 guest_svn: 1,
1640 vmpl: 3,
1641 ..Default::default()
1642 };
1643 assert_eq!(report.version, 2);
1644 assert_eq!(report.guest_svn, 1);
1645 assert_eq!(report.vmpl, 3);
1646 assert_eq!(report.measurement, [0; 48]);
1647 }
1648
1649 #[test]
1650 fn test_guest_policy_combined_fields() {
1651 let mut policy: GuestPolicy = Default::default();
1652
1653 policy.set_abi_major(2);
1654 policy.set_abi_minor(1);
1655 policy.set_smt_allowed(true);
1656 policy.set_debug_allowed(true);
1657
1658 assert_eq!(policy.abi_major(), 2);
1659 assert_eq!(policy.abi_minor(), 1);
1660 assert!(policy.smt_allowed());
1661 assert!(policy.debug_allowed());
1662
1663 let policy_u64: u64 = policy.into();
1664 assert_eq!(policy_u64 & (1 << 17), 1 << 17); }
1666
1667 #[test]
1668 fn test_version_display() {
1669 let version = Version::new(3, 2, 1);
1670 assert_eq!(version.to_string(), "3.2.1");
1671
1672 let max_version = Version::new(255, 255, 255);
1673 assert_eq!(max_version.to_string(), "255.255.255");
1674
1675 let min_version = Version::new(0, 0, 0);
1676 assert_eq!(min_version.to_string(), "0.0.0");
1677 }
1678
1679 #[test]
1680 fn test_version_byte_parser() {
1681 let bytes = [1, 2, 3];
1683 let version = Version::from_bytes(&bytes).unwrap();
1684 assert_eq!(version, Version::new(3, 2, 1));
1685
1686 let version = Version::new(4, 5, 6);
1688 let bytes = version.to_bytes().unwrap();
1689 assert_eq!(bytes, [6, 5, 4]);
1690
1691 let original = Version::new(7, 8, 9);
1693 let bytes = original.to_bytes().unwrap();
1694 let roundtrip = Version::from_bytes(&bytes).unwrap();
1695 assert_eq!(original, roundtrip);
1696
1697 assert_eq!(<Version as Default>::default(), Version::new(0, 0, 0));
1699 }
1700
1701 #[test]
1702 fn test_attestation_report_from_bytes() {
1703 let mut bytes: Vec<u8> = vec![0; 1183];
1705
1706 bytes.insert(0, 2);
1708
1709 let vcek = [
1710 0xD4, 0x95, 0x54, 0xEC, 0x71, 0x7F, 0x4E, 0x5B, 0x0F, 0xE6, 0xB1, 0x43, 0xBC, 0xF0,
1711 0x40, 0x5B, 0xD7, 0xAE, 0x30, 0x47, 0x27, 0xED, 0xF4, 0x66, 0x03, 0xF2, 0xA7, 0x6A,
1712 0xEF, 0x6A, 0x3A, 0xBC, 0x15, 0xD7, 0xAF, 0x38, 0xDB, 0x75, 0x70, 0x39, 0x02, 0x9F,
1713 0x0E, 0xFA, 0xCF, 0xD0, 0x8E, 0x24, 0x43, 0x24, 0x88, 0x47, 0x38, 0xC7, 0x2B, 0x08,
1714 0x2E, 0x2F, 0x87, 0xA4, 0x4D, 0x54, 0x1E, 0xB6,
1715 ];
1716
1717 bytes[0x1A8..0x1E0].copy_from_slice(&vcek[..(0x1E0 - 0x1A8)]);
1718
1719 let result = AttestationReport::from_bytes(bytes.as_slice());
1721 assert!(result.is_ok());
1722 }
1723
1724 #[test]
1725 #[should_panic]
1726 fn test_attestation_report_from_invalid_bytes() {
1727 let mut bytes: Vec<u8> = vec![0; 1183];
1729
1730 bytes.insert(0, 2);
1732
1733 AttestationReport::from_bytes(bytes[..100].try_into().unwrap()).unwrap();
1735 }
1736
1737 #[test]
1738 fn test_attestation_report_parse_and_write_bytes() {
1739 let report = AttestationReport {
1740 version: 2,
1741 guest_svn: Default::default(),
1742 policy: Default::default(),
1743 family_id: Default::default(),
1744 image_id: Default::default(),
1745 chip_id: [
1746 0xD4, 0x95, 0x54, 0xEC, 0x71, 0x7F, 0x4E, 0x5B, 0x0F, 0xE6, 0xB1, 0x43, 0xBC, 0xF0,
1747 0x40, 0x5B, 0xD7, 0xAE, 0x30, 0x47, 0x27, 0xED, 0xF4, 0x66, 0x03, 0xF2, 0xA7, 0x6A,
1748 0xEF, 0x6A, 0x3A, 0xBC, 0x15, 0xD7, 0xAF, 0x38, 0xDB, 0x75, 0x70, 0x39, 0x02, 0x9F,
1749 0x0E, 0xFA, 0xCF, 0xD0, 0x8E, 0x24, 0x43, 0x24, 0x88, 0x47, 0x38, 0xC7, 0x2B, 0x08,
1750 0x2E, 0x2F, 0x87, 0xA4, 0x4D, 0x54, 0x1E, 0xB6,
1751 ],
1752 ..Default::default()
1753 };
1754
1755 let result = report.to_bytes();
1757 assert!(result.is_ok());
1758
1759 struct FailingWriter;
1761 impl Write for FailingWriter {
1762 fn write(&mut self, _buf: &[u8]) -> std::io::Result<usize> {
1763 Err(std::io::Error::other("test error"))
1764 }
1765 fn flush(&mut self) -> std::io::Result<()> {
1766 Ok(())
1767 }
1768 }
1769
1770 let mut writer = FailingWriter;
1771
1772 let result = report.encode(&mut FailingWriter, ());
1773 assert!(result.is_err());
1774 assert!(writer.flush().is_ok());
1775 }
1776
1777 #[test]
1778 fn test_version_edge_cases() {
1779 let version = Version::new(255, 255, 255);
1781 let bytes = version.to_bytes().unwrap();
1782 assert_eq!(bytes, [255, 255, 255]);
1783
1784 let version = Version::new(0, 255, 0);
1786 let bytes = version.to_bytes().unwrap();
1787 assert_eq!(bytes, [0, 255, 0]);
1788 }
1789
1790 #[test]
1791 fn test_version_ordering() {
1792 let v1 = Version::new(1, 0, 0);
1793 let v2 = Version::new(1, 0, 1);
1794 let v3 = Version::new(1, 1, 0);
1795
1796 assert!(v1 < v2);
1797 assert!(v2 < v3);
1798 assert!(v1 < v3);
1799
1800 assert_eq!(Version::new(1, 2, 3), Version::new(1, 2, 3));
1802 assert_ne!(Version::new(1, 2, 3), Version::new(1, 2, 4));
1803 }
1804
1805 #[test]
1806 fn test_version_copy() {
1807 let original = Version::new(1, 2, 3);
1808 let cloned = original;
1809
1810 assert_eq!(original, cloned);
1811 assert_eq!(original.to_bytes().unwrap(), cloned.to_bytes().unwrap());
1812 }
1813
1814 #[test]
1815 fn test_attestation_report_complex_write() {
1816 let report = AttestationReport {
1817 version: 2,
1818 guest_svn: 1,
1819 policy: GuestPolicy::from(0xFF),
1820 family_id: [0xAA; 16],
1821 image_id: [0xBB; 16],
1822 chip_id: [
1823 0xD4, 0x95, 0x54, 0xEC, 0x71, 0x7F, 0x4E, 0x5B, 0x0F, 0xE6, 0xB1, 0x43, 0xBC, 0xF0,
1824 0x40, 0x5B, 0xD7, 0xAE, 0x30, 0x47, 0x27, 0xED, 0xF4, 0x66, 0x03, 0xF2, 0xA7, 0x6A,
1825 0xEF, 0x6A, 0x3A, 0xBC, 0x15, 0xD7, 0xAF, 0x38, 0xDB, 0x75, 0x70, 0x39, 0x02, 0x9F,
1826 0x0E, 0xFA, 0xCF, 0xD0, 0x8E, 0x24, 0x43, 0x24, 0x88, 0x47, 0x38, 0xC7, 0x2B, 0x08,
1827 0x2E, 0x2F, 0x87, 0xA4, 0x4D, 0x54, 0x1E, 0xB6,
1828 ],
1829 ..Default::default()
1830 };
1831
1832 let buffer = report.to_bytes();
1833 assert!(buffer.is_ok());
1834
1835 let read_back = AttestationReport::from_bytes(&buffer.unwrap()).unwrap();
1837 assert_eq!(read_back.version, 2);
1838 assert_eq!(read_back.guest_svn, 1);
1839 assert_eq!(read_back.family_id, [0xAA; 16]);
1840 assert_eq!(read_back.image_id, [0xBB; 16]);
1841 }
1842
1843 #[test]
1844 fn test_write_with_limited_writer() {
1845 let report = AttestationReport {
1846 version: 2,
1847 guest_svn: Default::default(),
1848 policy: Default::default(),
1849 family_id: Default::default(),
1850 image_id: Default::default(),
1851 chip_id: [
1852 0xD4, 0x95, 0x54, 0xEC, 0x71, 0x7F, 0x4E, 0x5B, 0x0F, 0xE6, 0xB1, 0x43, 0xBC, 0xF0,
1853 0x40, 0x5B, 0xD7, 0xAE, 0x30, 0x47, 0x27, 0xED, 0xF4, 0x66, 0x03, 0xF2, 0xA7, 0x6A,
1854 0xEF, 0x6A, 0x3A, 0xBC, 0x15, 0xD7, 0xAF, 0x38, 0xDB, 0x75, 0x70, 0x39, 0x02, 0x9F,
1855 0x0E, 0xFA, 0xCF, 0xD0, 0x8E, 0x24, 0x43, 0x24, 0x88, 0x47, 0x38, 0xC7, 0x2B, 0x08,
1856 0x2E, 0x2F, 0x87, 0xA4, 0x4D, 0x54, 0x1E, 0xB6,
1857 ],
1858 ..Default::default()
1859 };
1860
1861 struct LimitedWriter {
1863 data: Vec<u8>,
1864 max_write: usize,
1865 }
1866
1867 impl Write for LimitedWriter {
1868 fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
1869 let write_size = std::cmp::min(self.max_write, buf.len());
1870 self.data.extend_from_slice(&buf[..write_size]);
1871 Ok(write_size)
1872 }
1873
1874 fn flush(&mut self) -> std::io::Result<()> {
1875 Ok(())
1876 }
1877 }
1878
1879 let mut writer = LimitedWriter {
1880 data: Vec::new(),
1881 max_write: 16, };
1883
1884 assert!(report.encode(&mut writer, ()).is_ok());
1885 assert!(writer.flush().is_ok());
1886 }
1887
1888 #[test]
1889 fn test_platform_v2_info_from_u64() {
1890 let value: u64 = 0xFFFF;
1891 let platform_info = PlatformInfo::from(value);
1892 assert_eq!(platform_info.0, value);
1893
1894 let value: u64 = 0;
1895 let platform_info = PlatformInfo::from(value);
1896 assert_eq!(platform_info.0, value);
1897
1898 let value: u64 = u64::MAX;
1899 let platform_info = PlatformInfo::from(value);
1900 assert_eq!(platform_info.0, value);
1901 }
1902
1903 #[test]
1904 fn test_platform_v2_info_into_u64() {
1905 let platform_info = PlatformInfo(0xFFFF);
1906 let value: u64 = platform_info.into();
1907 assert_eq!(value, 0xFFFF);
1908
1909 let platform_info = PlatformInfo(0);
1910 let value: u64 = platform_info.into();
1911 assert_eq!(value, 0);
1912
1913 let platform_info = PlatformInfo(u64::MAX);
1914 let value: u64 = platform_info.into();
1915 assert_eq!(value, u64::MAX);
1916 }
1917
1918 #[test]
1919 fn test_key_info_from_u32() {
1920 let value: u32 = 0xFFFF;
1921 let key_info = KeyInfo::from(value);
1922 assert_eq!(key_info.0, value);
1923
1924 let value: u32 = 0;
1925 let key_info = KeyInfo::from(value);
1926 assert_eq!(key_info.0, value);
1927
1928 let value: u32 = u32::MAX;
1929 let key_info = KeyInfo::from(value);
1930 assert_eq!(key_info.0, value);
1931 }
1932
1933 #[test]
1934 fn test_key_info_into_u32() {
1935 let key_info = KeyInfo(0xFFFF);
1936 let value: u32 = key_info.into();
1937 assert_eq!(value, 0xFFFF);
1938
1939 let key_info = KeyInfo(0);
1940 let value: u32 = key_info.into();
1941 assert_eq!(value, 0);
1942
1943 let key_info = KeyInfo(u32::MAX);
1944 let value: u32 = key_info.into();
1945 assert_eq!(value, u32::MAX);
1946 }
1947
1948 #[test]
1949 fn test_turin_like_chip_id_milan_chip_id() {
1950 let vcek_bytes = [
1952 0xD4, 0x95, 0x54, 0xEC, 0x71, 0x7F, 0x4E, 0x5B, 0x0F, 0xE6, 0xB1, 0x43, 0xBC, 0xF0,
1953 0x40, 0x5B, 0xD7, 0xAE, 0x30, 0x47, 0x27, 0xED, 0xF4, 0x66, 0x03, 0xF2, 0xA7, 0x6A,
1954 0xEF, 0x6A, 0x3A, 0xBC, 0x15, 0xD7, 0xAF, 0x38, 0xDB, 0x75, 0x70, 0x39, 0x02, 0x9F,
1955 0x0E, 0xFA, 0xCF, 0xD0, 0x8E, 0x24, 0x43, 0x24, 0x88, 0x47, 0x38, 0xC7, 0x2B, 0x08,
1956 0x2E, 0x2F, 0x87, 0xA4, 0x4D, 0x54, 0x1E, 0xB6,
1957 ];
1958
1959 assert!(!AttestationReport::chip_id_is_turin_like(&vcek_bytes).unwrap());
1960 }
1961
1962 #[test]
1963 fn test_turin_like_chip_id_turin_chip_id() {
1964 let vcek_bytes = [
1966 0xD4, 0x95, 0x54, 0xEC, 0x71, 0x7F, 0x4E, 0x5B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1967 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1968 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1969 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1970 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1971 ];
1972
1973 assert!(AttestationReport::chip_id_is_turin_like(&vcek_bytes).unwrap());
1974 }
1975}