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 3072);
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 usage_constraints: self.usage_constraints.unpack("usage_constraints")?,
307 pub_key: self.pub_key.unpack("pub_key")?.try_into()?,
308 address_translation: self.address_translation.unpack("address_translation")?,
309 identifier: self.identifier.unpack("identifier")?,
310 manifest_version: self.manifest_version.unpack("manifest_version")?,
311 signed_region_end: self.signed_region_end.unpack("signed_region_end")?,
312 length: self.length.unpack("length")?,
313 version_major: self.version_major.unpack("version_major")?,
314 version_minor: self.version_minor.unpack("version_minor")?,
315 security_version: self.security_version.unpack("security_version")?,
316 timestamp: self.timestamp.unpack("timestamp")?.try_into()?,
317 binding_value: self.binding_value.unpack("binding_value")?.try_into()?,
318 max_key_version: self.max_key_version.unpack("max_key_version")?,
319 code_start: self.code_start.unpack("code_start")?,
320 code_end: self.code_end.unpack("code_end")?,
321 entry_point: self.entry_point.unpack("entry_point")?,
322 extensions: self.extensions.unpack("extensions")?.into(),
323 })
324 }
325
326 fn overwrite(&mut self, o: ManifestSpec) {
327 self.signature.overwrite(o.signature);
328 self.usage_constraints.overwrite(o.usage_constraints);
329 self.pub_key.overwrite(o.pub_key);
330 self.address_translation.overwrite(o.address_translation);
331 self.identifier.overwrite(o.identifier);
332 self.manifest_version.overwrite(o.manifest_version);
333 self.signed_region_end.overwrite(o.signed_region_end);
334 self.length.overwrite(o.length);
335 self.version_major.overwrite(o.version_major);
336 self.version_minor.overwrite(o.version_minor);
337 self.security_version.overwrite(o.security_version);
338 self.timestamp.overwrite(o.timestamp);
339 self.binding_value.overwrite(o.binding_value);
340 self.max_key_version.overwrite(o.max_key_version);
341 self.code_start.overwrite(o.code_start);
342 self.code_end.overwrite(o.code_end);
343 self.entry_point.overwrite(o.entry_point);
344 self.extensions.overwrite(o.extensions);
345 }
348}
349
350impl TryInto<Manifest> for ManifestSpec {
351 type Error = anyhow::Error;
352
353 fn try_into(self) -> Result<Manifest> {
354 self.unpack("")
355 }
356}
357
358impl TryFrom<&Manifest> for ManifestSpec {
359 type Error = anyhow::Error;
360
361 fn try_from(o: &Manifest) -> Result<Self> {
362 Ok(ManifestSpec {
363 signature: (&o.signature).try_into()?,
364 usage_constraints: (&o.usage_constraints).try_into()?,
365 pub_key: (&o.pub_key).try_into()?,
366 address_translation: (&o.address_translation).into(),
367 identifier: (&o.identifier).into(),
368 manifest_version: (&o.manifest_version).try_into()?,
369 signed_region_end: (&o.signed_region_end).into(),
370 length: (&o.length).into(),
371 version_major: (&o.version_major).into(),
372 version_minor: (&o.version_minor).into(),
373 security_version: (&o.security_version).into(),
374 timestamp: (&o.timestamp).into(),
375 binding_value: (&o.binding_value).into(),
376 max_key_version: (&o.max_key_version).into(),
377 code_start: (&o.code_start).into(),
378 code_end: (&o.code_end).into(),
379 entry_point: (&o.entry_point).into(),
380 extensions: (&o.extensions).into(),
381
382 extension_params: Vec::new(),
384 })
385 }
386}
387
388manifest_def! {
389 pub struct ManifestUsageConstraintsDef {
390 selector_bits: ManifestSmallInt<u32>,
391 device_id: [ManifestSmallInt<u32>; 8],
392 manuf_state_creator: ManifestSmallInt<u32>,
393 manuf_state_owner: ManifestSmallInt<u32>,
394 life_cycle_state: ManifestSmallInt<u32>,
395 }, ManifestUsageConstraints
396}
397
398manifest_def! {
399 pub struct ManifestVersionDef {
400 minor: ManifestSmallInt<u16>,
401 major: ManifestSmallInt<u16>,
402 }, ManifestVersion
403}
404
405#[derive(Clone, Default, Deserialize, Serialize, Debug)]
406#[serde(untagged)]
407enum ManifestExtEntryVar {
408 #[default]
409 None,
410 Name(ManifestExtId),
411 IdOffset {
412 identifier: ManifestExtId,
413 offset: u32,
414 },
415}
416
417#[derive(Clone, Default, Deserialize, Serialize, Debug)]
418pub struct ManifestExtTableEntryDef(ManifestExtEntryVar);
419
420impl TryFrom<ManifestSigverifyBuffer> for SigverifyBuffer {
421 type Error = anyhow::Error;
422
423 fn try_from(buffer: ManifestSigverifyBuffer) -> Result<SigverifyBuffer> {
424 if buffer.eq(&ManifestSigverifyBuffer::from_le_bytes([0])?) {
425 Ok(SigverifyBuffer {
428 data: le_slice_to_arr(&[0]),
429 })
430 } else {
431 Ok(SigverifyBuffer {
433 data: le_bytes_to_word_arr(&buffer.to_le_bytes())?,
434 })
435 }
436 }
437}
438
439pub(crate) fn le_bytes_to_word_arr<const N: usize>(bytes: &[u8]) -> Result<[u32; N]> {
440 Ok(le_slice_to_arr(
441 bytes
442 .chunks(4)
443 .map(|v| Ok(u32::from_le_bytes(le_slice_to_arr(v))))
444 .collect::<Result<Vec<u32>>>()?
445 .as_slice(),
446 ))
447}
448
449fn le_slice_to_arr<T: Default + Copy, const N: usize>(slice: &[T]) -> [T; N] {
454 let mut arr = [T::default(); N];
455 arr[..slice.len()].copy_from_slice(slice);
456 arr
457}
458
459impl TryFrom<[u32; 96]> for SigverifyBuffer {
460 type Error = anyhow::Error;
461
462 fn try_from(words: [u32; 96]) -> Result<SigverifyBuffer> {
463 Ok(SigverifyBuffer { data: words })
464 }
465}
466
467impl TryFrom<[u32; 8]> for KeymgrBindingValue {
468 type Error = anyhow::Error;
469
470 fn try_from(words: [u32; 8]) -> Result<KeymgrBindingValue> {
471 Ok(KeymgrBindingValue { data: words })
472 }
473}
474
475impl TryFrom<[u32; 2]> for Timestamp {
476 type Error = anyhow::Error;
477
478 fn try_from(words: [u32; 2]) -> Result<Timestamp> {
479 Ok(Timestamp {
480 timestamp_low: words[0],
481 timestamp_high: words[1],
482 })
483 }
484}
485
486impl TryFrom<[u32; 8]> for LifecycleDeviceId {
487 type Error = anyhow::Error;
488
489 fn try_from(words: [u32; 8]) -> Result<LifecycleDeviceId> {
490 Ok(LifecycleDeviceId { device_id: words })
491 }
492}
493
494impl TryFrom<SigverifyBuffer> for ManifestSigverifyBigInt {
495 type Error = anyhow::Error;
496
497 fn try_from(o: SigverifyBuffer) -> Result<ManifestSigverifyBigInt> {
498 (&o).try_into()
499 }
500}
501
502impl TryFrom<&SigverifyBuffer> for ManifestSigverifyBigInt {
503 type Error = anyhow::Error;
504
505 fn try_from(o: &SigverifyBuffer) -> Result<ManifestSigverifyBigInt> {
506 let rsa = ManifestSigverifyBuffer::from_le_bytes(o.data.as_bytes())?;
507 Ok(ManifestSigverifyBigInt(Some(HexEncoded(rsa))))
508 }
509}
510
511impl<T> From<&T> for ManifestSmallInt<T>
512where
513 T: ParseInt + fmt::LowerHex + Copy,
514{
515 fn from(o: &T) -> ManifestSmallInt<T> {
516 ManifestSmallInt(Some(HexEncoded(*o)))
517 }
518}
519
520impl From<&KeymgrBindingValue> for [ManifestSmallInt<u32>; 8] {
521 fn from(o: &KeymgrBindingValue) -> [ManifestSmallInt<u32>; 8] {
522 o.data.map(|v| ManifestSmallInt(Some(HexEncoded(v))))
523 }
524}
525impl From<&Timestamp> for [ManifestSmallInt<u32>; 2] {
526 fn from(o: &Timestamp) -> [ManifestSmallInt<u32>; 2] {
527 [
528 ManifestSmallInt(Some(HexEncoded(o.timestamp_low))),
529 ManifestSmallInt(Some(HexEncoded(o.timestamp_high))),
530 ]
531 }
532}
533
534impl From<&LifecycleDeviceId> for [ManifestSmallInt<u32>; 8] {
535 fn from(o: &LifecycleDeviceId) -> [ManifestSmallInt<u32>; 8] {
536 o.device_id.map(|v| ManifestSmallInt(Some(HexEncoded(v))))
537 }
538}
539
540impl From<&ManifestExtTableEntry> for ManifestExtTableEntryDef {
541 fn from(o: &ManifestExtTableEntry) -> ManifestExtTableEntryDef {
542 ManifestExtTableEntryDef(ManifestExtEntryVar::IdOffset {
543 identifier: ManifestExtId(o.identifier),
544 offset: o.offset,
545 })
546 }
547}
548
549impl From<[ManifestExtTableEntry; CHIP_MANIFEST_EXT_TABLE_COUNT]> for ManifestExtTable {
550 fn from(o: [ManifestExtTableEntry; CHIP_MANIFEST_EXT_TABLE_COUNT]) -> ManifestExtTable {
551 ManifestExtTable { entries: o }
552 }
553}
554
555impl From<&ManifestExtTable> for [ManifestExtTableEntryDef; CHIP_MANIFEST_EXT_TABLE_COUNT] {
556 fn from(o: &ManifestExtTable) -> [ManifestExtTableEntryDef; CHIP_MANIFEST_EXT_TABLE_COUNT] {
557 o.entries.map(|v| (&v).into())
558 }
559}
560
561#[cfg(test)]
562mod tests {
563 use super::*;
564 use crate::util::testdata;
565 use deser_hjson::from_str;
566
567 #[test]
568 fn test_manifest_from_hjson() {
569 let def: ManifestSpec =
570 from_str(&std::fs::read_to_string(testdata("image/manifest.hjson")).unwrap()).unwrap();
571
572 let _: Manifest = def.try_into().unwrap();
573 }
574
575 #[test]
576 fn test_manifest_from_hjson_missing() {
577 let def: ManifestSpec =
578 from_str(&std::fs::read_to_string(testdata("image/manifest_missing.hjson")).unwrap())
579 .unwrap();
580
581 let res: Result<Manifest> = def.try_into();
582 assert!(res.is_err())
583 }
584
585 #[test]
586 fn test_manifest_overwrite() {
587 let mut base: ManifestSpec =
588 from_str(&std::fs::read_to_string(testdata("image/manifest.hjson")).unwrap()).unwrap();
589 let other = ManifestSpec {
590 identifier: from_str("0xabcd").unwrap(),
591 binding_value: from_str(stringify!(["0", "1", "2", "3", "4", "5", "6", "7"])).unwrap(),
592 ..Default::default()
593 };
594 base.overwrite(other);
595 assert_eq!(base.identifier.0.unwrap().0, 0xabcd);
596 assert_eq!(
597 base.binding_value.map(|v| v.0.unwrap().0)[..],
598 [0, 1, 2, 3, 4, 5, 6, 7]
599 );
600
601 assert_eq!(base.address_translation.0.unwrap().0, 0x739);
603 }
604
605 #[test]
606 fn test_manifest_convert() {
607 let def1: ManifestSpec =
608 from_str(&std::fs::read_to_string(testdata("image/manifest.hjson")).unwrap()).unwrap();
609 let def2 = def1.clone();
610
611 let bin1: Manifest = def1.try_into().unwrap();
612 let bin2: Manifest = def2.try_into().unwrap();
613
614 let redef: ManifestSpec = (&bin1).try_into().unwrap();
615 let rebin: Manifest = redef.try_into().unwrap();
616 assert_eq!(bin2.as_bytes(), rebin.as_bytes());
617 }
618}