Skip to content

Commit

Permalink
Adding to_bytes and from_bytes for AttestationReport
Browse files Browse the repository at this point in the history
Serde serializes and deserializes enums by manually appending 4 tag bytes at the start and end of the byte stream it generates. This causes issues when deserializing reports that are raw bytes and results in reports that are offset by 4 bytes.

Since some users might implement their own methods for handling reports, we want to ensure that, regardless of the enum interface, they always receive the raw bytes of the attestation report when serializing/deserializing.

By implementing manual serialization, we bypassed the 4-byte tag issue. However, we couldn't find a reliable method to deserialize raw bytes directly into an enum. Instead, we recommend using TryFrom<&[u8]>.

To simplify this, we added two helper functions, to_bytes and from_bytes, making the process more straightforward and user-friendly.

Recommendation:
Use these helper functions instead of Serde’s serialize and deserialize when working with the enum. Raw report structures work fine.

Signed-off-by: DGonzalezVillal <[email protected]>
  • Loading branch information
DGonzalezVillal committed Feb 4, 2025
1 parent 4968d8f commit 7b51076
Showing 1 changed file with 26 additions and 2 deletions.
28 changes: 26 additions & 2 deletions src/firmware/guest/types/snp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use crate::certs::snp::{Certificate, Chain, Verifiable};

use crate::util::sealed;
use bitfield::bitfield;
use serde::{Deserialize, Serialize};
use serde::{Deserialize, Serialize, Serializer};
use serde_big_array::BigArray;
use std::convert::{TryFrom, TryInto};

Expand Down Expand Up @@ -141,7 +141,7 @@ pub trait Attestable: Serialize + sealed::Sealed {
///
/// Since the release of the 1.56 ABI, the Attestation Report was bumped from version 2 to 3.
/// Due to content differences, both versions are kept separately in order to provide backwards compatibility and most reliable security.
#[derive(Debug, Clone, Copy, Deserialize, Serialize)]
#[derive(Debug, Clone, Copy)]
pub enum AttestationReport {
/// Version 2 of the Attestation Report
V2(AttestationReportV2),
Expand Down Expand Up @@ -170,6 +170,21 @@ impl TryFrom<&[u8]> for AttestationReport {
}
}

/// Implement custom serialization for AttestationReport
/// This will ensure that the Attestation Report enum gets serialized into raw bytes,
/// not the serde default that tags the enum with 4 extra bytes for its own tagging mechanism.
impl Serialize for AttestationReport {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
match self {
AttestationReport::V2(report) => report.serialize(serializer),
AttestationReport::V3(report) => report.serialize(serializer),
}
}
}

impl sealed::Sealed for AttestationReport {}

impl Attestable for AttestationReport {
Expand All @@ -190,6 +205,15 @@ impl Attestable for AttestationReport {
}

impl AttestationReport {
/// Convert bytes to an Attestation Report Enum
pub fn from_bytes(bytes: &[u8]) -> Result<AttestationReport, AttestationReportError> {
AttestationReport::try_from(bytes)
}

/// Serialize the Attestation Report enum to raw bytes
pub fn to_bytes(&self) -> Result<Vec<u8>, AttestationReportError> {
bincode::serialize(self).map_err(|e| AttestationReportError::BincodeError(*e))
}
/// Get Attestation Report Version
pub fn version(&self) -> u32 {
match self {
Expand Down

0 comments on commit 7b51076

Please sign in to comment.