blob: 071af0ca527a6b6e163de315c8909e78c5f1940d [file] [log] [blame]
David Brown187dd882017-07-11 11:15:23 -06001//! TLV Support
2//!
3//! mcuboot images are followed immediately by a list of TLV items that contain integrity
4//! information about the image. Their generation is made a little complicated because the size of
5//! the TLV block is in the image header, which is included in the hash. Since some signatures can
6//! vary in size, we just make them the largest size possible.
7//!
8//! Because of this header, we have to make two passes. The first pass will compute the size of
9//! the TLV, and the second pass will build the data for the TLV.
10
11use crypto::digest::Digest;
12use crypto::sha2::Sha256;
13
14#[derive(EnumFlags, Copy, Clone, Debug)]
15#[repr(u32)]
16#[allow(non_camel_case_types)]
17pub enum Flags {
18 PIC = 0x000001,
19 SHA256 = 0x000002,
20 PKCS15_RSA2048_SHA256 = 0x000004,
21 ECDSA224_SHA256 = 0x000008,
22 NON_BOOTABLE = 0x000010,
23 ECDSA256_SHA256 = 0x000020,
24 PKCS1_PSS_RSA2048_SHA256 = 0x000040,
25}
26
27#[repr(u8)]
28#[derive(Copy, Clone, PartialEq, Eq)]
29#[allow(dead_code)] // TODO: For now
30pub enum TlvKinds {
31 SHA256 = 1,
32 RSA2048 = 2,
33 ECDSA224 = 3,
34 ECDSA256 = 4,
35}
36
37pub struct TlvGen {
38 flags: Flags,
39 kinds: Vec<TlvKinds>,
40 size: u16,
41 hasher: Sha256,
42}
43
44impl TlvGen {
45 /// Construct a new tlv generator that will only contain a hash of the data.
46 pub fn new_hash_only() -> TlvGen {
47 TlvGen {
48 flags: Flags::SHA256,
49 kinds: vec![TlvKinds::SHA256],
50 size: 4 + 32,
51 hasher: Sha256::new(),
52 }
53 }
54
55 /// Retrieve the header flags for this configuration. This can be called at any time.
56 pub fn get_flags(&self) -> u32 {
57 self.flags as u32
58 }
59
60 /// Retrieve the size that the TLV will occupy. This can be called at any time.
61 pub fn get_size(&self) -> u16 {
62 self.size
63 }
64
65 /// Add bytes to the covered hash.
66 pub fn add_bytes(&mut self, bytes: &[u8]) {
67 self.hasher.input(bytes);
68 }
69
70 /// Compute the TLV given the specified block of data.
71 pub fn make_tlv(mut self) -> Vec<u8> {
72 let mut result: Vec<u8> = vec![];
73
74 if self.kinds.contains(&TlvKinds::SHA256) {
75 let hash_size = self.hasher.output_bytes();
76 assert!(hash_size == 32); // Assumption made.
77
78 let mut hash = vec![0; hash_size];
79
80 self.hasher.result(&mut hash);
81
82 result.push(TlvKinds::SHA256 as u8);
83 result.push(0);
84 result.push(32);
85 result.push(0);
86 result.append(&mut hash);
87 }
88
89 result
90 }
91}