Skip to main content

islet_hes/measured_boot/
manager.rs

1use super::*;
2use crate::{BootMeasurement, ValueHash};
3use alloc::vec::Vec;
4use measurement::*;
5use sha2::{Digest, Sha256, Sha384, Sha512};
6
7#[derive(Debug)]
8/// Keeps measurement in a slot.
9struct MeasurementSlot {
10    /// Measurement metadata and value.
11    measurement: Measurement,
12    /// Indicates whether the slot is locked and cannot be further extended.
13    is_locked: bool,
14    /// Indicates whether the slot is populated with an actual measurement.
15    is_populated: bool,
16}
17
18impl Default for MeasurementSlot {
19    /// Create an instance of `MeasurementSlot` with default values.
20    fn default() -> Self {
21        Self {
22            is_locked: false,
23            is_populated: false,
24            measurement: Measurement::default(),
25        }
26    }
27}
28
29impl MeasurementSlot {
30    /// Extends slot metadata and value.
31    pub fn extend(&mut self, measurement: Measurement, lock: bool) {
32        self.extend_metadata(measurement.metadata);
33        self.extend_value(measurement.value, lock);
34    }
35
36    /// Extends slot metadata. Updates only sw type and version, as signer_id
37    /// and algorithm never change.
38    fn extend_metadata(&mut self, metadata: MeasurementMetaData) {
39        // RSS does something strange here - it zero'es metadatas version and sw type
40        // see https://git.trustedfirmware.org/TF-M/tf-m-extras.git/tree/partitions/measured_boot/measured_boot.c#n221
41        // I think it was supposed to clear and then update the version and sw type.
42        self.measurement.metadata.sw_type = metadata.sw_type;
43        self.measurement.metadata.sw_version = metadata.sw_version;
44    }
45
46    /// Extends slot value only. Recalculates value hash based on current slot value
47    /// and new measurement value.
48    fn extend_value(&mut self, value: ValueHash, lock: bool) {
49        let measurement_value_len = self.measurement.metadata.algorithm.hash_len();
50
51        let total_len = measurement_value_len + value.len();
52        let mut temp = Vec::with_capacity(total_len);
53        temp.resize(total_len, 0);
54        temp[..measurement_value_len]
55            .copy_from_slice(&self.measurement.value[..measurement_value_len]);
56        temp[measurement_value_len..].copy_from_slice(&value);
57
58        match self.measurement.metadata.algorithm {
59            MeasurementType::Sha256 => {
60                let mut hasher = Sha256::new();
61                hasher.update(&temp);
62                let result = hasher.finalize();
63                self.measurement.value[..result.len()].copy_from_slice(&result);
64            }
65            MeasurementType::Sha384 => {
66                let mut hasher = Sha384::new();
67                hasher.update(&temp);
68                let result = hasher.finalize();
69                self.measurement.value[..result.len()].copy_from_slice(&result);
70            }
71            MeasurementType::Sha512 => {
72                let mut hasher = Sha512::new();
73                hasher.update(&temp);
74                let result = hasher.finalize();
75                self.measurement.value[..result.len()].copy_from_slice(&result);
76            }
77        };
78
79        self.is_populated = true;
80        self.is_locked = lock;
81    }
82
83    /// Overwrites measurement metadata and value. Should be used only when
84    /// upopulated slot is extended for the first time.
85    pub fn initialize(&mut self, measurement: Measurement, lock: bool) {
86        assert!(!self.is_populated, "Do not initialize a populated slot!");
87
88        self.set_metadata(measurement.metadata);
89        self.measurement
90            .value
91            .resize(self.measurement.metadata.algorithm.hash_len(), 0);
92        self.extend_value(measurement.value, lock);
93    }
94
95    /// Overwrites measurement metadata. Should be used only when unpopulated
96    /// slot is extended for the first time.
97    fn set_metadata(&mut self, metadata: MeasurementMetaData) {
98        self.measurement.metadata = metadata;
99    }
100
101    pub fn is_locked(&self) -> bool {
102        self.is_locked
103    }
104
105    pub fn is_populated(&self) -> bool {
106        self.is_populated
107    }
108
109    pub fn mark_as_populated(&mut self) {
110        self.is_populated = true;
111    }
112
113    /// Checks if slot extending is prohibited. The singer_id and algorithm
114    /// cannot change.
115    pub fn is_prohibited(&self, metadata: &MeasurementMetaData) -> bool {
116        metadata.signer_id != self.measurement.metadata.signer_id
117            || metadata.algorithm != self.measurement.metadata.algorithm
118    }
119}
120
121#[derive(Debug)]
122/// Responsible for storing all software components measurements and performing
123/// the `read_measurement` and `extend_measurement` functions.
124pub struct MeasurementMgr {
125    measurements: [MeasurementSlot; NUM_OF_MEASUREMENT_SLOTS],
126}
127
128/// Maximum number of slots - based on the RSS implementation.
129pub const NUM_OF_MEASUREMENT_SLOTS: usize = 32;
130
131impl MeasurementMgr {
132    /// Initializes with `BootMeasurement`s repacked and stores as `Measurement` slots.
133    pub fn init(
134        boot_measurements: Vec<BootMeasurement>,
135    ) -> Result<MeasurementMgr, MeasurementError> {
136        assert!(
137            boot_measurements.len() <= NUM_OF_MEASUREMENT_SLOTS,
138            "MeasurementMgr cannot contain HW measurements"
139        );
140
141        let mut measurements = core::array::from_fn(|_| MeasurementSlot::default());
142
143        boot_measurements
144            .into_iter()
145            .enumerate()
146            .try_for_each(|(index, boot_measurement)| {
147                let measurement = boot_measurement.try_into()?;
148                measurements[index].initialize(measurement, false);
149                Ok::<(), MeasurementError>(())
150            })
151            .unwrap();
152
153        Ok(MeasurementMgr { measurements })
154    }
155
156    /// Returns measurement metadata, value and locked attribute from given slot_id.
157    /// Returns [`MeasurementError::InvalidArgument`], when slot_id is out of bounds.
158    /// Returns [`MeasurementError::DoesNotExist`], when is not populated.
159    pub fn read_measurement(
160        &self,
161        slot_id: usize,
162    ) -> Result<(&Measurement, bool), MeasurementError> {
163        if slot_id >= NUM_OF_MEASUREMENT_SLOTS {
164            return Err(MeasurementError::InvalidArgument);
165        }
166        let slot = &self.measurements[slot_id];
167
168        if !slot.is_populated() {
169            return Err(MeasurementError::DoesNotExist);
170        }
171        Ok((&slot.measurement, slot.is_locked))
172    }
173
174    /// Extends measurement with updated metadata, value and locked attribute in given slot_id.
175    /// Returns [`MeasurementError::InvalidArgument`], when slot_id is out of bounds.
176    /// Returns [`MeasurementError::BadState`], when measurement is locked.
177    /// Returns [`MeasurementError::NotPermitted`], when measurements signer id's
178    /// and algorithm do not match.
179    pub fn extend_measurement(
180        &mut self,
181        slot_id: usize,
182        measurement: Measurement,
183        lock: bool,
184    ) -> Result<(), MeasurementError> {
185        if slot_id >= NUM_OF_MEASUREMENT_SLOTS {
186            return Err(MeasurementError::InvalidArgument);
187        }
188
189        let slot = &mut self.measurements[slot_id];
190
191        if slot.is_locked() {
192            return Err(MeasurementError::BadState);
193        }
194
195        if slot.is_populated() {
196            if slot.is_prohibited(&measurement.metadata) {
197                return Err(MeasurementError::NotPermitted);
198            }
199            slot.extend(measurement, lock);
200        } else {
201            slot.initialize(measurement, lock);
202            slot.mark_as_populated();
203        }
204
205        Ok(())
206    }
207}
208
209#[cfg(test)]
210mod tests {
211    use crate::hw::BootMeasurementMetadata;
212    use alloc::{string::ToString, vec::Vec};
213    use core::{iter, str::from_utf8};
214
215    use super::*;
216    use tinyvec::ArrayVec;
217
218    fn metadata(algorithm: MeasurementType) -> MeasurementMetaData {
219        let signer_id: SignerHash = ArrayVec::from([
220            0x01, 0x05, 0x01, 0xEF, 0x68, 0x07, 0x88, 0xCC, 0x33, 0x06, 0x54, 0xAB, 0x09, 0x01,
221            0x74, 0x77, 0x49, 0x08, 0x93, 0xA8, 0x01, 0x07, 0xEF, 0x01, 0x83, 0x09, 0x22, 0xCD,
222            0x09, 0x61, 0xB6, 0xFF, 0x01, 0x05, 0x01, 0xEF, 0x68, 0x07, 0x88, 0xCC, 0x33, 0x06,
223            0x54, 0xAB, 0x09, 0x01, 0x74, 0x77, 0x49, 0x08, 0x93, 0xA8, 0x01, 0x07, 0xEF, 0x01,
224            0x83, 0x09, 0x22, 0xCD, 0x09, 0x61, 0xB6, 0xFF,
225        ]);
226
227        let sw_version: SWVersion = from_utf8(&[
228            0x32, 0x35, 0x35, 0x2E, 0x32, 0x35, 0x35, 0x2E, 0x36, 0x35, 0x35, 0x33, 0x35, 0x0,
229        ])
230        .unwrap()
231        .to_string();
232
233        let sw_type: SWType = from_utf8(&[
234            0x4D, 0x45, 0x41, 0x53, 0x55, 0x52, 0x45, 0x44, 0x5F, 0x42, 0x4F, 0x4F, 0x54, 0x5F,
235            0x54, 0x45, 0x53, 0x54, 0x53, 0x0,
236        ])
237        .unwrap()
238        .to_string();
239
240        MeasurementMetaData {
241            signer_id,
242            sw_version,
243            algorithm,
244            sw_type,
245        }
246    }
247
248    fn value(len: usize) -> ValueHash {
249        let mut value: ValueHash = ValueHash::from([
250            0x8a, 0x66, 0x01, 0xf6, 0x70, 0x74, 0x8b, 0xe2, 0x33, 0xff, 0x5d, 0x75, 0xd7, 0xea,
251            0x89, 0xa8, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0x01, 0x05, 0x01, 0xEF,
252            0x68, 0x07, 0x88, 0xCC, 0x83, 0x09, 0x22, 0xCD, 0x09, 0x61, 0xB6, 0xFF, 0xbb, 0xbb,
253            0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0x56, 0x46, 0x58, 0x49, 0x99, 0x31, 0xcf, 0x59,
254            0x7d, 0xbc, 0x3a, 0x4e, 0x68, 0x79, 0x8a, 0x1c,
255        ]);
256        value.truncate(len);
257        value
258    }
259
260    fn test_extend(
261        mgr: &mut MeasurementMgr,
262        slot_id: usize,
263        algorithm: MeasurementType,
264        value: ValueHash,
265        expected_value: &[u8],
266    ) {
267        let metadata = metadata(algorithm);
268        let measurement = Measurement {
269            metadata: metadata.clone(),
270            value,
271        };
272
273        mgr.extend_measurement(slot_id, measurement, false).unwrap();
274
275        let (read_measurement, lock) = mgr.read_measurement(slot_id).unwrap();
276
277        assert_eq!(lock, false);
278        assert_eq!(metadata, read_measurement.metadata);
279        assert_eq!(&read_measurement.value[..], expected_value);
280    }
281
282    //---------------POSITIVE EXTEND/READ MEASUREMENT TESTS--------------------
283
284    #[test]
285    fn extend_256_with_256() {
286        let slot_id = 20;
287        let algorithm = MeasurementType::Sha256;
288
289        // First extend on slot 20
290        let value_256_0: ValueHash = [
291            0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb,
292            0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb,
293            0xbb, 0xbb, 0xbb, 0xbb,
294        ]
295        .iter()
296        .cloned()
297        .collect();
298
299        let expected_value_256_0 = [
300            0x86, 0xbf, 0xbc, 0xe7, 0xf8, 0x8e, 0x77, 0xda, 0xb6, 0xbb, 0xfb, 0x92, 0x3b, 0xb7,
301            0x0e, 0x24, 0x11, 0xd3, 0x74, 0xdc, 0x65, 0x8d, 0xb7, 0x51, 0xc9, 0xbd, 0xec, 0x43,
302            0x8f, 0x5c, 0xce, 0x54,
303        ];
304
305        let mut mgr = MeasurementMgr::init(Vec::new()).unwrap();
306
307        test_extend(
308            &mut mgr,
309            slot_id,
310            algorithm,
311            value_256_0,
312            &expected_value_256_0,
313        );
314
315        // First extend on slot 21
316        let value_256_different_slot: ValueHash = [
317            0x75, 0xb2, 0x20, 0xfd, 0x5f, 0xfc, 0xdb, 0xfc, 0x20, 0x73, 0xe4, 0xa0, 0x2f, 0x8c,
318            0x53, 0x38, 0x3c, 0x74, 0xbd, 0xf3, 0xb6, 0xab, 0x9f, 0xb6, 0xb3, 0xd2, 0xbb, 0x7a,
319            0xa2, 0x08, 0xc5, 0x98,
320        ]
321        .iter()
322        .cloned()
323        .collect();
324
325        let expected_value_256_different_slot = [
326            0x84, 0x8A, 0x8C, 0xA6, 0x4F, 0x17, 0x54, 0x6A, 0x71, 0x8E, 0xE2, 0x59, 0x45, 0x92,
327            0x01, 0xBE, 0x31, 0xF8, 0x85, 0xF1, 0xD3, 0x3F, 0x38, 0x09, 0xE6, 0xF6, 0xF1, 0x82,
328            0x3A, 0x90, 0x04, 0x5A,
329        ];
330
331        test_extend(
332            &mut mgr,
333            slot_id + 1,
334            algorithm,
335            value_256_different_slot,
336            &expected_value_256_different_slot,
337        );
338
339        // Second extend on slot 20
340        let value_256_1: ValueHash = [
341            0x01, 0x05, 0x01, 0xEF, 0x68, 0x07, 0x88, 0xCC, 0x33, 0x06, 0x54, 0xAB, 0x09, 0x01,
342            0x74, 0x77, 0x49, 0x08, 0x93, 0xA8, 0x01, 0x07, 0xEF, 0x01, 0x83, 0x09, 0x22, 0xCD,
343            0x09, 0x61, 0xB6, 0xFF,
344        ]
345        .iter()
346        .cloned()
347        .collect();
348
349        let expected_value_256_1 = [
350            0xd2, 0xab, 0xc1, 0x26, 0xeb, 0x5c, 0x25, 0x9d, 0x30, 0x33, 0x9c, 0x02, 0xd7, 0x49,
351            0x4f, 0x04, 0xe2, 0xd4, 0x49, 0xbe, 0x81, 0xa9, 0x60, 0x39, 0x56, 0x0e, 0x56, 0x90,
352            0xb3, 0xda, 0xaf, 0x25,
353        ];
354
355        test_extend(
356            &mut mgr,
357            slot_id,
358            algorithm,
359            value_256_1,
360            &expected_value_256_1,
361        );
362    }
363
364    #[test]
365    fn test_extend_256_with_512() {
366        let slot_id = 22;
367        let algorithm = MeasurementType::Sha256;
368
369        let value_512_0 = ArrayVec::from([
370            0x8a, 0x66, 0x01, 0xf6, 0x70, 0x74, 0x8b, 0xe2, 0x33, 0xff, 0x5d, 0x75, 0xd7, 0xea,
371            0x89, 0xa8, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0x01, 0x05, 0x01, 0xEF,
372            0x68, 0x07, 0x88, 0xCC, 0x83, 0x09, 0x22, 0xCD, 0x09, 0x61, 0xB6, 0xFF, 0xbb, 0xbb,
373            0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0x56, 0x46, 0x58, 0x49, 0x99, 0x31, 0xcf, 0x59,
374            0x7d, 0xbc, 0x3a, 0x4e, 0x68, 0x79, 0x8a, 0x1c,
375        ]);
376
377        let expected_value_256_0 = [
378            0x75, 0xb2, 0x20, 0xfd, 0x5f, 0xfc, 0xdb, 0xfc, 0x20, 0x73, 0xe4, 0xa0, 0x2f, 0x8c,
379            0x53, 0x38, 0x3c, 0x74, 0xbd, 0xf3, 0xb6, 0xab, 0x9f, 0xb6, 0xb3, 0xd2, 0xbb, 0x7a,
380            0xa2, 0x08, 0xc5, 0x98,
381        ];
382
383        let mut mgr = MeasurementMgr::init(Vec::new()).unwrap();
384
385        test_extend(
386            &mut mgr,
387            slot_id,
388            algorithm,
389            value_512_0,
390            &expected_value_256_0,
391        );
392
393        let value_512_1 = ArrayVec::from([
394            0x56, 0x46, 0x58, 0x49, 0x99, 0x31, 0xcf, 0x59, 0x7d, 0xbc, 0x3a, 0x4e, 0x68, 0x79,
395            0x8a, 0x1c, 0x01, 0x05, 0x01, 0xEF, 0x68, 0x07, 0x88, 0xCC, 0x83, 0x09, 0x22, 0xCD,
396            0x09, 0x61, 0xB6, 0xFF, 0x7d, 0xbc, 0x3a, 0x4e, 0x68, 0x79, 0x8a, 0x1c, 0x01, 0x05,
397            0x01, 0xEF, 0x68, 0x07, 0x88, 0xCC, 0x8a, 0x66, 0x01, 0xf6, 0x70, 0x74, 0x8b, 0xe2,
398            0x83, 0x09, 0x22, 0xCD, 0x09, 0x61, 0xB6, 0xFF,
399        ]);
400
401        let expected_value_256_1 = [
402            0x79, 0xc3, 0xb9, 0xca, 0xf7, 0x7b, 0xa7, 0xf3, 0x20, 0x65, 0x77, 0x04, 0x09, 0x60,
403            0x8a, 0x02, 0x4f, 0xa5, 0x45, 0x9c, 0x6d, 0x10, 0xa7, 0xca, 0x59, 0x3f, 0xf1, 0x4d,
404            0x9b, 0x37, 0xe8, 0x3c,
405        ];
406
407        test_extend(
408            &mut mgr,
409            slot_id,
410            algorithm,
411            value_512_1,
412            &expected_value_256_1,
413        );
414    }
415
416    #[test]
417    fn test_extend_512_with_256() {
418        let slot_id = 23;
419        let algorithm = MeasurementType::Sha512;
420
421        let value_256_0: ValueHash = [
422            0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb,
423            0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb,
424            0xbb, 0xbb, 0xbb, 0xbb,
425        ]
426        .iter()
427        .cloned()
428        .collect();
429
430        let expected_value_512_0 = [
431            0xa6, 0x34, 0xb5, 0xb6, 0xe5, 0xe9, 0x71, 0x5d, 0x47, 0x88, 0xf7, 0x2f, 0x1a, 0x39,
432            0xc3, 0xe2, 0xd2, 0xe1, 0x03, 0xde, 0xcf, 0xb8, 0xf8, 0xd6, 0x22, 0xcc, 0xff, 0x8c,
433            0xb2, 0xe3, 0xe8, 0x22, 0x74, 0x31, 0x6c, 0x4b, 0x8d, 0x66, 0x25, 0x11, 0xcc, 0x1c,
434            0xf9, 0x0a, 0x24, 0x56, 0xdf, 0xf2, 0xb6, 0x20, 0xd3, 0xbe, 0xf0, 0xe0, 0xb9, 0x56,
435            0xcf, 0x3a, 0xcc, 0x78, 0xe6, 0x58, 0xbe, 0x40,
436        ];
437
438        let mut mgr = MeasurementMgr::init(Vec::new()).unwrap();
439
440        test_extend(
441            &mut mgr,
442            slot_id,
443            algorithm,
444            value_256_0,
445            &expected_value_512_0,
446        );
447
448        let value_256_1: ValueHash = [
449            0x01, 0x05, 0x01, 0xEF, 0x68, 0x07, 0x88, 0xCC, 0x33, 0x06, 0x54, 0xAB, 0x09, 0x01,
450            0x74, 0x77, 0x49, 0x08, 0x93, 0xA8, 0x01, 0x07, 0xEF, 0x01, 0x83, 0x09, 0x22, 0xCD,
451            0x09, 0x61, 0xB6, 0xFF,
452        ]
453        .iter()
454        .cloned()
455        .collect();
456
457        let expected_value_512_1 = [
458            0x53, 0x2e, 0x19, 0xa7, 0xdf, 0x21, 0xe7, 0x7f, 0x6a, 0xe0, 0xe6, 0x30, 0xda, 0xfb,
459            0x39, 0x67, 0x8c, 0xdd, 0x74, 0x5f, 0x30, 0x9f, 0x10, 0x80, 0xb3, 0xfa, 0x88, 0x75,
460            0x33, 0x31, 0x00, 0x46, 0x59, 0x4f, 0x76, 0xb8, 0xfe, 0x5b, 0xae, 0xc4, 0xeb, 0xe2,
461            0xe9, 0x15, 0x02, 0x4f, 0x34, 0x4e, 0x88, 0xc0, 0x43, 0xcd, 0x90, 0x14, 0xcd, 0xaa,
462            0xd1, 0xc5, 0x73, 0xba, 0xc3, 0x4c, 0x56, 0xbe,
463        ];
464
465        test_extend(
466            &mut mgr,
467            slot_id,
468            algorithm,
469            value_256_1,
470            &expected_value_512_1,
471        );
472    }
473
474    #[test]
475    fn extend_512_with_512() {
476        let slot_id = NUM_OF_MEASUREMENT_SLOTS - 1;
477        let algorithm = MeasurementType::Sha512;
478
479        let value_512_0: ValueHash = [
480            0x8a, 0x66, 0x01, 0xf6, 0x70, 0x74, 0x8b, 0xe2, 0x33, 0xff, 0x5d, 0x75, 0xd7, 0xea,
481            0x89, 0xa8, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0x01, 0x05, 0x01, 0xEF,
482            0x68, 0x07, 0x88, 0xCC, 0x83, 0x09, 0x22, 0xCD, 0x09, 0x61, 0xB6, 0xFF, 0xbb, 0xbb,
483            0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0x56, 0x46, 0x58, 0x49, 0x99, 0x31, 0xcf, 0x59,
484            0x7d, 0xbc, 0x3a, 0x4e, 0x68, 0x79, 0x8a, 0x1c,
485        ]
486        .iter()
487        .cloned()
488        .collect();
489
490        let expected_value_512_0 = [
491            0x8e, 0x17, 0x5a, 0x1d, 0xcd, 0x79, 0xb8, 0xb5, 0x1c, 0xe9, 0xe2, 0x59, 0xc2, 0x56,
492            0x83, 0x05, 0xb7, 0x3f, 0x5f, 0x26, 0xf5, 0x67, 0x3a, 0x8c, 0xf7, 0x81, 0xa9, 0x45,
493            0x98, 0xe4, 0x4f, 0x67, 0xfd, 0xf4, 0x92, 0x68, 0x69, 0xee, 0x76, 0x67, 0xe9, 0x12,
494            0x0b, 0x5c, 0x1b, 0x97, 0x62, 0x5c, 0xc9, 0x6d, 0x34, 0x7c, 0x23, 0xce, 0x3c, 0x5f,
495            0x76, 0x3b, 0xf1, 0xd9, 0xb5, 0x47, 0x81, 0xf6,
496        ];
497
498        let mut mgr = MeasurementMgr::init(Vec::new()).unwrap();
499
500        test_extend(
501            &mut mgr,
502            slot_id,
503            algorithm,
504            value_512_0,
505            &expected_value_512_0,
506        );
507
508        let value_512_1: ValueHash = [
509            0x56, 0x46, 0x58, 0x49, 0x99, 0x31, 0xcf, 0x59, 0x7d, 0xbc, 0x3a, 0x4e, 0x68, 0x79,
510            0x8a, 0x1c, 0x01, 0x05, 0x01, 0xEF, 0x68, 0x07, 0x88, 0xCC, 0x83, 0x09, 0x22, 0xCD,
511            0x09, 0x61, 0xB6, 0xFF, 0x7d, 0xbc, 0x3a, 0x4e, 0x68, 0x79, 0x8a, 0x1c, 0x01, 0x05,
512            0x01, 0xEF, 0x68, 0x07, 0x88, 0xCC, 0x8a, 0x66, 0x01, 0xf6, 0x70, 0x74, 0x8b, 0xe2,
513            0x83, 0x09, 0x22, 0xCD, 0x09, 0x61, 0xB6, 0xFF,
514        ]
515        .iter()
516        .cloned()
517        .collect();
518
519        let expected_value_512_1 = [
520            0x69, 0x8f, 0xc1, 0x9d, 0xc0, 0xfb, 0x93, 0xc9, 0x78, 0x31, 0x52, 0xd9, 0x33, 0x6f,
521            0x35, 0xa7, 0x9a, 0x2d, 0x48, 0xdb, 0x45, 0xa8, 0xd4, 0xc4, 0x8c, 0x0e, 0xef, 0xcb,
522            0xeb, 0xc0, 0x11, 0x0d, 0xa2, 0xe4, 0x0f, 0x62, 0x78, 0x34, 0xdd, 0x8e, 0x46, 0xa9,
523            0x2b, 0xaa, 0x23, 0x00, 0x6b, 0x36, 0xc6, 0x79, 0xc0, 0x4e, 0x14, 0xca, 0x91, 0x3f,
524            0xd2, 0xde, 0xe2, 0x38, 0x58, 0xd5, 0x43, 0xd2,
525        ];
526
527        test_extend(
528            &mut mgr,
529            slot_id,
530            algorithm,
531            value_512_1,
532            &expected_value_512_1,
533        );
534    }
535
536    //---------------NEGATIVE WRONG PARAMETERS TESTS---------------------------
537
538    #[test]
539    fn test_prohibited_extend_after_lock() {
540        let slot_id = 9;
541
542        let measurement = Measurement {
543            metadata: metadata(MeasurementType::Sha256),
544            value: value(32),
545        };
546
547        let mut mgr = MeasurementMgr::init(Vec::new()).unwrap();
548
549        mgr.extend_measurement(slot_id, measurement.clone(), true)
550            .unwrap();
551
552        assert_eq!(
553            mgr.extend_measurement(slot_id, measurement, false)
554                .unwrap_err(),
555            MeasurementError::BadState
556        );
557    }
558
559    #[test]
560    fn test_prohibited_algorithm_change() {
561        let slot_id = 10;
562        let value = value(32);
563        let mut metadata = metadata(MeasurementType::Sha256);
564
565        let measurement = Measurement {
566            metadata: metadata.clone(),
567            value: value.clone(),
568        };
569
570        let mut mgr = MeasurementMgr::init(Vec::new()).unwrap();
571
572        mgr.extend_measurement(slot_id, measurement, false).unwrap();
573
574        metadata.algorithm = MeasurementType::Sha384;
575
576        let measurement = Measurement {
577            metadata: metadata.clone(),
578            value: value.clone(),
579        };
580
581        assert_eq!(
582            mgr.extend_measurement(slot_id, measurement, false)
583                .unwrap_err(),
584            MeasurementError::NotPermitted
585        );
586    }
587
588    #[test]
589    fn test_prohibited_signer_change() {
590        let slot_id = 10;
591        let value = value(32);
592        let mut metadata = metadata(MeasurementType::Sha256);
593
594        let measurement = Measurement {
595            metadata: metadata.clone(),
596            value: value.clone(),
597        };
598
599        let mut mgr = MeasurementMgr::init(Vec::new()).unwrap();
600
601        mgr.extend_measurement(slot_id, measurement, false).unwrap();
602
603        metadata.signer_id[13] = 13;
604
605        let measurement = Measurement {
606            metadata: metadata.clone(),
607            value: value.clone(),
608        };
609
610        assert_eq!(
611            mgr.extend_measurement(slot_id, measurement, false)
612                .unwrap_err(),
613            MeasurementError::NotPermitted
614        );
615    }
616
617    #[test]
618    fn test_extend_slot_out_of_bounds() {
619        let slot_id = NUM_OF_MEASUREMENT_SLOTS;
620        let value = value(32);
621        let metadata = metadata(MeasurementType::Sha256);
622
623        let mut mgr = MeasurementMgr::init(Vec::new()).unwrap();
624
625        assert_eq!(
626            mgr.extend_measurement(slot_id, Measurement { metadata, value }, false)
627                .unwrap_err(),
628            MeasurementError::InvalidArgument
629        );
630    }
631
632    #[test]
633    fn test_read_slot_out_of_bounds() {
634        let slot_id = NUM_OF_MEASUREMENT_SLOTS;
635        let mgr = MeasurementMgr::init(Vec::new()).unwrap();
636
637        assert_eq!(
638            mgr.read_measurement(slot_id).unwrap_err(),
639            MeasurementError::InvalidArgument
640        );
641    }
642
643    #[test]
644    fn test_read_slot_unpopulated() {
645        let slot_id = 20;
646        let mgr = MeasurementMgr::init(Vec::new()).unwrap();
647
648        assert_eq!(
649            mgr.read_measurement(slot_id).unwrap_err(),
650            MeasurementError::DoesNotExist
651        );
652    }
653
654    //---------------BOOT MEASUREMENTS INITIALIZATION TESTS--------------------
655    fn boot_measurements() -> Vec<BootMeasurement> {
656        Vec::from([
657            BootMeasurement {
658                measurement_value: [
659                    0x61, 0x97, 0x3b, 0x4f, 0x62, 0x0c, 0x2a, 0xe6, 0xc7, 0x63, 0x51, 0x18, 0xa0,
660                    0xb4, 0x37, 0x6d, 0x15, 0x34, 0x4c, 0x1c, 0x53, 0xa2, 0x17, 0x89, 0xb1, 0xaa,
661                    0x95, 0xd2, 0x0f, 0x3c, 0x45, 0x06,
662                ]
663                .iter()
664                .cloned()
665                .collect(),
666                metadata: BootMeasurementMetadata {
667                    signer_id: [
668                        0xc6, 0xc3, 0x2a, 0x95, 0x7d, 0xf4, 0xc6, 0x69, 0x8c, 0x55, 0x0b, 0x69,
669                        0x5d, 0x02, 0x2e, 0xd5, 0x18, 0x0c, 0xae, 0x71, 0xf8, 0xb4, 0x9c, 0xbb,
670                        0x75, 0xe6, 0x06, 0x1c, 0x2e, 0xf4, 0x97, 0xe1,
671                    ]
672                    .iter()
673                    .cloned()
674                    .collect(),
675                    measurement_type: 0,
676                    sw_type: b"BL1".iter().cloned().collect(),
677                    sw_version: b"0.1.0".iter().cloned().collect(),
678                },
679            },
680            BootMeasurement {
681                measurement_value: [
682                    0xf1, 0x5f, 0x95, 0x3b, 0xe5, 0x0d, 0xad, 0x92, 0xc3, 0xb2, 0xaa, 0x32, 0x97,
683                    0xe6, 0xa4, 0xa8, 0xd6, 0x6d, 0x33, 0x63, 0x84, 0x49, 0xec, 0x19, 0x22, 0xb4,
684                    0xa7, 0x92, 0x4a, 0x7b, 0x30, 0x22,
685                ]
686                .iter()
687                .cloned()
688                .collect(),
689                metadata: BootMeasurementMetadata {
690                    signer_id: [
691                        0xa0, 0x64, 0xb1, 0xad, 0x60, 0xfa, 0x18, 0x33, 0x94, 0xdd, 0xa5, 0x78,
692                        0x91, 0x35, 0x7f, 0x97, 0x2e, 0x4f, 0xe7, 0x22, 0x78, 0x2a, 0xdf, 0xf1,
693                        0x85, 0x4c, 0x8b, 0x2a, 0x14, 0x2c, 0x04, 0x10,
694                    ]
695                    .iter()
696                    .cloned()
697                    .collect(),
698                    measurement_type: 0,
699                    sw_type: b"BL2".iter().cloned().collect(),
700                    sw_version: b"1.9.0+0".iter().cloned().collect(),
701                },
702            },
703        ])
704    }
705
706    const BL_1_MEASUREMENT_SLOT_ID: usize = 0;
707    const BL_2_MEASUREMENT_SLOT_ID: usize = 1;
708
709    #[test]
710    fn test_boot_measurements_ok() {
711        let boot_measurements = boot_measurements();
712        let mgr = MeasurementMgr::init(boot_measurements.clone()).unwrap();
713
714        let bl1_measurement = &boot_measurements[0];
715        let (measurement, lock) = mgr.read_measurement(BL_1_MEASUREMENT_SLOT_ID).unwrap();
716
717        let expected_measurement_value: ValueHash = [
718            0x69, 0x7d, 0xe4, 0x40, 0x7d, 0xae, 0x45, 0xc0, 0x75, 0x06, 0xd1, 0xf0, 0x0b, 0x3d,
719            0xbf, 0x5c, 0xe1, 0xdb, 0x41, 0xf6, 0x9e, 0x17, 0x50, 0xa3, 0x11, 0xf9, 0x1d, 0x21,
720            0x3e, 0x11, 0x98, 0x89,
721        ]
722        .iter()
723        .cloned()
724        .collect();
725
726        assert_eq!(lock, false);
727        assert_eq!(
728            measurement.metadata,
729            <BootMeasurement as TryInto<Measurement>>::try_into(bl1_measurement.clone())
730                .unwrap()
731                .metadata
732        );
733        assert_eq!(measurement.value, expected_measurement_value);
734
735        let bl2_measurement = &boot_measurements[1];
736        let (measurement, lock) = mgr.read_measurement(BL_2_MEASUREMENT_SLOT_ID).unwrap();
737
738        let expected_measurement_value_2: ValueHash = [
739            0xa1, 0x9b, 0x4c, 0xf9, 0x32, 0x89, 0xd6, 0x89, 0xc8, 0xa9, 0xb7, 0xfe, 0x16, 0x6b,
740            0x4c, 0x5c, 0x12, 0xab, 0xc1, 0x12, 0xb3, 0x5f, 0xba, 0x81, 0xdf, 0x12, 0xf1, 0x4a,
741            0x99, 0x6f, 0x9d, 0x81,
742        ]
743        .iter()
744        .cloned()
745        .collect();
746
747        assert_eq!(lock, false);
748        assert_eq!(
749            measurement.metadata,
750            <BootMeasurement as TryInto<Measurement>>::try_into(bl2_measurement.clone())
751                .unwrap()
752                .metadata
753        );
754        assert_eq!(measurement.value, expected_measurement_value_2);
755    }
756
757    #[test]
758    #[should_panic(expected = "MeasurementMgr cannot contain HW measurements")]
759    fn test_boot_measurements_too_many() {
760        let boot_measurements = Vec::from_iter(
761            iter::repeat(BootMeasurement::default()).take(NUM_OF_MEASUREMENT_SLOTS + 1),
762        );
763
764        let _ = MeasurementMgr::init(boot_measurements);
765    }
766}