underhill_attestation/igvm_attest/
ak_cert.rs1use crate::igvm_attest::Error as CommonError;
7use crate::igvm_attest::parse_response_header;
8
9use thiserror::Error;
10
11#[derive(Debug, Error)]
13pub enum AkCertError {
14 #[error(
15 "AK cert response is too small to parse. Found {size} bytes but expected at least {minimum_size}"
16 )]
17 SizeTooSmall { size: usize, minimum_size: usize },
18 #[error(
19 "AK cert response size {specified_size} specified in the header is larger then the actual size {size}"
20 )]
21 SizeMismatch { size: usize, specified_size: usize },
22 #[error(
23 "AK cert response header version {version} does match the expected version {expected_version}"
24 )]
25 HeaderVersionMismatch { version: u32, expected_version: u32 },
26 #[error("error in parsing response header")]
27 ParseHeader(#[source] CommonError),
28}
29
30pub fn parse_response(response: &[u8]) -> Result<Vec<u8>, AkCertError> {
34 use openhcl_attestation_protocol::igvm_attest::get::IGVM_ATTEST_RESPONSE_VERSION_1;
35 use openhcl_attestation_protocol::igvm_attest::get::IgvmAttestAkCertResponseHeader;
36 use openhcl_attestation_protocol::igvm_attest::get::IgvmAttestCommonResponseHeader;
37
38 let header = parse_response_header(response).map_err(AkCertError::ParseHeader)?;
39
40 let header_size = match header.version {
43 IGVM_ATTEST_RESPONSE_VERSION_1 => size_of::<IgvmAttestCommonResponseHeader>(),
44 _ => size_of::<IgvmAttestAkCertResponseHeader>(),
45 };
46
47 Ok(response[header_size..header.data_size as usize].to_vec())
48}
49
50#[cfg(test)]
51mod tests {
52 use super::*;
53 use openhcl_attestation_protocol::igvm_attest::get::IgvmAttestAkCertResponseHeader;
54 use openhcl_attestation_protocol::igvm_attest::get::IgvmAttestCommonResponseHeader;
55 use zerocopy::FromBytes;
56
57 #[test]
58 fn test_undersized_response() {
59 const HEADER_SIZE: usize = size_of::<IgvmAttestAkCertResponseHeader>();
60 let properly_sized_response: [u8; HEADER_SIZE] = [1; HEADER_SIZE];
61 let undersized_response = &properly_sized_response[..HEADER_SIZE - 1];
62
63 let result = parse_response(&[]);
65 assert!(result.is_err());
66 assert_eq!(
67 result.unwrap_err().to_string(),
68 AkCertError::ParseHeader(CommonError::ResponseSizeTooSmall { response_size: 0 })
69 .to_string()
70 );
71
72 let undersized_parse_ = parse_response(undersized_response);
74 assert!(undersized_parse_.is_err());
75 assert_eq!(
76 undersized_parse_.unwrap_err().to_string(),
77 AkCertError::ParseHeader(CommonError::ResponseSizeTooSmall {
78 response_size: HEADER_SIZE - 1
79 })
80 .to_string()
81 );
82
83 let properly_sized_parse = parse_response(&properly_sized_response);
86 assert!(
87 !properly_sized_parse
88 .unwrap_err()
89 .to_string()
90 .starts_with("AK cert response is too small to parse"),
91 );
92 }
93
94 #[test]
95 fn test_valid_response_size_match() {
96 const VALID_RESPONSE: [u8; 56] = [
97 0x38, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x30, 0x82, 0x03, 0xeb, 0x30, 0x82,
98 0x02, 0xd3, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0x3b, 0xa3, 0x33, 0x97, 0xef,
99 0x2f, 0x9e, 0xef, 0xbd, 0x35, 0x5e, 0xda, 0xdd, 0x27, 0x38, 0x42, 0x30, 0x0d, 0x06,
100 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x25,
101 ];
102
103 const HEADER_SIZE: usize = size_of::<IgvmAttestCommonResponseHeader>();
104 let result = IgvmAttestAkCertResponseHeader::read_from_prefix(&VALID_RESPONSE);
105 assert!(result.is_ok());
106
107 let result = parse_response(&VALID_RESPONSE);
108 assert!(result.is_ok());
109
110 let payload = result.unwrap();
111 let data_size = parse_response_header(&VALID_RESPONSE).unwrap().data_size as usize;
112 assert_eq!(payload.len(), data_size - HEADER_SIZE);
113 assert_eq!(payload, &VALID_RESPONSE[HEADER_SIZE..data_size]);
114 }
115
116 #[test]
117 fn test_valid_response_size_smaller_than_specified() {
118 const VALID_RESPONSE: [u8; 56] = [
119 0x37, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x30, 0x82, 0x03, 0xeb, 0x30, 0x82,
120 0x02, 0xd3, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0x3b, 0xa3, 0x33, 0x97, 0xef,
121 0x2f, 0x9e, 0xef, 0xbd, 0x35, 0x5e, 0xda, 0xdd, 0x27, 0x38, 0x42, 0x30, 0x0d, 0x06,
122 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x25,
123 ];
124
125 const HEADER_SIZE: usize = size_of::<IgvmAttestCommonResponseHeader>();
126
127 let result = IgvmAttestAkCertResponseHeader::read_from_prefix(&VALID_RESPONSE);
128 assert!(result.is_ok());
129
130 let result = parse_response(&VALID_RESPONSE);
131 assert!(result.is_ok());
132
133 let payload = result.unwrap();
134 let data_size = parse_response_header(&VALID_RESPONSE).unwrap().data_size as usize;
135 assert_eq!(payload.len(), data_size - HEADER_SIZE);
136 assert_eq!(payload, &VALID_RESPONSE[HEADER_SIZE..data_size]);
137 }
138}