use std::{borrow::Cow, fmt};
use lexe_crypto::ed25519;
use lexe_enclave::enclave;
use lexe_hex::hex;
use yasna::models::ObjectIdentifier;
use crate::attest_client::quote::ReportData;
#[derive(Eq, PartialEq)]
pub struct SgxAttestationExtension<'quote> {
pub quote: Cow<'quote, [u8]>,
}
impl SgxAttestationExtension<'_> {
pub const OID: &'static [u64] = &[1, 2, 840, 113741, 1337, 7];
pub const OID_DER: &'static [u8] = &[
0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF8, 0x4D, 0x8A, 0x39, 0x07,
];
pub fn oid_yasna() -> ObjectIdentifier {
ObjectIdentifier::from_slice(Self::OID)
}
#[rustfmt::skip]
pub const fn oid_asn1_rs() -> asn1_rs::Oid<'static> {
asn1_rs::oid!(1.2.840.113741.1337.7)
}
pub const fn is_critical() -> bool {
false
}
pub fn to_der_bytes(&self) -> Vec<u8> {
yasna::construct_der(|writer| {
writer.write_sequence(|writer| {
writer.next().write_bytes(&self.quote);
})
})
}
pub fn to_cert_extension(&self) -> rcgen::CustomExtension {
let mut ext = rcgen::CustomExtension::from_oid_content(
Self::OID,
self.to_der_bytes(),
);
ext.set_criticality(Self::is_critical());
ext
}
}
impl SgxAttestationExtension<'static> {
pub fn dummy(cert_pk: &ed25519::PublicKey) -> Self {
let mut report = enclave::report().clone();
let report_data = ReportData::from_cert_pk(cert_pk);
report.reportdata = report_data.into_inner();
Self {
quote: Cow::Owned(AsRef::<[u8]>::as_ref(&report).to_owned()),
}
}
pub fn from_der_bytes(buf: &[u8]) -> yasna::ASN1Result<Self> {
yasna::parse_der(buf, |reader| {
reader.read_sequence(|reader| {
let quote = reader.next().read_bytes()?;
Ok(Self {
quote: Cow::Owned(quote),
})
})
})
}
}
impl fmt::Debug for SgxAttestationExtension<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("SgxAttestationExtension")
.field("quote", &hex::display(&self.quote))
.finish()
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_sgx_attestation_ext_oid_der_bytes() {
let oid = SgxAttestationExtension::oid_yasna();
let oid_der = yasna::encode_der(&oid);
assert_eq!(SgxAttestationExtension::OID_DER, &oid_der);
}
#[test]
fn test_sgx_attestation_ext_serde() {
let ext = SgxAttestationExtension {
quote: b"test".as_slice().into(),
};
let der_bytes = ext.to_der_bytes();
let ext2 = SgxAttestationExtension::from_der_bytes(&der_bytes).unwrap();
assert_eq!(ext, ext2);
let der_bytes2 = ext2.to_der_bytes();
assert_eq!(der_bytes, der_bytes2);
assert_eq!(b"test".as_slice(), ext2.quote.as_ref());
}
}