1use base64::{engine::general_purpose::STANDARD, Engine};
15use core::convert::TryInto;
16use p384::ecdsa::{Signature, VerifyingKey};
17use rsa::signature::Verifier;
18use rustls::{server::AllowAnyAuthenticatedClient, Certificate, RootCertStore};
19use std::collections::BTreeMap;
20use thiserror::Error;
21use tracing::info;
22
23use x509_cert::der::Decode;
24use x509_cert::der::Encode;
25
26#[derive(Debug, Error)]
27pub enum VerificationError {
28 #[error("Invalid nonce")]
29 InvalidNonce,
30 #[error("Invalid PCR {0}")]
31 InvalidPCR(usize),
32 #[error("X509 certificate verification failed: {0}")]
33 X509CertVerificationFailed(String),
34 #[error("Signature verification failed: {0}")]
35 SignatureVerificationFailed(String),
36 #[error("Failed to decode trusted root: {0}")]
37 FailedToDecodeTrustedRoot(base64::DecodeError),
38 #[error("Payload length bytes conversion failed: {0}")]
39 PayloadLengthBytesConversionFailed(core::num::TryFromIntError),
40 #[error("Decode X509 certificate failed: {0}")]
41 DecodeX509CertFailed(String),
42 #[error("Public key DER failed: {0}")]
43 PublicKeyDerFailed(String),
44 #[error("Invalid public key: {0}")]
45 InvalidPublicKey(String),
46 #[error("Failed to add trusted root cert: {0}")]
47 FailedToAddTrustedRootCert(String),
48}
49
50#[derive(Debug, Error)]
51pub enum ParseError {
52 #[error("Parse document failed: {0}")]
53 ParseDocumentFailed(String),
54 #[error("Parse payload failed: {0}")]
55 ParsePayloadFailed(String),
56}
57
58#[derive(Debug, Error)]
59pub enum ParseVerificationError {
60 #[error("Parse error: {0}")]
61 ParseError(ParseError),
62 #[error("Verification error: {0}")]
63 VerificationError(VerificationError),
64}
65
66#[derive(Debug)]
67pub struct AttestationDocument {
68 pub protected: Vec<u8>,
69 pub signature: Vec<u8>,
70 pub payload: Vec<u8>,
71}
72
73const AWS_TRUSTED_ROOT_CERT: &str = "MIICETCCAZagAwIBAgIRAPkxdWgbkK/hHUbMtOTn+FYwCgYIKoZIzj0EAwMwSTELMAkGA1UEBhMCVVMxDzANBgNVBAoMBkFtYXpvbjEMMAoGA1UECwwDQVdTMRswGQYDVQQDDBJhd3Mubml0cm8tZW5jbGF2ZXMwHhcNMTkxMDI4MTMyODA1WhcNNDkxMDI4MTQyODA1WjBJMQswCQYDVQQGEwJVUzEPMA0GA1UECgwGQW1hem9uMQwwCgYDVQQLDANBV1MxGzAZBgNVBAMMEmF3cy5uaXRyby1lbmNsYXZlczB2MBAGByqGSM49AgEGBSuBBAAiA2IABPwCVOumCMHzaHDimtqQvkY4MpJzbolL//Zy2YlES1BR5TSksfbb48C8WBoyt7F2Bw7eEtaaP+ohG2bnUs990d0JX28TcPQXCEPZ3BABIeTPYwEoCWZEh8l5YoQwTcU/9KNCMEAwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUkCW1DdkFR+eWw5b6cp3PmanfS5YwDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMDA2kAMGYCMQCjfy+Rocm9Xue4YnwWmNJVA44fA0P5W2OpYow9OYCVRaEevL8uO1XYru5xtMPWrfMCMQCi85sWBbJwKKXdS6BptQFuZbT73o/gBh1qUxl/nNr12UO8Yfwr6wPLb+6NIwLz3/Y=";
74
75#[derive(Debug)]
76pub struct Payload {
77 pub module_id: String,
78 pub timestamp: u64,
79 pub public_key: Vec<u8>,
80 pub certificate: Vec<u8>,
81 pub cabundle: Vec<Vec<u8>>,
82 pub nonce: Vec<u8>,
83 pub user_data: Option<Vec<u8>>,
84 pub digest: String,
85 pub pcrs: Vec<Vec<u8>>,
86}
87
88fn verify_x509_cert(
89 trusted_root: Vec<u8>,
90 cabundle: Vec<Vec<u8>>,
91 certificate: Vec<u8>,
92 unix_time: u64,
93) -> Result<(), VerificationError> {
94 let mut certs: Vec<Certificate> = Vec::new();
95 for this_cert in cabundle.clone().iter().rev() {
96 let cert = Certificate(this_cert.to_vec());
97 certs.push(cert);
98 }
99 let cert = Certificate(certificate.clone());
100 certs.push(cert.clone());
101
102 let mut root_store = RootCertStore::empty();
103 root_store
104 .add(&Certificate(trusted_root.clone()))
105 .map_err(|err| VerificationError::FailedToAddTrustedRootCert(err.to_string()))?;
106
107 let verifier = AllowAnyAuthenticatedClient::new(root_store);
108
109 info!("verifying client cert");
110
111 let duration = std::time::Duration::from_secs(unix_time);
113 let datetime = std::time::UNIX_EPOCH + duration;
114 let _verified = verifier
115 .verify_client_cert(&cert, &certs, datetime)
116 .map_err(|err| VerificationError::X509CertVerificationFailed(err.to_string()))?;
117 Ok(())
118}
119
120fn verify_remote_attestation_signature(
121 protected: Vec<u8>,
122 signature: Vec<u8>,
123 certificate: Vec<u8>,
124 payload: Vec<u8>,
125) -> Result<(), VerificationError> {
126 let cert = x509_cert::Certificate::from_der(&certificate)
127 .map_err(|err| VerificationError::DecodeX509CertFailed(err.to_string()))?;
128
129 let public_key = cert
130 .tbs_certificate
131 .subject_public_key_info
132 .to_der()
133 .map_err(|err| VerificationError::PublicKeyDerFailed(err.to_string()))?;
134
135 let public_key = &public_key[public_key.len() - 97..];
136 let verifying_key = VerifyingKey::from_sec1_bytes(&public_key)
137 .map_err(|err| VerificationError::InvalidPublicKey(err.to_string()))?;
138
139 let signature = Signature::from_slice(&signature).expect("Invalid signature");
140
141 const HEADER: [u8; 13] = [132, 106, 83, 105, 103, 110, 97, 116, 117, 114, 101, 49, 68];
142
143 let payload_length_bytes: u8 = (payload.len() + 94 - 4446)
144 .try_into()
145 .map_err(|err| VerificationError::PayloadLengthBytesConversionFailed(err))?;
146
147 let filler: [u8; 4] = [64, 89, 17, payload_length_bytes];
148
149 let sign_structure = [
150 HEADER.as_ref(),
151 protected.as_ref(),
152 filler.as_ref(),
153 payload.as_ref(),
154 ]
155 .concat();
156
157 verifying_key
158 .verify(&sign_structure, &signature)
159 .map_err(|err| VerificationError::SignatureVerificationFailed(err.to_string()))?;
160 Ok(())
161}
162
163pub fn verify(
164 attestation_document: AttestationDocument,
165 payload: Payload,
166 nonce: Vec<u8>,
167 pcrs: Vec<Vec<u8>>,
168 trusted_root: Option<Vec<u8>>,
169 unix_time: u64,
170) -> Result<(), VerificationError> {
171 if payload.nonce != nonce {
172 return Err(VerificationError::InvalidNonce);
173 }
174
175 for (i, pcr) in pcrs.iter().enumerate() {
176 if pcr != &vec![0 as u8; 48] && pcr != &payload.pcrs[i] {
177 return Err(VerificationError::InvalidPCR(i));
178 }
179 }
180
181 let trusted_root = match trusted_root {
182 Some(root) => root,
183 None => STANDARD
184 .decode(AWS_TRUSTED_ROOT_CERT)
185 .map_err(|err| VerificationError::FailedToDecodeTrustedRoot(err))?,
186 };
187 verify_x509_cert(
188 trusted_root,
189 payload.cabundle,
190 payload.certificate.clone(),
191 unix_time,
192 )
193 .map_err(|err| VerificationError::X509CertVerificationFailed(err.to_string()))?;
194
195 verify_remote_attestation_signature(
196 attestation_document.protected,
197 attestation_document.signature,
198 payload.certificate,
199 attestation_document.payload,
200 )
201 .map_err(|err| VerificationError::SignatureVerificationFailed(err.to_string()))?;
202
203 Ok(())
204}
205
206pub fn parse_document(document_data: &Vec<u8>) -> Result<AttestationDocument, ParseError> {
207 let cbor: serde_cbor::Value = serde_cbor::from_slice(document_data)
208 .map_err(|err| ParseError::ParseDocumentFailed(err.to_string()))?;
209 let elements = match cbor {
210 serde_cbor::Value::Array(elements) => elements,
211 _ => panic!("AttestationVerifier::parse Unknown field cbor:{:?}", cbor),
212 };
213 let protected = match &elements[0] {
214 serde_cbor::Value::Bytes(prot) => prot,
215 _ => panic!(
216 "AttestationVerifier::parse Unknown field protected:{:?}",
217 elements[0]
218 ),
219 };
220 let _unprotected = match &elements[1] {
221 serde_cbor::Value::Map(unprot) => unprot,
222 _ => panic!(
223 "AttestationVerifier::parse Unknown field unprotected:{:?}",
224 elements[1]
225 ),
226 };
227 let payload = match &elements[2] {
228 serde_cbor::Value::Bytes(payld) => payld,
229 _ => panic!(
230 "AttestationVerifier::parse Unknown field payload:{:?}",
231 elements[2]
232 ),
233 };
234 let signature = match &elements[3] {
235 serde_cbor::Value::Bytes(sig) => sig,
236 _ => panic!(
237 "AttestationVerifier::parse Unknown field signature:{:?}",
238 elements[3]
239 ),
240 };
241 Ok(AttestationDocument {
242 protected: protected.to_vec(),
243 payload: payload.to_vec(),
244 signature: signature.to_vec(),
245 })
246}
247
248pub fn parse_payload(payload: &Vec<u8>) -> Result<Payload, ParseError> {
249 let document_data: serde_cbor::Value = serde_cbor::from_slice(payload.as_slice())
250 .map_err(|err| ParseError::ParsePayloadFailed(err.to_string()))?;
251 let document_map: BTreeMap<serde_cbor::Value, serde_cbor::Value> = match document_data {
252 serde_cbor::Value::Map(map) => map,
253 _ => {
254 return Err(ParseError::ParsePayloadFailed(format!(
255 "AttestationVerifier::parse_payload field ain't what it should be:{:?}",
256 document_data
257 )))
258 }
259 };
260 let module_id = match document_map.get(&serde_cbor::Value::Text(
261 "module_id".try_into().expect("module_id_fail"),
262 )) {
263 Some(serde_cbor::Value::Text(val)) => val.to_string(),
264 _ => {
265 return Err(ParseError::ParsePayloadFailed(format!(
266 "AttestationVerifier::parse_payload module_id is wrong type or not present"
267 )))
268 }
269 };
270 let timestamp: i128 = match document_map.get(&serde_cbor::Value::Text("timestamp".to_string()))
271 {
272 Some(serde_cbor::Value::Integer(val)) => *val,
273 _ => {
274 return Err(ParseError::ParsePayloadFailed(format!(
275 "AttestationVerifier::parse_payload timestamp is wrong type or not present"
276 )))
277 }
278 };
279 let timestamp: u64 = timestamp.try_into().map_err(|err| {
280 ParseError::ParsePayloadFailed(format!(
281 "AttestationVerifier::parse_payload failed to convert timestamp to u64:{:?}",
282 err
283 ))
284 })?;
285 let public_key: Vec<u8> =
286 match document_map.get(&serde_cbor::Value::Text("public_key".to_string())) {
287 Some(serde_cbor::Value::Bytes(val)) => val.to_vec(),
288 Some(_null) => vec![],
289 _ => {
290 return Err(ParseError::ParsePayloadFailed(format!(
291 "AttestationVerifier::parse_payload public_key is wrong type or not present"
292 )))
293 }
294 };
295 let certificate: Vec<u8> =
296 match document_map.get(&serde_cbor::Value::Text("certificate".to_string())) {
297 Some(serde_cbor::Value::Bytes(val)) => val.to_vec(),
298 _ => {
299 return Err(ParseError::ParsePayloadFailed(format!(
300 "AttestationVerifier::parse_payload certificate is wrong type or not present"
301 )))
302 }
303 };
304 let pcrs: Vec<Vec<u8>> = match document_map.get(&serde_cbor::Value::Text("pcrs".to_string())) {
305 Some(serde_cbor::Value::Map(map)) => {
306 let mut ret_vec: Vec<Vec<u8>> = Vec::new();
307 let num_entries: i128 = map.len().try_into().map_err(|err| {
308 ParseError::ParsePayloadFailed(format!(
309 "AttestationVerifier::parse_payload failed to convert pcrs len into i128:{:?}",
310 err
311 ))
312 })?;
313 for x in 0..num_entries {
314 match map.get(&serde_cbor::Value::Integer(x)) {
315 Some(serde_cbor::Value::Bytes(inner_vec)) => {
316 ret_vec.push(inner_vec.to_vec());
317 }
318 _ => {
319 }
324 }
325 }
326 ret_vec
327 }
328 _ => {
329 return Err(ParseError::ParsePayloadFailed(format!(
330 "AttestationVerifier::parse_payload pcrs is wrong type or not present"
331 )))
332 }
333 };
334
335 let nonce = vec![0; 20];
345
346 let user_data: Option<Vec<u8>> =
347 match document_map.get(&serde_cbor::Value::Text("user_data".to_string())) {
348 Some(serde_cbor::Value::Bytes(val)) => Some(val.to_vec()),
349 None => None,
350 Some(_null) => None,
351 };
352 let digest: String = match document_map.get(&serde_cbor::Value::Text("digest".to_string())) {
353 Some(serde_cbor::Value::Text(val)) => val.to_string(),
354 _ => {
355 return Err(ParseError::ParsePayloadFailed(format!(
356 "AttestationVerifier::parse_payload digest is wrong type or not present"
357 )))
358 }
359 };
360 let cabundle: Vec<Vec<u8>> =
361 match document_map.get(&serde_cbor::Value::Text("cabundle".to_string())) {
362 Some(serde_cbor::Value::Array(outer_vec)) => {
363 let mut ret_vec: Vec<Vec<u8>> = Vec::new();
364 for this_vec in outer_vec.iter() {
365 match this_vec {
366 serde_cbor::Value::Bytes(inner_vec) => {
367 ret_vec.push(inner_vec.to_vec());
368 }
369 _ => {
370 return Err(ParseError::ParsePayloadFailed(format!(
371 "AttestationVerifier::parse_payload inner_vec is wrong type"
372 )))
373 }
374 }
375 }
376 ret_vec
377 }
378 _ => {
379 return Err(ParseError::ParsePayloadFailed(format!(
380 "AttestationVerifier::parse_payload cabundle is wrong type or not present:{:?}",
381 document_map.get(&serde_cbor::Value::Text("cabundle".to_string()))
382 )))
383 }
384 };
385 Ok(Payload {
386 module_id,
387 timestamp,
388 public_key,
389 certificate,
390 cabundle,
391 nonce,
392 user_data,
393 digest,
394 pcrs,
395 })
396}
397
398pub fn parse_verify_with(
399 document_data: Vec<u8>,
400 nonce: Vec<u8>,
401 pcrs: Vec<Vec<u8>>,
402 unix_time: u64,
403) -> Result<(), ParseVerificationError> {
404 let attestation_document =
405 parse_document(&document_data).map_err(ParseVerificationError::ParseError)?;
406
407 let payload =
408 parse_payload(&attestation_document.payload).map_err(ParseVerificationError::ParseError)?;
409
410 verify(attestation_document, payload, nonce, pcrs, None, unix_time)
411 .map_err(ParseVerificationError::VerificationError)?;
412 Ok(())
413}
414
415#[cfg(test)]
416mod tests {
417
418 use super::*;
419 use hex;
420 #[test]
421 fn test_verify() {
422 let unix_time = std::time::UNIX_EPOCH.elapsed().unwrap().as_secs();
423 let document_data = STANDARD.decode("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")
428 .expect("decode cbor document failed");
429
430 let mut pcrs = vec![vec![0; 48]; 16];
431 pcrs.insert(
432 2,
433 vec![
434 82, 109, 106, 26, 82, 112, 94, 220, 96, 33, 50, 18, 83, 138, 170, 165, 201, 23,
435 162, 43, 73, 60, 232, 132, 234, 119, 172, 24, 1, 253, 90, 10, 150, 45, 136, 78,
436 242, 58, 104, 123, 48, 108, 67, 123, 146, 152, 255, 65,
437 ]
438 .to_vec(),
439 );
440 let nonce =
441 hex::decode("0000000000000000000000000000000000000000").expect("decode nonce failed");
442
443 let document = parse_document(&document_data).expect("parse document failed");
444
445 let payload = parse_payload(&document.payload).expect("parse payload failed");
446
447 println!("pcrs {:?}", payload.pcrs);
448 println!("nonce {:?}", nonce);
449
450 match parse_verify_with(document_data, nonce, pcrs, unix_time) {
451 Ok(_) => (),
452 Err(e) => panic!("parse_verify_with failed: {:?}", e.to_string()),
453 }
454 }
455}