islet_rmm/rsi/attestation/
claims.rs1use core::fmt::Debug;
2
3use alloc::{
4 string::{String, ToString},
5 vec::Vec,
6};
7use ciborium::Value;
8use tinyvec::ArrayVec;
9
10use crate::cose;
11use crate::measurement::{Measurement, MEASUREMENTS_SLOT_NR, MEASUREMENTS_SLOT_RIM};
12
13pub const CHALLENGE_LABEL: u64 = 10;
14pub const PROFILE_LABEL: u64 = 265;
15pub const PERSONALIZATION_VALUE_LABEL: u64 = 44235;
16pub const INITIAL_MEASUREMENT_LABEL: u64 = 44238;
17pub const EXTENSIBLE_MEASUREMENTS_LABEL: u64 = 44239;
18pub const HASH_ALGO_ID_LABEL: u64 = 44236;
19pub const PUBLIC_KEY_LABEL: u64 = 44237;
20pub const PUBLIC_KEY_HASH_ALOG_ID_LABEL: u64 = 44240;
21
22pub const REALM_PROFILE: &str = "tag:arm.com,2023:realm#1.0.0";
23
24#[derive(Clone, Copy, Debug, Default)]
25pub struct MeasurementEntry(Measurement, usize);
26
27#[derive(Clone, Debug)]
28pub struct Data<T: Default, const N: usize>(ArrayVec<[T; N]>);
29
30impl<T: Copy + Default, const N: usize> Data<T, N> {
31 pub fn from_slice(slice: &[T]) -> Self {
32 Data(slice.iter().cloned().collect())
33 }
34}
35
36pub const REM_SLOT_NR: usize = MEASUREMENTS_SLOT_NR - 1;
37
38pub type Challenge = Data<u8, 64>;
39pub type Profile = String;
40pub type PersonalizationValue = Data<u8, 64>;
41pub type REMs = Data<MeasurementEntry, REM_SLOT_NR>;
42pub type RIM = MeasurementEntry;
43pub type HashAlgo = String;
44pub type RAKPubKey = Vec<u8>;
45
46#[derive(Clone, Debug)]
47pub struct Claim<T> {
48 value: T,
49 label: u64,
50}
51
52impl<T: Into<Value>> From<Claim<T>> for (Value, Value) {
53 fn from(value: Claim<T>) -> Self {
54 (Value::Integer(value.label.into()), value.value.into())
55 }
56}
57
58impl From<MeasurementEntry> for Value {
59 fn from(value: MeasurementEntry) -> Self {
60 Value::Bytes(value.0.as_ref()[..value.1].to_vec())
61 }
62}
63
64impl<const N: usize> From<Data<u8, N>> for Value {
65 fn from(value: Data<u8, N>) -> Self {
66 Value::Bytes(value.0.to_vec())
67 }
68}
69
70impl<T: Into<Value>, const N: usize> From<Data<T, N>> for Value
71where
72 T: Default,
73{
74 default fn from(value: Data<T, N>) -> Self {
75 let mut array = Vec::new();
76 for el in value.0.into_iter() {
77 array.push(el.into());
78 }
79 array.into()
80 }
81}
82
83#[derive(Clone, Debug)]
84pub struct RealmClaims {
85 pub challenge: Claim<Challenge>,
86 pub profile: Claim<Profile>,
87 pub personalization_value: Claim<PersonalizationValue>,
88 pub rim: Claim<RIM>,
89 pub rems: Claim<REMs>,
90 pub measurement_hash_algo: Claim<HashAlgo>,
91 pub rak_pub: Claim<RAKPubKey>,
92 pub rak_pub_hash_algo: Claim<HashAlgo>,
93}
94
95impl RealmClaims {
96 pub fn init(
97 challenge: &[u8],
98 personalization_val: &[u8],
99 measurements: &[Measurement],
100 measurement_hash_algo: String,
101 key_pub: &[u8],
102 key_pub_hash_algo: String,
103 ) -> RealmClaims {
104 let challenge_claim: Claim<Challenge> = Claim {
105 label: CHALLENGE_LABEL,
106 value: Data::from_slice(challenge),
107 };
108
109 let profile: Claim<Profile> = Claim {
110 label: PROFILE_LABEL,
111 value: REALM_PROFILE.to_string(),
112 };
113
114 let personalization_value: Claim<PersonalizationValue> = Claim {
115 label: PERSONALIZATION_VALUE_LABEL,
116 value: Data::from_slice(personalization_val),
117 };
118
119 let measurement_size = match measurement_hash_algo.as_str() {
120 "sha-256" => 32,
121 "sha-512" => 64,
122 _ => panic!("Unexpected hash algo id {}", measurement_hash_algo),
123 };
124
125 let rim: Claim<RIM> = Claim {
126 label: INITIAL_MEASUREMENT_LABEL,
127 value: MeasurementEntry(measurements[MEASUREMENTS_SLOT_RIM], measurement_size),
128 };
129
130 let mut rems_data = [MeasurementEntry::default(); REM_SLOT_NR];
131 for i in 0..REM_SLOT_NR {
132 rems_data[i] = MeasurementEntry(measurements[i + 1], measurement_size);
133 }
134
135 let rems: Claim<REMs> = Claim {
136 label: EXTENSIBLE_MEASUREMENTS_LABEL,
137 value: Data::from_slice(&rems_data),
138 };
139
140 let hash_algo_id: Claim<HashAlgo> = Claim {
141 label: HASH_ALGO_ID_LABEL,
142 value: measurement_hash_algo,
143 };
144
145 let key_pub_cose = cose::ec_public_key_sec1_to_cose(key_pub);
146
147 let rak_pub: Claim<RAKPubKey> = Claim {
148 label: PUBLIC_KEY_LABEL,
149 value: key_pub_cose,
150 };
151
152 let rak_pub_hash_algo: Claim<HashAlgo> = Claim {
153 label: PUBLIC_KEY_HASH_ALOG_ID_LABEL,
154 value: key_pub_hash_algo,
155 };
156
157 Self {
158 challenge: challenge_claim,
159 profile,
160 personalization_value,
161 rim,
162 rems,
163 measurement_hash_algo: hash_algo_id,
164 rak_pub,
165 rak_pub_hash_algo,
166 }
167 }
168}