1use crate::image::manifest::*;
6use crate::image::manifest_ext::{ManifestExtEntrySpec, ManifestExtId};
7use crate::util::bigint::fixed_size_bigint;
8use crate::util::num_de::HexEncoded;
9use crate::util::parse_int::ParseInt;
10
11use anyhow::{Context, Result, bail};
12use serde::{Deserialize, Serialize};
13use std::convert::{TryFrom, TryInto};
14use std::fmt;
15use std::iter::IntoIterator;
16use std::path::Path;
17use thiserror::Error;
18
19use zerocopy::IntoBytes;
20
21#[derive(Debug, Error)]
22pub enum ManifestError {
23 #[error("Manifest is missing field \"{0}\".")]
24 MissingField(&'static str),
25}
26
27fixed_size_bigint!(ManifestSigverifyBuffer, at_most 512);
28
29#[derive(Clone, Default, Debug, Deserialize, Serialize)]
30struct ManifestSigverifyBigInt(Option<HexEncoded<ManifestSigverifyBuffer>>);
31
32#[derive(Clone, Default, Debug, Deserialize, Serialize)]
33struct ManifestSmallInt<T: ParseInt + fmt::LowerHex>(Option<HexEncoded<T>>);
34
35impl fmt::LowerHex for ManifestSigverifyBuffer {
36 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
37 fmt::LowerHex::fmt(&self.as_biguint(), f)
38 }
39}
40
41macro_rules! manifest_def {
47 ($access:vis struct $name:ident {
48 $(
49 $(#[$doc:meta])?
50 $field_name:ident: $field_type:ty,
51 )*
52 }, $out_type:ident) => {
53 #[derive(Clone, Default, Deserialize, Serialize, Debug)]
54 $access struct $name {
55 $(
56 $(#[$doc])?
57 #[serde(default)]
58 $field_name: $field_type,
59 )*
60 }
61
62 impl ManifestPacked<$out_type> for $name {
63 fn unpack(self, _name: &'static str) -> Result<$out_type> {
64 Ok($out_type {
65 $($field_name: self.$field_name
68 .unpack(stringify!($field_name))?.try_into()?,)*
69 })
70 }
71
72 fn overwrite(&mut self, o: $name) {
73 $(self.$field_name.overwrite(o.$field_name);)*
74 }
75 }
76
77 impl TryInto<$out_type> for $name {
78 type Error = anyhow::Error;
79
80 fn try_into(self) -> Result<$out_type> {
81 self.unpack("")
82 }
83 }
84
85 impl TryFrom<&$out_type> for $name {
86 type Error = anyhow::Error;
87
88 fn try_from(o: &$out_type) -> Result<Self> {
89 Ok($name {
90 $($field_name: (&o.$field_name).try_into()?,)*
91 })
92 }
93 }
94 }
95}
96
97impl ManifestSpec {
98 pub fn read_from_file(path: &Path) -> Result<ManifestSpec> {
99 Ok(deser_hjson::from_str(
100 &std::fs::read_to_string(path).with_context(|| format!("Failed to open {path:?}"))?,
101 )?)
102 }
103
104 pub fn overwrite_fields(&mut self, other: ManifestSpec) {
105 self.overwrite(other)
106 }
107
108 pub fn update_signature(&mut self, signature: ManifestSigverifyBuffer) {
109 self.signature.0 = Some(HexEncoded(signature))
110 }
111
112 pub fn update_pub_key(&mut self, pub_key: ManifestSigverifyBuffer) {
113 self.pub_key.0 = Some(HexEncoded(pub_key))
114 }
115
116 pub fn signature(&self) -> Option<&ManifestSigverifyBuffer> {
117 self.signature.0.as_ref().map(|v| &v.0)
118 }
119
120 pub fn pub_key(&self) -> Option<&ManifestSigverifyBuffer> {
121 self.pub_key.0.as_ref().map(|v| &v.0)
122 }
123
124 pub fn has_length(&self) -> bool {
125 self.length.0.is_some()
126 }
127}
128
129trait ManifestPacked<T> {
130 fn unpack_err(&self, name: &'static str) -> Result<T> {
132 bail!(ManifestError::MissingField(name))
133 }
134
135 fn unpack(self, name: &'static str) -> Result<T>;
137
138 fn overwrite(&mut self, o: Self);
140}
141
142impl ManifestPacked<ManifestSigverifyBuffer> for ManifestSigverifyBigInt {
143 fn unpack(self, name: &'static str) -> Result<ManifestSigverifyBuffer> {
144 match self.0 {
145 Some(v) => Ok(v.0),
146 None => self.unpack_err(name),
147 }
148 }
149
150 fn overwrite(&mut self, o: Self) {
151 if o.0.is_some() {
152 *self = o;
153 }
154 }
155}
156
157impl ManifestPacked<[ManifestExtTableEntry; CHIP_MANIFEST_EXT_TABLE_COUNT]>
158 for [ManifestExtTableEntryDef; CHIP_MANIFEST_EXT_TABLE_COUNT]
159{
160 fn unpack(
161 self,
162 _name: &'static str,
163 ) -> Result<[ManifestExtTableEntry; CHIP_MANIFEST_EXT_TABLE_COUNT]> {
164 Ok(self.map(|v| match v.0 {
165 ManifestExtEntryVar::Name(name) => ManifestExtTableEntry {
166 identifier: name.into(),
167 offset: 0,
168 },
169 ManifestExtEntryVar::IdOffset { identifier, offset } => ManifestExtTableEntry {
170 identifier: identifier.into(),
171 offset,
172 },
173 _ => ManifestExtTableEntry {
174 identifier: 0,
175 offset: 0,
176 },
177 }))
178 }
179
180 fn overwrite(&mut self, o: Self) {
181 for i in 0..self.len() {
182 match o[i].0 {
183 ManifestExtEntryVar::Name(other_id) => match self[i].0 {
184 ManifestExtEntryVar::IdOffset {
185 identifier: self_id,
186 offset: _,
187 } => {
188 if self_id == other_id {
189 continue;
191 } else {
192 self[i].0 = o[i].0.clone()
193 }
194 }
195 _ => self[i].0 = o[i].0.clone(),
196 },
197 ManifestExtEntryVar::None => (),
198 _ => self[i].0 = o[i].0.clone(),
199 }
200 }
201 }
202}
203
204impl<T: ParseInt + fmt::LowerHex> ManifestPacked<T> for ManifestSmallInt<T> {
205 fn unpack(self, name: &'static str) -> Result<T> {
206 match self.0 {
207 Some(v) => Ok(v.0),
208 None => self.unpack_err(name),
209 }
210 }
211
212 fn overwrite(&mut self, o: Self) {
213 if o.0.is_some() {
214 *self = o;
215 }
216 }
217}
218
219impl<T: ParseInt + fmt::LowerHex, const N: usize> ManifestPacked<[T; N]>
220 for [ManifestSmallInt<T>; N]
221{
222 fn unpack(self, name: &'static str) -> Result<[T; N]> {
223 let results = self.map(|e| e.unpack(name));
224 if let Some(err_idx) = results.iter().position(Result::is_err) {
225 IntoIterator::into_iter(results).nth(err_idx).unwrap()?;
226 unreachable!();
227 } else {
228 Ok(results.map(|x| x.unwrap()))
229 }
230 }
231
232 fn overwrite(&mut self, o: Self) {
233 if o.iter().all(|v| v.0.is_some()) {
235 *self = o;
236 }
237 }
238}
239
240#[derive(Clone, Default, Deserialize, Serialize, Debug)]
241pub struct ManifestSpec {
242 #[serde(default)]
243 signature: ManifestSigverifyBigInt,
244
245 #[serde(default)]
246 usage_constraints: ManifestUsageConstraintsDef,
247
248 #[serde(default)]
249 pub_key: ManifestSigverifyBigInt,
250
251 #[serde(default)]
252 address_translation: ManifestSmallInt<u32>,
253
254 #[serde(default)]
255 identifier: ManifestSmallInt<u32>,
256
257 #[serde(default)]
258 manifest_version: ManifestVersionDef,
259
260 #[serde(default)]
261 signed_region_end: ManifestSmallInt<u32>,
262
263 #[serde(default)]
264 length: ManifestSmallInt<u32>,
265
266 #[serde(default)]
267 version_major: ManifestSmallInt<u32>,
268
269 #[serde(default)]
270 version_minor: ManifestSmallInt<u32>,
271
272 #[serde(default)]
273 security_version: ManifestSmallInt<u32>,
274
275 #[serde(default)]
276 timestamp: [ManifestSmallInt<u32>; 2],
277
278 #[serde(default)]
279 binding_value: [ManifestSmallInt<u32>; 8],
280
281 #[serde(default)]
282 max_key_version: ManifestSmallInt<u32>,
283
284 #[serde(default)]
285 code_start: ManifestSmallInt<u32>,
286
287 #[serde(default)]
288 code_end: ManifestSmallInt<u32>,
289
290 #[serde(default)]
291 entry_point: ManifestSmallInt<u32>,
292
293 #[serde(default)]
294 extensions: [ManifestExtTableEntryDef; CHIP_MANIFEST_EXT_TABLE_COUNT],
295
296 #[serde(default)]
297 pub extension_params: Vec<ManifestExtEntrySpec>,
298}
299
300impl ManifestPacked<Manifest> for ManifestSpec {
301 fn unpack(self, _name: &'static str) -> Result<Manifest> {
302 Ok(Manifest {
303 signature: self.signature.unpack("signature")?.try_into()?,
306 reserved_signature: Default::default(),
307 reserved_unsigned: Default::default(),
308 usage_constraints: self.usage_constraints.unpack("usage_constraints")?,
309 pub_key: self.pub_key.unpack("pub_key")?.try_into()?,
310 reserved_public_key: Default::default(),
311 reserved: Default::default(),
312 address_translation: self.address_translation.unpack("address_translation")?,
313 identifier: self.identifier.unpack("identifier")?,
314 manifest_version: self.manifest_version.unpack("manifest_version")?,
315 signed_region_end: self.signed_region_end.unpack("signed_region_end")?,
316 length: self.length.unpack("length")?,
317 version_major: self.version_major.unpack("version_major")?,
318 version_minor: self.version_minor.unpack("version_minor")?,
319 security_version: self.security_version.unpack("security_version")?,
320 timestamp: self.timestamp.unpack("timestamp")?.try_into()?,
321 binding_value: self.binding_value.unpack("binding_value")?.try_into()?,
322 max_key_version: self.max_key_version.unpack("max_key_version")?,
323 code_start: self.code_start.unpack("code_start")?,
324 code_end: self.code_end.unpack("code_end")?,
325 entry_point: self.entry_point.unpack("entry_point")?,
326 extensions: self.extensions.unpack("extensions")?.into(),
327 })
328 }
329
330 fn overwrite(&mut self, o: ManifestSpec) {
331 self.signature.overwrite(o.signature);
332 self.usage_constraints.overwrite(o.usage_constraints);
333 self.pub_key.overwrite(o.pub_key);
334 self.address_translation.overwrite(o.address_translation);
335 self.identifier.overwrite(o.identifier);
336 self.manifest_version.overwrite(o.manifest_version);
337 self.signed_region_end.overwrite(o.signed_region_end);
338 self.length.overwrite(o.length);
339 self.version_major.overwrite(o.version_major);
340 self.version_minor.overwrite(o.version_minor);
341 self.security_version.overwrite(o.security_version);
342 self.timestamp.overwrite(o.timestamp);
343 self.binding_value.overwrite(o.binding_value);
344 self.max_key_version.overwrite(o.max_key_version);
345 self.code_start.overwrite(o.code_start);
346 self.code_end.overwrite(o.code_end);
347 self.entry_point.overwrite(o.entry_point);
348 self.extensions.overwrite(o.extensions);
349 }
352}
353
354impl TryInto<Manifest> for ManifestSpec {
355 type Error = anyhow::Error;
356
357 fn try_into(self) -> Result<Manifest> {
358 self.unpack("")
359 }
360}
361
362impl TryFrom<&Manifest> for ManifestSpec {
363 type Error = anyhow::Error;
364
365 fn try_from(o: &Manifest) -> Result<Self> {
366 Ok(ManifestSpec {
367 signature: (&o.signature).try_into()?,
368 usage_constraints: (&o.usage_constraints).try_into()?,
369 pub_key: (&o.pub_key).try_into()?,
370 address_translation: (&o.address_translation).into(),
371 identifier: (&o.identifier).into(),
372 manifest_version: (&o.manifest_version).try_into()?,
373 signed_region_end: (&o.signed_region_end).into(),
374 length: (&o.length).into(),
375 version_major: (&o.version_major).into(),
376 version_minor: (&o.version_minor).into(),
377 security_version: (&o.security_version).into(),
378 timestamp: (&o.timestamp).into(),
379 binding_value: (&o.binding_value).into(),
380 max_key_version: (&o.max_key_version).into(),
381 code_start: (&o.code_start).into(),
382 code_end: (&o.code_end).into(),
383 entry_point: (&o.entry_point).into(),
384 extensions: (&o.extensions).into(),
385
386 extension_params: Vec::new(),
388 })
389 }
390}
391
392manifest_def! {
393 pub struct ManifestUsageConstraintsDef {
394 selector_bits: ManifestSmallInt<u32>,
395 device_id: [ManifestSmallInt<u32>; 8],
396 manuf_state_creator: ManifestSmallInt<u32>,
397 manuf_state_owner: ManifestSmallInt<u32>,
398 life_cycle_state: ManifestSmallInt<u32>,
399 }, ManifestUsageConstraints
400}
401
402manifest_def! {
403 pub struct ManifestVersionDef {
404 minor: ManifestSmallInt<u16>,
405 major: ManifestSmallInt<u16>,
406 }, ManifestVersion
407}
408
409#[derive(Clone, Default, Deserialize, Serialize, Debug)]
410#[serde(untagged)]
411enum ManifestExtEntryVar {
412 #[default]
413 None,
414 Name(ManifestExtId),
415 IdOffset {
416 identifier: ManifestExtId,
417 offset: u32,
418 },
419}
420
421#[derive(Clone, Default, Deserialize, Serialize, Debug)]
422pub struct ManifestExtTableEntryDef(ManifestExtEntryVar);
423
424impl TryFrom<ManifestSigverifyBuffer> for SigverifyBuffer {
425 type Error = anyhow::Error;
426
427 fn try_from(buffer: ManifestSigverifyBuffer) -> Result<SigverifyBuffer> {
428 if buffer.eq(&ManifestSigverifyBuffer::from_le_bytes([0])?) {
429 Ok(SigverifyBuffer {
432 data: le_slice_to_arr(&[0]),
433 })
434 } else {
435 Ok(SigverifyBuffer {
437 data: le_bytes_to_word_arr(&buffer.to_le_bytes())?,
438 })
439 }
440 }
441}
442
443pub(crate) fn le_bytes_to_word_arr<const N: usize>(bytes: &[u8]) -> Result<[u32; N]> {
444 Ok(le_slice_to_arr(
445 bytes
446 .chunks(4)
447 .map(|v| Ok(u32::from_le_bytes(le_slice_to_arr(v))))
448 .collect::<Result<Vec<u32>>>()?
449 .as_slice(),
450 ))
451}
452
453fn le_slice_to_arr<T: Default + Copy, const N: usize>(slice: &[T]) -> [T; N] {
458 let mut arr = [T::default(); N];
459 arr[..slice.len()].copy_from_slice(slice);
460 arr
461}
462
463impl TryFrom<[u32; 16]> for SigverifyBuffer {
464 type Error = anyhow::Error;
465
466 fn try_from(words: [u32; 16]) -> Result<SigverifyBuffer> {
467 Ok(SigverifyBuffer { data: words })
468 }
469}
470
471impl TryFrom<[u32; 8]> for KeymgrBindingValue {
472 type Error = anyhow::Error;
473
474 fn try_from(words: [u32; 8]) -> Result<KeymgrBindingValue> {
475 Ok(KeymgrBindingValue { data: words })
476 }
477}
478
479impl TryFrom<[u32; 2]> for Timestamp {
480 type Error = anyhow::Error;
481
482 fn try_from(words: [u32; 2]) -> Result<Timestamp> {
483 Ok(Timestamp {
484 timestamp_low: words[0],
485 timestamp_high: words[1],
486 })
487 }
488}
489
490impl TryFrom<[u32; 8]> for LifecycleDeviceId {
491 type Error = anyhow::Error;
492
493 fn try_from(words: [u32; 8]) -> Result<LifecycleDeviceId> {
494 Ok(LifecycleDeviceId { device_id: words })
495 }
496}
497
498impl TryFrom<SigverifyBuffer> for ManifestSigverifyBigInt {
499 type Error = anyhow::Error;
500
501 fn try_from(o: SigverifyBuffer) -> Result<ManifestSigverifyBigInt> {
502 (&o).try_into()
503 }
504}
505
506impl TryFrom<&SigverifyBuffer> for ManifestSigverifyBigInt {
507 type Error = anyhow::Error;
508
509 fn try_from(o: &SigverifyBuffer) -> Result<ManifestSigverifyBigInt> {
510 let rsa = ManifestSigverifyBuffer::from_le_bytes(o.data.as_bytes())?;
511 Ok(ManifestSigverifyBigInt(Some(HexEncoded(rsa))))
512 }
513}
514
515impl<T> From<&T> for ManifestSmallInt<T>
516where
517 T: ParseInt + fmt::LowerHex + Copy,
518{
519 fn from(o: &T) -> ManifestSmallInt<T> {
520 ManifestSmallInt(Some(HexEncoded(*o)))
521 }
522}
523
524impl From<&KeymgrBindingValue> for [ManifestSmallInt<u32>; 8] {
525 fn from(o: &KeymgrBindingValue) -> [ManifestSmallInt<u32>; 8] {
526 o.data.map(|v| ManifestSmallInt(Some(HexEncoded(v))))
527 }
528}
529impl From<&Timestamp> for [ManifestSmallInt<u32>; 2] {
530 fn from(o: &Timestamp) -> [ManifestSmallInt<u32>; 2] {
531 [
532 ManifestSmallInt(Some(HexEncoded(o.timestamp_low))),
533 ManifestSmallInt(Some(HexEncoded(o.timestamp_high))),
534 ]
535 }
536}
537
538impl From<&LifecycleDeviceId> for [ManifestSmallInt<u32>; 8] {
539 fn from(o: &LifecycleDeviceId) -> [ManifestSmallInt<u32>; 8] {
540 o.device_id.map(|v| ManifestSmallInt(Some(HexEncoded(v))))
541 }
542}
543
544impl From<&ManifestExtTableEntry> for ManifestExtTableEntryDef {
545 fn from(o: &ManifestExtTableEntry) -> ManifestExtTableEntryDef {
546 ManifestExtTableEntryDef(ManifestExtEntryVar::IdOffset {
547 identifier: ManifestExtId(o.identifier),
548 offset: o.offset,
549 })
550 }
551}
552
553impl From<[ManifestExtTableEntry; CHIP_MANIFEST_EXT_TABLE_COUNT]> for ManifestExtTable {
554 fn from(o: [ManifestExtTableEntry; CHIP_MANIFEST_EXT_TABLE_COUNT]) -> ManifestExtTable {
555 ManifestExtTable { entries: o }
556 }
557}
558
559impl From<&ManifestExtTable> for [ManifestExtTableEntryDef; CHIP_MANIFEST_EXT_TABLE_COUNT] {
560 fn from(o: &ManifestExtTable) -> [ManifestExtTableEntryDef; CHIP_MANIFEST_EXT_TABLE_COUNT] {
561 o.entries.map(|v| (&v).into())
562 }
563}
564
565#[cfg(test)]
566mod tests {
567 use super::*;
568 use crate::util::testdata;
569 use deser_hjson::from_str;
570
571 #[test]
572 fn test_manifest_from_hjson() {
573 let def: ManifestSpec =
574 from_str(&std::fs::read_to_string(testdata("image/manifest.hjson")).unwrap()).unwrap();
575
576 let _: Manifest = def.try_into().unwrap();
577 }
578
579 #[test]
580 fn test_manifest_from_hjson_missing() {
581 let def: ManifestSpec =
582 from_str(&std::fs::read_to_string(testdata("image/manifest_missing.hjson")).unwrap())
583 .unwrap();
584
585 let res: Result<Manifest> = def.try_into();
586 assert!(res.is_err())
587 }
588
589 #[test]
590 fn test_manifest_overwrite() {
591 let mut base: ManifestSpec =
592 from_str(&std::fs::read_to_string(testdata("image/manifest.hjson")).unwrap()).unwrap();
593 let other = ManifestSpec {
594 identifier: from_str("0xabcd").unwrap(),
595 binding_value: from_str(stringify!(["0", "1", "2", "3", "4", "5", "6", "7"])).unwrap(),
596 ..Default::default()
597 };
598 base.overwrite(other);
599 assert_eq!(base.identifier.0.unwrap().0, 0xabcd);
600 assert_eq!(
601 base.binding_value.map(|v| v.0.unwrap().0)[..],
602 [0, 1, 2, 3, 4, 5, 6, 7]
603 );
604
605 assert_eq!(base.address_translation.0.unwrap().0, 0x739);
607 }
608
609 #[test]
610 fn test_manifest_convert() {
611 let def1: ManifestSpec =
612 from_str(&std::fs::read_to_string(testdata("image/manifest.hjson")).unwrap()).unwrap();
613 let def2 = def1.clone();
614
615 let bin1: Manifest = def1.try_into().unwrap();
616 let bin2: Manifest = def2.try_into().unwrap();
617
618 let redef: ManifestSpec = (&bin1).try_into().unwrap();
619 let rebin: Manifest = redef.try_into().unwrap();
620 assert_eq!(bin2.as_bytes(), rebin.as_bytes());
621 }
622}