1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
//! Contains the [`RestoreInfo`] type that represents Image4 restore info (an IM4R file).

use crate::util;
use core::ops::Add;
use der::{asn1::Ia5StringRef, Decode, Encode, EncodeValue, FixedTag, Length, Reader, Writer};

/// Restore info that might be present in an Image4 file.
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub struct RestoreInfo {
    /// The seed used to generate the boot nonce in the corresponding manifest.
    pub nonce_seed: u64,
}

impl RestoreInfo {
    /// Decodes the part of encoded restore info after the magic string.
    ///
    /// May be used when it is required to first identify what kind of image you're looking at by
    /// checking the magic string.
    pub fn decode_after_magic<'a, R: Reader<'a>>(decoder: &mut R) -> der::Result<Self> {
        Ok(RestoreInfo {
            nonce_seed: decoder.decode()?,
        })
    }
}

impl<'a> Decode<'a> for RestoreInfo {
    fn decode<R: Reader<'a>>(decoder: &mut R) -> der::Result<Self> {
        decoder.sequence(|nested_decoder| {
            util::decode_and_check_magic(nested_decoder, b"IM4R")?;
            RestoreInfo::decode_after_magic(nested_decoder)
        })
    }
}

impl EncodeValue for RestoreInfo {
    fn value_len(&self) -> der::Result<Length> {
        Ia5StringRef::new(&b"IM4R")?
            .encoded_len()?
            .add(self.nonce_seed.encoded_len()?)
    }

    fn encode_value(&self, encoder: &mut impl Writer) -> der::Result<()> {
        Ia5StringRef::new(&b"IM4R")?.encode(encoder)?;
        self.nonce_seed.encode(encoder)
    }
}

impl FixedTag for RestoreInfo {
    const TAG: der::Tag = der::Tag::Sequence;
}