1#[macro_use]
2extern crate nom;
3
4use nom::{error::ErrorKind, Err};
5
6mod parsers;
7
8#[derive(Debug, Clone, PartialEq)]
9pub struct Quote<'a> {
10 pub header: Header<'a>,
11 pub isv_report: ReportBody<'a>,
12 pub signature: Signature<'a>,
13 signed_message: &'a [u8],
14}
15
16impl<'a> Quote<'a> {
19 pub fn parse(quote_bytes: &'a [u8]) -> Result<Self, Err<(&'a [u8], ErrorKind)>> {
20 crate::parsers::parse_quote(quote_bytes).map(|qp| qp.1)
21 }
22
23 pub fn signed_message(&self) -> &[u8] {
25 &self.signed_message
26 }
27}
28
29#[derive(Debug, Clone, PartialEq)]
30pub struct Header<'a> {
31 pub version: u16,
32 pub qe_svn: u16,
33 pub pce_svn: u16,
34 pub qe_vendor_id: &'a [u8],
35 pub user_data: &'a [u8],
36}
37
38#[derive(Debug, Clone, PartialEq)]
39pub enum Signature<'a> {
40 EcdsaP256 {
41 isv_report_signature: &'a [u8],
42 attestation_key: &'a [u8],
43 qe_report: ReportBody<'a>,
44 qe_report_signature: &'a [u8],
45 qe_authentication_data: &'a [u8],
46 qe_certification_data: QeCertificationData<'a>,
47 },
48}
49
50#[derive(Debug, Clone, PartialEq)]
51pub struct ReportBody<'a> {
52 pub cpu_svn: &'a [u8],
53 pub miscselect: u32,
54 pub attributes: &'a [u8],
55 pub mrenclave: &'a [u8],
56 pub mrsigner: &'a [u8],
57 pub isv_prod_id: u16,
58 pub isv_svn: u16,
59 pub report_data: &'a [u8],
60 signed_message: &'a [u8],
61}
62
63impl<'a> ReportBody<'a> {
64 pub fn signed_message(&self) -> &[u8] {
65 &self.signed_message
66 }
67}
68
69#[derive(Debug, Clone, PartialEq)]
70pub enum QeCertificationData<'a> {
71 Ppid {
72 ppid: Ppid<'a>,
73 cpu_svn: &'a [u8],
74 pce_svn: u16,
75 pce_id: u16,
76 },
77 CertChain(&'a [u8]),
78}
79
80#[derive(Debug, Clone, PartialEq)]
81pub enum Ppid<'a> {
82 Clear(&'a [u8]),
83 Enc2048(&'a [u8]),
84 Enc3072(&'a [u8]),
85}
86
87#[cfg(test)]
88mod tests {
89 use super::*;
90
91 static V2_QUOTE: &[u8] = include_bytes!("../fixtures/v2_quote.bin");
92
93 #[test]
94 fn test_parse_v2_quote() {
95 assert!(Quote::parse(V2_QUOTE).is_ok());
96 }
97}