Skip to content

Instantly share code, notes, and snippets.

@Vinc0682
Last active August 8, 2023 17:42
Show Gist options
  • Save Vinc0682/10c074202c995e4f87b4edf278ec4cae to your computer and use it in GitHub Desktop.
Save Vinc0682/10c074202c995e4f87b4edf278ec4cae to your computer and use it in GitHub Desktop.
rust-sgx local attestation made easy
use sgx_isa::Targetinfo;
use sgx_isa::Report;
use sgx_isa::Keyname;
use sgx_isa::Keyrequest;
use crypto_mac::Mac;
use cmac::Cmac;
use aes::Aes128;
pub struct Attestation;
impl Attestation {
/// Fetches the own target info and puts it into a byte-vector.
pub fn get_own_targetinfo() -> Vec<u8> {
let ti = Targetinfo::from(Report::for_self());
let result: &[u8] = ti.as_ref();
result.to_vec().clone()
}
/// Tries to create a report for the given target and puts it into a byte-vector.
/// Returns None if the target is invalid, returns the report otherwise.
pub fn locally_attest(target: &Vec<u8>, data: &[u8;64]) -> Option<Vec<u8>> {
let ti = Targetinfo::try_copy_from(&target[..])?;
let report = Report::for_target(&ti, data);
let report: &[u8] = report.as_ref();
Some(report.to_vec().clone())
}
/// Verifies a report created by locally_attest (or any other report generated by an enclave).
/// Returns true if the report is correctly formed and has been generated on the same machine/CPU
/// as the current enclave.
pub fn verify_local_attest(report: &Vec<u8>) -> bool {
if report.len() != Report::UNPADDED_SIZE {
return false;
}
// Can unwrap since the length is verified
let report = Report::try_copy_from(&report[..]).unwrap();
Self::verify_report(&report)
}
/// Verifies the given report locally, a.k.a. returns true if the Report was created in an enclave
/// on the same CPU.
pub fn verify_report(report: &Report) -> bool {
// Derive the report key.
let request = Keyrequest {
keyname: Keyname::Report as _,
keyid: report.keyid.clone(),
..Default::default()
};
// Maybe result false instead of panicking, but the specs
// ( https://software.intel.com/en-us/articles/intel-sdm Volume 3C, Chapter 40-4 )
// state that EGETKEY should have a problem with this parameters, so if it doesn't work
// there might be a deeper issue making a panic appropriate.
let key = request.egetkey().expect("Can't derive report key");
// Extract the data that is signed.
let report_data: &[u8] = report.as_ref();
let mut mac_data = &report_data[0..Report::UNPADDED_SIZE-48];
// Compute and verify the mac on the data.
let mut mac = Cmac::<Aes128>::new_varkey(&key[..]).unwrap();
mac.input(&mut mac_data);
mac.verify(&report.mac).is_ok()
}
}
[dependencies]
sgx-isa = { version = "0.2", features = ["sgxstd"] }
# RustCrypto, used for CMAC
cmac = "0.2.0"
crypto-mac = "0.7.0"
aes = "0.3.2"
block-cipher-trait = "0.6.2"
generic-array = "0.12"
use crate::attestation::Attestation;
mod attestation;
fn main() {
// Generate report on the fly
let ti = Attestation::get_own_targetinfo();
println!("Target info: {:x?}", ti);
let mut report = Attestation::locally_attest(&ti, &[0u8; 64])
.expect("Could not attest for own target info.");
println!("Report: {:x?}", report);
// Report should be invalid when uncommented:
//report[0] ^= 1u8;
println!("Valid: {}", Attestation::verify_local_attest(&report));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment