Skip to content

feat: decouple platform and measurements, allow flexible policies #28

@0x416e746f6e

Description

@0x416e746f6e

currently, the measurement policies look like:

[
  {
    "measurement_id": "dcap-tdx-example",
    "attestation_type": "dcap-tdx",
    "measurements": {
      "mrtd": {
        "expected_any": [
          "47a1cc074b914df8596bad0ed13d50d561ad1effc7f7cc530ab86da7ea49ffc03e57e7da829f8cba9c629c3970505323"
        ]
      },
      "rtmr0": {
        "expected_any": [
          "da6e07866635cb34a9ffcdc26ec6622f289e625c42c39b320f29cdf1dc84390b4f89dd0b073be52ac38ca7b0a0f375bb"
        ]
      },
      // ...
    }
  }
]

which poses 2 problems:

  • it gives false impression that attestation type binds the measurements to platform (e.g. qemu-tdx vs. gcp-tdx)
  • it makes hard to write complex policies (e.g. if we want to allow any permutation of 2 values for RTMR0 and 3 values for RTMR1, then we'd have to create a list of 6 entries)

the suggestion is to consider moving towards policies that are built along the lines of:

#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub enum TdxRegister {
    MRTD,
    RTMR(u8),
}

pub type TdxMeasurement = [u8; 48];

#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub enum PcrRegister {
    Pcr(u8),
}

pub type PcrMeasurement = [u8; 32];

#[derive(Clone, Debug, PartialEq, Eq)]
pub enum Measurements {
    Dcap(HashMap<TdxRegister, TdxMeasurement>),
    Vtpm(HashMap<PcrRegister, PcrMeasurement>),
    None,
}

#[derive(Clone, Debug, PartialEq, Eq)]
pub enum ExpectedMeasurement {
    Dcap(HashMap<TdxRegister, Vec<TdxMeasurement>>),
    Vtpm(HashMap<PcrRegister, Vec<PcrMeasurement>>),
    None,
}

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum DcapPlatform {
    Azure,
    Gcp,
    Qemu,
    None,
}

#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct MeasurementRecord {
    #[serde(skip_serializing_if = "Option::is_none")]
    pub platform: Option<DcapPlatform>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub measurements: Option<Vec<ExpectedMeasurement>>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub comment: Option<String>,
}

#[derive(Clone, Debug, PartialEq, Eq)]
pub enum MeasurementClause {
    Match(Box<MeasurementRecord>),

    Not(Box<MeasurementClause>),
    And(Box<Vec<MeasurementClause>>),
    Or(Box<Vec<MeasurementClause>>),
}

#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
pub struct MeasurementPolicy {
    pub policy: MeasurementClause,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub comment: Option<String>,
}

this would allow:

  • writing complex policies with and/or/not logical predicates
  • decouple platform from measurements (e.g. if in the future azure implements native tdx attestation, we could easily extend support for that)
  • when we have DCAP verification implemented, it could be easily plugged into DcapPlatform

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions