1use core::mem;
2
3use alloc::borrow::ToOwned;
4use alloc::string::{String, ToString};
5use alloc::vec::Vec;
6use ciborium::{ser, Value};
7use coset::{iana, AsCborValue, CoseKeyBuilder, CoseSign1, CoseSign1Builder, HeaderBuilder};
8use ecdsa::{elliptic_curve::sec1::ToEncodedPoint, signature::Signer};
9use key_derivation::{derive_p256_key, derive_p384_key, generate_seed};
10use p384::ecdsa::Signature as P384Signature;
11use sha2::{Digest, Sha256, Sha384, Sha512};
12use tinyvec::ArrayVec;
13
14use crate::utils::token_tag;
15use crate::{utils, HWHash, HWSymmetricKey, Measurement, MeasurementType};
16
17#[derive(Copy, Clone, Debug)]
19pub enum ECCFamily {
20 SecpR1,
22}
23
24#[derive(Copy, Clone, Debug)]
26pub enum KeyBits {
27 Bits256,
28 Bits384,
29 Bits521,
31}
32
33#[derive(Copy, Clone, Debug)]
35pub enum HashAlgo {
36 Sha256,
37 Sha384,
38 Sha512,
39}
40
41impl HashAlgo {
42 pub fn len(self) -> usize {
44 match self {
45 HashAlgo::Sha256 => 32,
46 HashAlgo::Sha384 => 48,
47 HashAlgo::Sha512 => 64,
48 }
49 }
50}
51
52impl Into<String> for HashAlgo {
53 fn into(self) -> String {
55 match self {
56 HashAlgo::Sha256 => "sha-256".to_string(),
57 HashAlgo::Sha384 => "sha-384".to_string(),
58 HashAlgo::Sha512 => "sha-512".to_string(),
59 }
60 }
61}
62
63impl Into<String> for MeasurementType {
64 fn into(self) -> String {
66 match self {
67 MeasurementType::Sha256 => "sha-256".to_string(),
68 MeasurementType::Sha384 => "sha-384".to_string(),
69 MeasurementType::Sha512 => "sha-512".to_string(),
70 }
71 }
72}
73
74#[derive(Debug, PartialEq)]
76pub enum AttestationError {
77 InvalidArgument,
82 GenericError,
85 NotSupported,
88}
89
90#[derive(Clone, Debug)]
92pub struct KeyMaterialData {
93 pub hash: HWHash,
95 pub guk: HWSymmetricKey,
97}
98
99#[derive(Clone, Debug)]
101pub struct HWClaims {
102 pub implementation_id: [u8; 32],
103 pub security_lifecycle: u32,
104 pub profile_definition: Option<String>,
105 pub verification_service_url: Option<String>,
106 pub platform_config: ArrayVec<[u8; 32]>,
107}
108
109pub struct DAKInfo {
111 hash_algo: HashAlgo,
113 key_bits: KeyBits,
115 key: Vec<u8>,
117}
118
119type InstanceId = ArrayVec<[u8; 33]>;
120
121struct CPAK {
123 key: p384::SecretKey,
127 instance_id: InstanceId,
130}
131
132pub struct AttestationMgr {
134 cpak: CPAK,
136 derivation_material: KeyMaterialData,
138 claims: HWClaims,
140 dak: Option<DAKInfo>,
142}
143
144pub fn ec_public_key_sec1_to_cose(key: &[u8]) -> Vec<u8> {
146 let p256_sec1_len = 1 + 2 * 32;
147 let p384_sec1_len = 1 + 2 * 48;
148 let p521_sec1_len = 1 + 2 * 66;
149
150 let key_cbor_value = match key.len() {
151 n if n == p256_sec1_len => {
152 let pk = p256::PublicKey::from_sec1_bytes(key).expect("Failed to load p256 sec1 key");
153 let ep = pk.to_encoded_point(false);
154 let x = ep.x().unwrap().to_owned().to_vec();
155 let y = ep.y().unwrap().to_owned().to_vec();
156 let key = CoseKeyBuilder::new_ec2_pub_key(iana::EllipticCurve::P_256, x, y).build();
157 key.to_cbor_value().expect("Failed to encode p256 as CBOR")
158 }
159 n if n == p384_sec1_len => {
160 let pk = p384::PublicKey::from_sec1_bytes(key).expect("Failed to load p384 sec1 key");
161 let ep = pk.to_encoded_point(false);
162 let x = ep.x().unwrap().to_owned().to_vec();
163 let y = ep.y().unwrap().to_owned().to_vec();
164 let key = CoseKeyBuilder::new_ec2_pub_key(iana::EllipticCurve::P_384, x, y).build();
165 key.to_cbor_value().expect("Failed to encode p384 as CBOR")
166 }
167 n if n == p521_sec1_len => {
168 let pk = p521::PublicKey::from_sec1_bytes(key).expect("Failed to load p521 sec1 key");
169 let ep = pk.to_encoded_point(false);
170 let x = ep.x().unwrap().to_owned().to_vec();
171 let y = ep.y().unwrap().to_owned().to_vec();
172 let key = CoseKeyBuilder::new_ec2_pub_key(iana::EllipticCurve::P_521, x, y).build();
173 key.to_cbor_value().expect("Failed to encode p521 as CBOR")
174 }
175 _ => panic!("Wrong sec1 key length"),
176 };
177
178 let mut key_cbor_bytes = Vec::new();
179 ser::into_writer(&key_cbor_value, &mut key_cbor_bytes).expect("Failed to serialize CBOR value");
180 key_cbor_bytes
181}
182
183pub fn calculate_public_key_hash(public_key: &[u8], hash_algo: HashAlgo) -> Vec<u8> {
185 match hash_algo {
186 HashAlgo::Sha256 => Sha256::digest(public_key).to_vec(),
187 HashAlgo::Sha384 => Sha384::digest(public_key).to_vec(),
188 HashAlgo::Sha512 => Sha512::digest(public_key).to_vec(),
189 }
190}
191
192impl AttestationMgr {
193 const CPAK_SEED_LABEL: &'static [u8] = b"BL1_CPAK_SEED_DERIVATION";
194 const DAK_SEED_LABEL: &'static [u8] = b"BL1_DAK_SEED_DERIVATION";
195
196 pub fn calculate_cpak_hash(&self) -> Vec<u8> {
197 calculate_public_key_hash(
198 &self.cpak.key.public_key().to_sec1_bytes(),
199 HashAlgo::Sha256,
200 )
201 }
202
203 pub fn calculate_dak_hash(&self, hash_algo: HashAlgo) -> Vec<u8> {
210 let dak_info = self.dak.as_ref().unwrap();
211 let key_public_sec1 = match dak_info.key_bits {
212 KeyBits::Bits256 => p256::SecretKey::from_slice(&dak_info.key)
213 .unwrap()
214 .public_key()
215 .to_sec1_bytes(),
216 KeyBits::Bits384 => p384::SecretKey::from_slice(&dak_info.key)
217 .unwrap()
218 .public_key()
219 .to_sec1_bytes(),
220 KeyBits::Bits521 => p521::SecretKey::from_slice(&dak_info.key)
221 .unwrap()
222 .public_key()
223 .to_sec1_bytes(),
224 };
225 let key_public_cose = ec_public_key_sec1_to_cose(&key_public_sec1);
226 calculate_public_key_hash(&key_public_cose, hash_algo)
227 }
228
229 fn generate_instance_id(cpak: &p384::SecretKey) -> InstanceId {
230 let hash = calculate_public_key_hash(&cpak.public_key().to_sec1_bytes(), HashAlgo::Sha256);
231
232 let mut instance_id: InstanceId = ArrayVec::new();
233 instance_id.push(0x01);
234 for item in hash {
235 instance_id.push(item)
236 }
237 instance_id
238 }
239
240 pub fn init(key_derivation_material: KeyMaterialData, claims: HWClaims) -> Self {
243 let lcs: u32 = 3;
244 let reprovisioning_bits: u32 = 0;
245 let input = key_derivation_material.hash.as_slice();
246
247 let mut context = Vec::with_capacity(input.len() + mem::size_of::<u32>() * 2);
248 context.extend(input);
249 context.extend(&lcs.to_ne_bytes());
250 context.extend(&reprovisioning_bits.to_ne_bytes());
251
252 let seed = generate_seed(
253 &context,
254 &key_derivation_material.guk,
255 Self::CPAK_SEED_LABEL,
256 );
257 let cpak = derive_p384_key(&seed, None);
258
259 Self {
260 cpak: CPAK {
261 instance_id: Self::generate_instance_id(&cpak).into_iter().collect(),
262 key: cpak,
263 },
264 derivation_material: key_derivation_material,
265 claims,
266 dak: None,
267 }
268 }
269
270 pub fn reset(&mut self) {
272 self.dak = None;
273 }
274
275 pub fn get_delegated_key(
281 &mut self,
282 _ecc_family: ECCFamily,
283 key_bits: KeyBits,
284 hash_algo: HashAlgo,
285 measurements: &[Measurement],
286 ) -> Result<Vec<u8>, AttestationError> {
287 let mut context = Vec::new();
288 context.extend(&self.derivation_material.hash);
289 context.extend(&self.claims.security_lifecycle.to_ne_bytes());
290 context.extend(&0u32.to_ne_bytes());
291
292 let seed = generate_seed(
293 &context,
294 &self.derivation_material.guk,
295 &Self::DAK_SEED_LABEL,
296 );
297
298 let salt = utils::encode_measurements(measurements);
299 let mut salt_bytes: Vec<u8> = Vec::new();
300 ser::into_writer(&salt, &mut salt_bytes).map_err(|_| AttestationError::GenericError)?;
301
302 let dak = match key_bits {
303 KeyBits::Bits256 => derive_p256_key(&seed, Some(&salt_bytes))
304 .to_bytes()
305 .to_vec(),
306 KeyBits::Bits384 => derive_p384_key(&seed, Some(&salt_bytes))
307 .to_bytes()
308 .to_vec(),
309 KeyBits::Bits521 => return Err(AttestationError::NotSupported),
310 };
311
312 self.dak = Some(DAKInfo {
313 hash_algo,
314 key_bits,
315 key: dak.clone(),
316 });
317
318 Ok(dak)
319 }
320
321 fn encode_claims(&self, dak_hash: &[u8], measurements: &[Measurement]) -> Value {
322 let mut map = Vec::with_capacity(9);
323
324 map.push((
325 Value::Integer(token_tag::CCA_PLAT_CHALLENGE.into()),
326 Value::Bytes(dak_hash.to_vec()),
327 ));
328 map.push((
329 Value::Integer(token_tag::CCA_PLAT_INSTANCE_ID.into()),
330 Value::Bytes(self.cpak.instance_id.to_vec()),
331 ));
332 if let Some(profile_definition) = &self.claims.profile_definition {
333 map.push((
334 Value::Integer(token_tag::CCA_PLAT_PROFILE.into()),
335 Value::Text(profile_definition.clone()),
336 ));
337 }
338
339 map.push((
340 Value::Integer(token_tag::CCA_PLAT_SECURITY_LIFECYCLE.into()),
341 Value::Integer((self.claims.security_lifecycle as u32).into()),
342 ));
343 map.push((
344 Value::Integer(token_tag::CCA_PLAT_IMPLEMENTATION_ID.into()),
345 Value::Bytes(self.claims.implementation_id.to_vec()),
346 ));
347 map.push((
348 Value::Integer(token_tag::CCA_PLAT_SW_COMPONENTS.into()),
349 utils::encode_measurements(measurements),
350 ));
351 if let Some(verification_service_url) = &self.claims.verification_service_url {
352 map.push((
353 Value::Integer(token_tag::CCA_PLAT_VERIFICATION_SERVICE.into()),
354 Value::Text(verification_service_url.clone()),
355 ));
356 }
357 map.push((
358 Value::Integer(token_tag::CCA_PLAT_CONFIGURATION.into()),
359 Value::Bytes(self.claims.platform_config.to_vec()),
360 ));
361 map.push((
362 Value::Integer(token_tag::CCA_PLAT_HASH_ALGO_DESC.into()),
363 Value::Text(self.dak.as_ref().unwrap().hash_algo.into()),
364 ));
365 Value::Map(map)
366 }
367
368 fn sign(&self, data: &[u8]) -> Result<Vec<u8>, AttestationError> {
369 let signing_key = p384::ecdsa::SigningKey::from_bytes(&self.cpak.key.to_bytes())
370 .map_err(|_| AttestationError::GenericError)?;
371 let signature: P384Signature = signing_key
372 .try_sign(data)
373 .map_err(|_| AttestationError::GenericError)?;
374 Ok(signature.to_vec())
375 }
376
377 fn verify_dak_hash(&self, dak_pub_hash: &[u8]) -> bool {
378 let DAKInfo { hash_algo, .. } = self.dak.as_ref().unwrap();
379 let calculated_hash = self.calculate_dak_hash(*hash_algo);
380 dak_pub_hash == &calculated_hash[..]
381 }
382
383 pub fn get_platform_token(
390 &mut self,
391 dak_pub_hash: &[u8],
392 measurements: &[Measurement],
393 ) -> Result<CoseSign1, AttestationError> {
394 if self.dak.is_none() {
395 return Err(AttestationError::InvalidArgument);
396 }
397
398 if !self.verify_dak_hash(dak_pub_hash) {
399 return Err(AttestationError::InvalidArgument);
400 }
401
402 let encoded_claims = self.encode_claims(dak_pub_hash, measurements);
403 let mut token = Vec::new();
404 ser::into_writer(&encoded_claims, &mut token).expect("Unable to encode token");
405
406 let protected = HeaderBuilder::new()
407 .algorithm(coset::iana::Algorithm::ES384)
408 .build();
409
410 let mut singning_error = None;
411
412 let sign1 = CoseSign1Builder::new()
413 .protected(protected)
414 .payload(token)
415 .create_signature(b"", |payload| match self.sign(payload) {
416 Ok(sign) => sign,
417 Err(e) => {
418 singning_error = Some(e);
419 Vec::new()
420 }
421 })
422 .build();
423
424 match singning_error {
425 None => Ok(sign1),
426 Some(e) => Err(e),
427 }
428 }
429}
430
431#[cfg(test)]
432mod tests {
433 use core::str::from_utf8;
434
435 use alloc::vec;
436 use ciborium::de;
437
438 use crate::{MeasurementMetaData, SWType, SWVersion, SignerHash, ValueHash};
439
440 use super::*;
441
442 fn key_derivation_material() -> KeyMaterialData {
443 KeyMaterialData {
444 hash: [
445 0xf1, 0x5f, 0x95, 0x3b, 0xe5, 0x0d, 0xad, 0x92, 0xc3, 0xb2, 0xaa, 0x32, 0x97, 0xe6,
446 0xa4, 0xa8, 0xd6, 0x6d, 0x33, 0x63, 0x84, 0x49, 0xec, 0x19, 0x22, 0xb4, 0xa7, 0x92,
447 0x4a, 0x7b, 0x30, 0x22,
448 ]
449 .iter()
450 .cloned()
451 .collect(),
452 guk: [
453 0x01, 0x23, 0x45, 0x67, 0x89, 0x01, 0x23, 0x45, 0x67, 0x89, 0x01, 0x23, 0x45, 0x67,
454 0x89, 0x01, 0x23, 0x45, 0x67, 0x89, 0x01, 0x23, 0x45, 0x67, 0x89, 0x01, 0x23, 0x45,
455 0x67, 0x89, 0x01, 0x23,
456 ]
457 .into(),
458 }
459 }
460
461 fn hw_claims() -> HWClaims {
462 HWClaims {
463 implementation_id: [
464 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB,
465 0xBB, 0xBB, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xDD, 0xDD, 0xDD, 0xDD,
466 0xDD, 0xDD, 0xDD, 0xDD,
467 ],
468 security_lifecycle: 0x4000,
469 profile_definition: Some("tag:arm.com,2023:cca_platform#1.0.0".to_string()),
470 verification_service_url: Some("http://whatever.com".to_string()),
471 platform_config: 0xDEADBEEFu32.to_ne_bytes().iter().cloned().collect(),
472 }
473 }
474
475 fn measurements() -> Vec<Measurement> {
476 let signer_id: SignerHash = ArrayVec::from([
477 0x01, 0x05, 0x01, 0xEF, 0x68, 0x07, 0x88, 0xCC, 0x33, 0x06, 0x54, 0xAB, 0x09, 0x01,
478 0x74, 0x77, 0x49, 0x08, 0x93, 0xA8, 0x01, 0x07, 0xEF, 0x01, 0x83, 0x09, 0x22, 0xCD,
479 0x09, 0x61, 0xB6, 0xFF, 0x01, 0x05, 0x01, 0xEF, 0x68, 0x07, 0x88, 0xCC, 0x33, 0x06,
480 0x54, 0xAB, 0x09, 0x01, 0x74, 0x77, 0x49, 0x08, 0x93, 0xA8, 0x01, 0x07, 0xEF, 0x01,
481 0x83, 0x09, 0x22, 0xCD, 0x09, 0x61, 0xB6, 0xFF,
482 ]);
483
484 let sw_version: SWVersion = from_utf8(&[
485 0x32, 0x35, 0x35, 0x2E, 0x32, 0x35, 0x35, 0x2E, 0x36, 0x35, 0x35, 0x33, 0x35, 0x0,
486 ])
487 .unwrap()
488 .to_string();
489
490 let sw_type: SWType = from_utf8(&[
491 0x4D, 0x45, 0x41, 0x53, 0x55, 0x52, 0x45, 0x44, 0x5F, 0x42, 0x4F, 0x4F, 0x54, 0x5F,
492 0x54, 0x45, 0x53, 0x54, 0x53, 0x0,
493 ])
494 .unwrap()
495 .to_string();
496
497 vec![Measurement {
498 metadata: MeasurementMetaData {
499 signer_id,
500 sw_version,
501 algorithm: MeasurementType::Sha512,
502 sw_type,
503 },
504 value: ValueHash::from([
505 0x8a, 0x66, 0x01, 0xf6, 0x70, 0x74, 0x8b, 0xe2, 0x33, 0xff, 0x5d, 0x75, 0xd7, 0xea,
506 0x89, 0xa8, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0x01, 0x05, 0x01, 0xEF,
507 0x68, 0x07, 0x88, 0xCC, 0x83, 0x09, 0x22, 0xCD, 0x09, 0x61, 0xB6, 0xFF, 0xbb, 0xbb,
508 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0x56, 0x46, 0x58, 0x49, 0x99, 0x31, 0xcf, 0x59,
509 0x7d, 0xbc, 0x3a, 0x4e, 0x68, 0x79, 0x8a, 0x1c,
510 ]),
511 }]
512 }
513
514 #[test]
515 fn token_before_dak_error() {
516 let mut mgr = AttestationMgr::init(key_derivation_material(), hw_claims());
517
518 assert_eq!(
519 mgr.get_platform_token(&[], &[]).unwrap_err(),
520 AttestationError::InvalidArgument
521 );
522 }
523
524 #[test]
525 fn token_bad_dak_hash_value() {
526 let mut mgr = AttestationMgr::init(key_derivation_material(), hw_claims());
527
528 let _dak = mgr
529 .get_delegated_key(ECCFamily::SecpR1, KeyBits::Bits384, HashAlgo::Sha256, &[])
530 .unwrap();
531
532 assert_eq!(
533 mgr.get_platform_token(&[], &[]).unwrap_err(),
534 AttestationError::InvalidArgument
535 );
536 }
537
538 #[test]
539 fn token_bad_dak_hash_algo() {
540 let mut mgr = AttestationMgr::init(key_derivation_material(), hw_claims());
541
542 let dak = mgr
543 .get_delegated_key(ECCFamily::SecpR1, KeyBits::Bits384, HashAlgo::Sha256, &[])
544 .unwrap();
545
546 let key_public_sec1 = p384::SecretKey::from_slice(&dak)
547 .unwrap()
548 .public_key()
549 .to_sec1_bytes();
550 let key_public_cose = ec_public_key_sec1_to_cose(&key_public_sec1);
551 let hash = calculate_public_key_hash(&key_public_cose, HashAlgo::Sha512);
552
553 assert_eq!(
554 mgr.get_platform_token(&hash, &[]).unwrap_err(),
555 AttestationError::InvalidArgument
556 );
557 }
558
559 #[test]
560 fn token_sign1_verify() {
561 let key_derivation_material = key_derivation_material();
562 let claims = hw_claims();
563 let boot_measurements = measurements();
564 let hash_algo = HashAlgo::Sha256;
565
566 let mut mgr = AttestationMgr::init(key_derivation_material.clone(), claims.clone());
567 let dak = mgr
568 .get_delegated_key(
569 ECCFamily::SecpR1,
570 KeyBits::Bits384,
571 hash_algo,
572 &boot_measurements,
573 )
574 .unwrap();
575
576 let key_public_sec1 = p384::SecretKey::from_slice(&dak)
577 .unwrap()
578 .public_key()
579 .to_sec1_bytes();
580 let key_public_cose = ec_public_key_sec1_to_cose(&key_public_sec1);
581 let hash = calculate_public_key_hash(&key_public_cose, hash_algo);
582
583 let token_sign1 = mgr.get_platform_token(&hash, &boot_measurements).unwrap();
584
585 assert!(token_sign1
586 .verify_signature(&[], |sig, data| {
587 (mgr.sign(data).unwrap() == sig).then_some(()).ok_or(())
588 })
589 .is_ok());
590 }
591
592 fn claims_occurence_vector() -> Vec<(u32, bool)> {
593 let occurence_vec = vec![
594 (token_tag::CCA_PLAT_CHALLENGE, false),
595 (token_tag::CCA_PLAT_INSTANCE_ID, false),
596 (token_tag::CCA_PLAT_SECURITY_LIFECYCLE, false),
597 (token_tag::CCA_PLAT_IMPLEMENTATION_ID, false),
598 (token_tag::CCA_PLAT_SW_COMPONENTS, false),
599 (token_tag::CCA_PLAT_PROFILE, false),
600 (token_tag::CCA_PLAT_VERIFICATION_SERVICE, false),
601 (token_tag::CCA_PLAT_CONFIGURATION, false),
602 (token_tag::CCA_PLAT_HASH_ALGO_DESC, false),
603 ];
604
605 assert_eq!(occurence_vec.len(), 9);
606
607 occurence_vec
608 }
609
610 fn mark_occurence(vec: &mut Vec<(u32, bool)>, occured_tag: u32) {
611 let (_, tag_occurence) = vec
612 .iter_mut()
613 .find(|&&mut (tag, _)| tag == occured_tag)
614 .unwrap();
615 *tag_occurence = true;
616 }
617
618 fn verify_occurence(vec: &Vec<(u32, bool)>) -> bool {
619 !vec.iter()
620 .find(|&&(_, occurence)| occurence == false)
621 .is_some()
622 }
623
624 #[test]
625 fn token_decode_verify() {
626 let key_derivation_material = key_derivation_material();
627 let claims = hw_claims();
628 let measurements = measurements();
629 let hash_algo = HashAlgo::Sha256;
630
631 let mut mgr = AttestationMgr::init(key_derivation_material.clone(), claims.clone());
632 let dak = mgr
633 .get_delegated_key(
634 ECCFamily::SecpR1,
635 KeyBits::Bits384,
636 hash_algo,
637 &measurements,
638 )
639 .unwrap();
640
641 let key_public_sec1 = p384::SecretKey::from_slice(&dak)
642 .unwrap()
643 .public_key()
644 .to_sec1_bytes();
645 let key_public_cose = ec_public_key_sec1_to_cose(&key_public_sec1);
646 let hash = calculate_public_key_hash(&key_public_cose, hash_algo);
647
648 let token_sign1 = mgr.get_platform_token(&hash, &measurements).unwrap();
649 let payload = de::from_reader(&token_sign1.payload.unwrap()[..])
650 .expect("CoseSign1 is not a cbor Value");
651
652 let token_map = match payload {
653 Value::Map(platform_token_map) => platform_token_map,
654 _ => panic!("CoseSign1 payload is not a map!"),
655 };
656
657 let mut occurence_vec = claims_occurence_vector();
658
659 for (tag_value, value) in token_map {
660 let tag: u32 = match tag_value {
661 Value::Integer(tag_integer) => tag_integer.try_into().unwrap(),
662 _ => panic!("Tag is incorrect"),
663 };
664
665 match tag {
666 token_tag::CCA_PLAT_CHALLENGE => {
667 if let Value::Bytes(dak_hash) = value {
668 assert_eq!(dak_hash, hash);
669 } else {
670 panic!("CCA_PLAT_CHALLENGE incorrect");
671 }
672 }
673 token_tag::CCA_PLAT_CONFIGURATION => {
674 if let Value::Bytes(platform_config) = value {
675 assert_eq!(&platform_config[..], &claims.platform_config[..]);
676 } else {
677 panic!("CCA_PLAT_CONFIGURATION incorrect");
678 }
679 }
680 token_tag::CCA_PLAT_INSTANCE_ID => {
681 if let Value::Bytes(instance_id) = value {
682 assert_eq!(instance_id[0], 0x01);
683 assert_eq!(
684 instance_id[1..],
685 calculate_public_key_hash(
686 &mgr.cpak.key.public_key().to_sec1_bytes(),
687 HashAlgo::Sha256
688 )
689 );
690 } else {
691 panic!("CCA_PLAT_INSTANCE_ID incorrect");
692 }
693 }
694 token_tag::CCA_PLAT_PROFILE => {
695 if let Value::Text(profile) = value {
696 assert_eq!(profile, *claims.profile_definition.as_ref().unwrap());
697 } else {
698 panic!("CCA_PLAT_PROFILE incorrect");
699 }
700 }
701 token_tag::CCA_PLAT_SECURITY_LIFECYCLE => {
702 if let Value::Integer(security_lifecycle) = value {
703 let value_u32: u32 = security_lifecycle.try_into().unwrap();
704 assert_eq!(value_u32, claims.security_lifecycle as u32);
705 } else {
706 panic!("CCA_PLAT_PROFILE incorrect");
707 }
708 }
709 token_tag::CCA_PLAT_IMPLEMENTATION_ID => {
710 if let Value::Bytes(implementation_id) = value {
711 assert_eq!(implementation_id, &claims.implementation_id);
712 } else {
713 panic!("CCA_PLAT_IMPLEMENTATION_ID incorrect");
714 }
715 }
716 token_tag::CCA_PLAT_HASH_ALGO_DESC => {
717 if let Value::Text(algo_desc) = value {
718 let claim_desc: String = mgr.dak.as_ref().unwrap().hash_algo.into();
719 assert_eq!(algo_desc, claim_desc);
720 } else {
721 panic!("CCA_PLAT_HASH_ALGO_DESC incorrect");
722 }
723 }
724 token_tag::CCA_PLAT_VERIFICATION_SERVICE => {
725 if let Value::Text(verficiation_service) = value {
726 assert_eq!(
727 verficiation_service,
728 *claims.verification_service_url.as_ref().unwrap()
729 );
730 }
731 }
732 token_tag::CCA_PLAT_SW_COMPONENTS => {
733 if let Value::Array(measurements_array) = value {
734 for measurement_map in measurements_array {
736 if let Value::Map(measurement) = measurement_map {
737 for (tag_value, value) in measurement {
738 let tag: u32 = match tag_value {
739 Value::Integer(tag_integer) => {
740 tag_integer.try_into().unwrap()
741 }
742 _ => panic!("SW COMP map tag not an Integer"),
743 };
744 match tag {
745 token_tag::CCA_SW_COMP_HASH_ALGORITHM => {
746 if let Value::Text(algorithm) = value {
747 let claim_desc: String =
748 measurements[0].metadata.algorithm.into();
749 assert_eq!(algorithm, claim_desc);
750 } else {
751 panic!("CCA_SW_COMP_HASH_ALGORITHM incorrect");
752 }
753 }
754 token_tag::CCA_SW_COMP_TITLE => {
755 if let Value::Text(title) = value {
756 assert_eq!(title, measurements[0].metadata.sw_type);
757 } else {
758 panic!("CCA_SW_COMP_TITLE incorrect");
759 }
760 }
761 token_tag::CCA_SW_COMP_SIGNER_ID => {
762 if let Value::Bytes(signer_id) = value {
763 assert_eq!(
764 &signer_id[..],
765 &measurements[0].metadata.signer_id[..]
766 );
767 } else {
768 panic!("CCA_SW_COMP_SINGER_ID incorrect");
769 }
770 }
771 token_tag::CCA_SW_COMP_VERSION => {
772 if let Value::Text(version) = value {
773 assert_eq!(
774 version,
775 measurements[0].metadata.sw_version
776 );
777 } else {
778 panic!("CCA_SW_COMP_VERSION incorrect");
779 }
780 }
781 token_tag::CCA_SW_COMP_MEASUREMENT_VALUE => {
782 if let Value::Bytes(measurement_value) = value {
783 assert_eq!(
784 measurement_value,
785 &measurements[0].value[..]
786 );
787 } else {
788 panic!("CCA_SW_COMP_MEASUREMENT_VALUE incorrect");
789 }
790 }
791 _ => panic!("Invalid SW COMP tag value: {}", tag),
792 }
793 }
794 }
795 }
796 }
797 }
798 _ => panic!("Invalid tag value: {}", tag),
799 }
800 mark_occurence(&mut occurence_vec, tag);
801 }
802
803 assert!(verify_occurence(&occurence_vec));
804 }
805}