image4/manifest/
owned.rs

1use super::{CertChain, ManifestRef, UnsignedManifestRef};
2use crate::{
3    manifest::AnyManifestRef,
4    property::{Dict, Value},
5    Tag,
6};
7use alloc::{collections::BTreeMap, vec::Vec};
8use der::{
9    asn1::OctetString,
10    referenced::{OwnedToRef, RefToOwned},
11    DecodeValue, EncodeValue, FixedTag, Header, Length, Reader, Writer,
12};
13#[cfg(feature = "signature")]
14use {
15    super::SigningError,
16    signature::{SignatureEncoding, Signer},
17};
18
19/// A signed Image4 manifest that owns its contents.
20///
21/// # Validation
22///
23/// The manifest's body, signature and certificate chain **ARE NOT** required to be valid. Types
24/// representing the body and the certificate chain were designed for lazy decoding and thus **DO
25/// NOT VERIFY** their contents.
26///
27/// Currently the only way to check that a [`Manifest`] contains valid data is as follows:
28///
29/// ```
30/// # use der::Decode;
31/// # use image4::Manifest;
32/// # fn main() -> der::Result<()> {
33/// # let bytes = include_bytes!("../../tests/data/apticket.der");
34/// let manifest = Manifest::from_der(bytes)?;
35///
36/// let _body = manifest.decode_body()?;
37/// let _certs = manifest.cert_chain().decode_body()?;
38/// # Ok(())
39/// # }
40/// ```
41///
42/// This **DOES NOT** check that the signature is valid and only ensures that the manifest is
43/// properly encoded.
44#[derive(Clone, Debug)]
45#[cfg_attr(test, derive(Eq, PartialEq))]
46pub struct Manifest {
47    pub(super) tbs: UnsignedManifest,
48    pub(super) signature: OctetString,
49    pub(super) cert_chain: CertChain,
50}
51
52impl Manifest {
53    /// Builds an Image4 property list for a manifest body from a [`BTreeMap`] describing its
54    /// properties and signs the encoded body with the provided key and certificate chain.
55    ///
56    /// # Certificate chain validity
57    ///
58    /// The certificate chain isn't validated anyhow and may be completely unrelated to the signing
59    /// key or even contain invalid X.509 certificates. Validating the certificate chain is the
60    /// caller's responsibility.
61    #[cfg(feature = "signature")]
62    pub fn encode_and_sign<K: Signer<S>, S: SignatureEncoding>(
63        body: &BTreeMap<Tag, Value>,
64        key: &K,
65        cert_chain: impl Into<CertChain>,
66    ) -> Result<Self, SigningError> {
67        let body = Dict::encode_from(body)?;
68        Self::sign_encoded(body, key, cert_chain)
69    }
70
71    /// Signs an encoded body with the provided key and certificate chain and produces a signed
72    /// manifest.
73    ///
74    /// # Certificate chain validity
75    ///
76    /// The certificate chain isn't validated anyhow and may be completely unrelated to the signing
77    /// key or even contain invalid X.509 certificates. Validating the certificate chain is the
78    /// caller's responsibility.
79    #[cfg(feature = "signature")]
80    pub fn sign_encoded<K: Signer<S>, S: SignatureEncoding>(
81        body: impl Into<Dict>,
82        key: &K,
83        cert_chain: impl Into<CertChain>,
84    ) -> Result<Self, SigningError> {
85        let body = body.into();
86        let signature = key.try_sign(body.as_bytes())?;
87
88        Ok(Manifest {
89            tbs: UnsignedManifest { version: 0, body },
90            signature: OctetString::new(signature.to_vec())?,
91            cert_chain: cert_chain.into(),
92        })
93    }
94
95    /// Decodes the part of a manifest after the magic string.
96    ///
97    /// May be used when it is required to first identify what kind of buffer you're looking at by
98    /// checking the magic string.
99    pub fn decode_after_magic<'a, R: Reader<'a>>(decoder: &mut R) -> der::Result<Self> {
100        Ok(ManifestRef::decode_after_magic(decoder)?.into())
101    }
102
103    /// Returns the manifest's version.
104    pub fn version(&self) -> u32 {
105        self.tbs.version
106    }
107
108    /// Returns a reference to the manifest's body.
109    pub fn body(&self) -> &Dict {
110        &self.tbs.body
111    }
112
113    /// Decodes the manifest's body into a [`BTreeMap`] describing its properties.
114    pub fn decode_body(&self) -> der::Result<BTreeMap<Tag, Value>> {
115        self.tbs.decode_body()
116    }
117
118    /// Encodes new manifest body from a [`BTreeMap`] which describes the properties.
119    pub fn encode_body(&mut self, body: &BTreeMap<Tag, Value>) -> der::Result<()> {
120        self.tbs.encode_body(body)
121    }
122
123    /// Returns a reference to the signature data.
124    pub fn signature(&self) -> &[u8] {
125        self.signature.as_bytes()
126    }
127
128    /// Sets a new signature.
129    pub fn set_signature(&mut self, signature: Vec<u8>) -> der::Result<()> {
130        self.signature = OctetString::new(signature)?;
131        Ok(())
132    }
133
134    /// Returns an immutable reference to the encoded certificate chain.
135    pub fn cert_chain(&self) -> &CertChain {
136        &self.cert_chain
137    }
138
139    /// Returns a mutable reference to the encoded certificate chain.
140    pub fn cert_chain_mut(&mut self) -> &mut CertChain {
141        &mut self.cert_chain
142    }
143
144    /// Sets a new certificate chain.
145    pub fn set_cert_chain(&mut self, cert_chain: CertChain) {
146        self.cert_chain = cert_chain;
147    }
148
149    /// Resigns a signed manifest with the specified key and certificate chain.
150    ///
151    /// # Certificate chain validity
152    ///
153    /// The certificate chain isn't validated anyhow and may be completely unrelated to the signing
154    /// key or even contain invalid X.509 certificates. Validating the certificate chain is the
155    /// caller's responsibility.
156    #[cfg(feature = "signature")]
157    pub fn resign<K: Signer<S>, S: SignatureEncoding>(
158        &mut self,
159        key: &K,
160        cert_chain: impl Into<CertChain>,
161    ) -> Result<(), SigningError> {
162        let signature = key.try_sign(self.tbs.body.as_bytes())?;
163
164        self.signature = OctetString::new(signature.to_vec())?;
165        self.cert_chain = cert_chain.into();
166
167        Ok(())
168    }
169}
170
171impl FixedTag for Manifest {
172    const TAG: der::Tag = der::Tag::Sequence;
173}
174
175impl<'a> DecodeValue<'a> for Manifest {
176    fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> der::Result<Self> {
177        ManifestRef::decode_value(reader, header).map(Manifest::from)
178    }
179}
180
181impl EncodeValue for Manifest {
182    fn value_len(&self) -> der::Result<Length> {
183        ManifestRef::from(self).value_len()
184    }
185
186    fn encode_value(&self, encoder: &mut impl Writer) -> der::Result<()> {
187        ManifestRef::from(self).encode_value(encoder)
188    }
189}
190
191impl From<ManifestRef<'_>> for Manifest {
192    fn from(value: ManifestRef<'_>) -> Self {
193        (&value).into()
194    }
195}
196
197impl From<&'_ ManifestRef<'_>> for Manifest {
198    fn from(value: &'_ ManifestRef<'_>) -> Self {
199        Self {
200            tbs: value.tbs.ref_to_owned(),
201            signature: value.signature.ref_to_owned(),
202            cert_chain: value.cert_chain.ref_to_owned(),
203        }
204    }
205}
206
207impl OwnedToRef for Manifest {
208    type Borrowed<'a> = ManifestRef<'a>;
209
210    fn owned_to_ref(&self) -> Self::Borrowed<'_> {
211        self.into()
212    }
213}
214
215impl AsRef<UnsignedManifest> for Manifest {
216    fn as_ref(&self) -> &UnsignedManifest {
217        &self.tbs
218    }
219}
220
221/// An unsigned Image4 manifest that owns its contents.
222///
223/// # Validation
224///
225/// The manifest's body **IS NOT** required to be valid.
226///
227/// Currently the only way to check that an [`UnsignedManifest`] contains valid data is to decode
228/// its body using the [`UnsignedManifest::decode_body`] method.
229#[derive(Clone, Debug)]
230#[cfg_attr(test, derive(Eq, PartialEq))]
231pub struct UnsignedManifest {
232    pub(super) version: u32,
233    pub(super) body: Dict,
234}
235
236impl UnsignedManifest {
237    /// Creates a new unsigned manifest from its body contents.
238    pub fn new(body: Dict) -> Self {
239        Self { version: 0, body }
240    }
241
242    /// Creates a bew unsigned manifest by encoding an Image4 property list.
243    pub fn encode_from(dict: &BTreeMap<Tag, Value>) -> der::Result<Self> {
244        Ok(Self {
245            version: 0,
246            body: Dict::encode_from(dict)?,
247        })
248    }
249
250    /// Decodes the part of an unsigned manifest after the magic string.
251    ///
252    /// May be used when it is required to first identify what kind of buffer you're looking at by
253    /// checking the magic string.
254    pub fn decode_after_magic<'a, R: Reader<'a>>(decoder: &mut R) -> der::Result<Self> {
255        Ok(UnsignedManifestRef::decode_after_magic(decoder)?.into())
256    }
257
258    /// Returns the manifest's version.
259    pub fn version(&self) -> u32 {
260        self.version
261    }
262
263    /// Returns a reference to the manifest's body.
264    pub fn body(&self) -> &Dict {
265        &self.body
266    }
267
268    /// Decodes the manifest's body into a [`BTreeMap`] describing its properties.
269    pub fn decode_body(&self) -> der::Result<BTreeMap<Tag, Value>> {
270        self.body.decode_owned()
271    }
272
273    /// Encodes new manifest body from a [`BTreeMap`] which describes the properties.
274    pub fn encode_body(&mut self, body: &BTreeMap<Tag, Value>) -> der::Result<()> {
275        self.body = Dict::encode_from(body)?;
276        Ok(())
277    }
278
279    /// Signs an unsigned manifest with the specified key and certificate chain.
280    ///
281    /// # Certificate chain validity
282    ///
283    /// The certificate chain isn't validated anyhow and may be completely unrelated to the signing
284    /// key or even contain invalid X.509 certificates. Validating the certificate chain is the
285    /// caller's responsibility.
286    #[cfg(feature = "signature")]
287    pub fn sign<K: Signer<S>, S: SignatureEncoding>(
288        self,
289        key: &K,
290        cert_chain: impl Into<CertChain>,
291    ) -> Result<Manifest, SigningError> {
292        let signature = key.try_sign(self.body.as_bytes())?;
293
294        Ok(Manifest {
295            tbs: self,
296            signature: OctetString::new(signature.to_vec())?,
297            cert_chain: cert_chain.into(),
298        })
299    }
300}
301
302impl FixedTag for UnsignedManifest {
303    const TAG: der::Tag = der::Tag::Sequence;
304}
305
306impl<'a> DecodeValue<'a> for UnsignedManifest {
307    fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> der::Result<Self> {
308        UnsignedManifestRef::decode_value(reader, header).map(From::from)
309    }
310}
311
312impl EncodeValue for UnsignedManifest {
313    fn value_len(&self) -> der::Result<Length> {
314        UnsignedManifestRef::from(self).value_len()
315    }
316
317    fn encode_value(&self, encoder: &mut impl Writer) -> der::Result<()> {
318        UnsignedManifestRef::from(self).encode_value(encoder)
319    }
320}
321
322impl From<Manifest> for UnsignedManifest {
323    fn from(value: Manifest) -> Self {
324        value.tbs
325    }
326}
327
328impl From<ManifestRef<'_>> for UnsignedManifest {
329    fn from(value: ManifestRef<'_>) -> Self {
330        (&value.tbs).into()
331    }
332}
333
334impl From<&'_ ManifestRef<'_>> for UnsignedManifest {
335    fn from(value: &'_ ManifestRef<'_>) -> Self {
336        (&value.tbs).into()
337    }
338}
339
340impl From<UnsignedManifestRef<'_>> for UnsignedManifest {
341    fn from(value: UnsignedManifestRef<'_>) -> Self {
342        (&value).into()
343    }
344}
345
346impl From<&'_ UnsignedManifestRef<'_>> for UnsignedManifest {
347    fn from(value: &'_ UnsignedManifestRef<'_>) -> Self {
348        Self {
349            version: value.version,
350            body: value.body.ref_to_owned(),
351        }
352    }
353}
354
355impl OwnedToRef for UnsignedManifest {
356    type Borrowed<'a> = UnsignedManifestRef<'a>;
357
358    fn owned_to_ref(&self) -> Self::Borrowed<'_> {
359        self.into()
360    }
361}
362
363/// Either a signed or an unsigned Image4 manifest that owns its contents.
364#[derive(Clone, Debug)]
365#[cfg_attr(test, derive(Eq, PartialEq))]
366pub enum AnyManifest {
367    /// A signed manifest.
368    Signed(Manifest),
369    /// An unsigned manifest.
370    Unsigned(UnsignedManifest),
371}
372
373impl AnyManifest {
374    /// Decodes the part of a manifest after the magic string.
375    ///
376    /// May be used when it is required to first identify what kind of buffer you're looking at by
377    /// checking the magic string.
378    ///
379    /// See docs for [`AnyManifestRef::decode_after_magic`] for more info.
380    pub fn decode_after_magic<'a, R: Reader<'a>>(decoder: &mut R) -> der::Result<Self> {
381        Ok(UnsignedManifestRef::decode_after_magic(decoder)?.into())
382    }
383
384    /// Returns the manifest's version.
385    pub fn version(&self) -> u32 {
386        match self {
387            AnyManifest::Signed(m) => m.version(),
388            AnyManifest::Unsigned(m) => m.version(),
389        }
390    }
391
392    /// Decodes the manifest's body into a [`BTreeMap`] describing its properties.
393    pub fn decode_body(&self) -> der::Result<BTreeMap<Tag, Value>> {
394        match self {
395            AnyManifest::Signed(m) => m.decode_body(),
396            AnyManifest::Unsigned(m) => m.decode_body(),
397        }
398    }
399
400    /// Encodes new manifest body from a [`BTreeMap`] which describes the properties.
401    pub fn encode_body(&mut self, body: &BTreeMap<Tag, Value>) -> der::Result<()> {
402        match self {
403            AnyManifest::Signed(m) => m.encode_body(body),
404            AnyManifest::Unsigned(m) => m.encode_body(body),
405        }
406    }
407}
408
409impl From<Manifest> for AnyManifest {
410    fn from(value: Manifest) -> Self {
411        Self::Signed(value)
412    }
413}
414
415impl From<UnsignedManifest> for AnyManifest {
416    fn from(value: UnsignedManifest) -> Self {
417        Self::Unsigned(value)
418    }
419}
420
421impl From<UnsignedManifestRef<'_>> for AnyManifest {
422    fn from(value: UnsignedManifestRef<'_>) -> Self {
423        (&value).into()
424    }
425}
426
427impl From<&'_ UnsignedManifestRef<'_>> for AnyManifest {
428    fn from(value: &'_ UnsignedManifestRef<'_>) -> Self {
429        Self::Unsigned(value.into())
430    }
431}
432
433impl From<ManifestRef<'_>> for AnyManifest {
434    fn from(value: ManifestRef<'_>) -> Self {
435        (&value).into()
436    }
437}
438
439impl From<&'_ ManifestRef<'_>> for AnyManifest {
440    fn from(value: &'_ ManifestRef<'_>) -> Self {
441        Self::Signed(value.into())
442    }
443}
444
445impl From<AnyManifestRef<'_>> for AnyManifest {
446    fn from(value: AnyManifestRef<'_>) -> Self {
447        (&value).into()
448    }
449}
450
451impl From<&'_ AnyManifestRef<'_>> for AnyManifest {
452    fn from(value: &'_ AnyManifestRef<'_>) -> Self {
453        match value {
454            AnyManifestRef::Signed(m) => Self::Signed(m.into()),
455            AnyManifestRef::Unsigned(m) => Self::Unsigned(m.into()),
456        }
457    }
458}
459
460impl OwnedToRef for AnyManifest {
461    type Borrowed<'a> = AnyManifestRef<'a>;
462
463    fn owned_to_ref(&self) -> Self::Borrowed<'_> {
464        self.into()
465    }
466}
467
468impl AsRef<UnsignedManifest> for AnyManifest {
469    fn as_ref(&self) -> &UnsignedManifest {
470        match self {
471            AnyManifest::Signed(m) => &m.tbs,
472            AnyManifest::Unsigned(m) => m,
473        }
474    }
475}