blob: ad0cce5170674f41659ff371450bd9427336c515 [file] [log] [blame]
David Brownc8d62012021-10-27 15:03:48 -06001// Copyright (c) 2017-2021 Linaro LTD
David Browne2acfae2020-01-21 16:45:01 -07002// Copyright (c) 2017-2020 JUUL Labs
Roland Mikhel75c7c312023-02-23 15:39:14 +01003// Copyright (c) 2021-2023 Arm Limited
David Browne2acfae2020-01-21 16:45:01 -07004//
5// SPDX-License-Identifier: Apache-2.0
6
David Brown187dd882017-07-11 11:15:23 -06007//! TLV Support
8//!
9//! mcuboot images are followed immediately by a list of TLV items that contain integrity
10//! information about the image. Their generation is made a little complicated because the size of
11//! the TLV block is in the image header, which is included in the hash. Since some signatures can
12//! vary in size, we just make them the largest size possible.
13//!
14//! Because of this header, we have to make two passes. The first pass will compute the size of
15//! the TLV, and the second pass will build the data for the TLV.
16
David Brown91d68632019-07-29 14:32:13 -060017use byteorder::{
18 LittleEndian, WriteBytesExt,
19};
David Brown9c6322f2021-08-19 13:03:39 -060020use cipher::FromBlockCipher;
David Brown8a4e23b2021-06-11 10:29:01 -060021use crate::caps::Caps;
David Brown7a81c4b2019-07-29 15:20:21 -060022use crate::image::ImageVersion;
Fabio Utzige84f0ef2019-11-22 12:29:32 -030023use log::info;
Fabio Utzig90f449e2019-10-24 07:43:53 -030024use ring::{digest, rand, agreement, hkdf, hmac};
Fabio Utzige84f0ef2019-11-22 12:29:32 -030025use ring::rand::SecureRandom;
Fabio Utzig05ab0142018-07-10 09:15:28 -030026use ring::signature::{
27 RsaKeyPair,
28 RSA_PSS_SHA256,
29 EcdsaKeyPair,
30 ECDSA_P256_SHA256_ASN1_SIGNING,
Fabio Utzig97710282019-05-24 17:44:49 -030031 Ed25519KeyPair,
Fabio Utzig05ab0142018-07-10 09:15:28 -030032};
David Brown9c6322f2021-08-19 13:03:39 -060033use aes::{
34 Aes128,
Fabio Utzig90f449e2019-10-24 07:43:53 -030035 Aes128Ctr,
David Brown9c6322f2021-08-19 13:03:39 -060036 Aes256,
Salome Thirot6fdbf552021-05-14 16:46:14 +010037 Aes256Ctr,
David Brown9c6322f2021-08-19 13:03:39 -060038 NewBlockCipher
39};
40use cipher::{
41 generic_array::GenericArray,
42 StreamCipher,
Fabio Utzig90f449e2019-10-24 07:43:53 -030043};
Fabio Utzig80fde2f2017-12-05 09:25:31 -020044use mcuboot_sys::c;
Salome Thirot6fdbf552021-05-14 16:46:14 +010045use typenum::{U16, U32};
David Brown187dd882017-07-11 11:15:23 -060046
David Brown69721182019-12-04 14:50:52 -070047#[repr(u16)]
David Brownc3898d62019-08-05 14:20:02 -060048#[derive(Copy, Clone, Debug, PartialEq, Eq)]
David Brown187dd882017-07-11 11:15:23 -060049#[allow(dead_code)] // TODO: For now
50pub enum TlvKinds {
David Brown43cda332017-09-01 09:53:23 -060051 KEYHASH = 0x01,
David Brown27648b82017-08-31 10:40:29 -060052 SHA256 = 0x10,
53 RSA2048 = 0x20,
David Brown27648b82017-08-31 10:40:29 -060054 ECDSA256 = 0x22,
Fabio Utzig39297432019-05-08 18:51:10 -030055 RSA3072 = 0x23,
Fabio Utzig97710282019-05-24 17:44:49 -030056 ED25519 = 0x24,
Roland Mikhel6205c102023-02-06 13:32:02 +010057 ECDSASIG = 0x25,
Fabio Utzig1e48b912018-09-18 09:04:18 -030058 ENCRSA2048 = 0x30,
Salome Thirot0f641972021-05-14 11:19:55 +010059 ENCKW = 0x31,
Fabio Utzig90f449e2019-10-24 07:43:53 -030060 ENCEC256 = 0x32,
Fabio Utzig3fa72ca2020-04-02 11:20:37 -030061 ENCX25519 = 0x33,
David Brown7a81c4b2019-07-29 15:20:21 -060062 DEPENDENCY = 0x40,
Fabio Utzig1e48b912018-09-18 09:04:18 -030063}
64
65#[allow(dead_code, non_camel_case_types)]
66pub enum TlvFlags {
67 PIC = 0x01,
68 NON_BOOTABLE = 0x02,
Salome Thirot6fdbf552021-05-14 16:46:14 +010069 ENCRYPTED_AES128 = 0x04,
Salome Thirot6fdbf552021-05-14 16:46:14 +010070 ENCRYPTED_AES256 = 0x08,
David Brownd8713a52021-10-22 16:27:23 -060071 RAM_LOAD = 0x20,
David Brown187dd882017-07-11 11:15:23 -060072}
73
David Brown43643dd2019-01-11 15:43:28 -070074/// A generator for manifests. The format of the manifest can be either a
75/// traditional "TLV" or a SUIT-style manifest.
76pub trait ManifestGen {
David Brownac46e262019-01-11 15:46:18 -070077 /// Retrieve the header magic value for this manifest type.
78 fn get_magic(&self) -> u32;
79
David Brown43643dd2019-01-11 15:43:28 -070080 /// Retrieve the flags value for this particular manifest type.
81 fn get_flags(&self) -> u32;
82
David Brown7a81c4b2019-07-29 15:20:21 -060083 /// Retrieve the number of bytes of this manifest that is "protected".
84 /// This field is stored in the outside image header instead of the
85 /// manifest header.
86 fn protect_size(&self) -> u16;
87
88 /// Add a dependency on another image.
89 fn add_dependency(&mut self, id: u8, version: &ImageVersion);
90
David Brown43643dd2019-01-11 15:43:28 -070091 /// Add a sequence of bytes to the payload that the manifest is
92 /// protecting.
93 fn add_bytes(&mut self, bytes: &[u8]);
94
David Browne90b13f2019-12-06 15:04:00 -070095 /// Set an internal flag indicating that the next `make_tlv` should
96 /// corrupt the signature.
97 fn corrupt_sig(&mut self);
98
David Brownef4f0742021-10-22 17:09:50 -060099 /// Estimate the size of the TLV. This can be called before the payload is added (but after
100 /// other information is added). Some of the signature algorithms can generate variable sized
101 /// data, and therefore, this can slightly overestimate the size.
102 fn estimate_size(&self) -> usize;
103
David Brown43643dd2019-01-11 15:43:28 -0700104 /// Construct the manifest for this payload.
105 fn make_tlv(self: Box<Self>) -> Vec<u8>;
Fabio Utzig90f449e2019-10-24 07:43:53 -0300106
Fabio Utzige84f0ef2019-11-22 12:29:32 -0300107 /// Generate a new encryption random key
108 fn generate_enc_key(&mut self);
Fabio Utzig90f449e2019-10-24 07:43:53 -0300109
110 /// Return the current encryption key
111 fn get_enc_key(&self) -> Vec<u8>;
David Brown43643dd2019-01-11 15:43:28 -0700112}
113
Fabio Utzig9a2b5de2019-11-22 12:50:02 -0300114#[derive(Debug, Default)]
David Brown187dd882017-07-11 11:15:23 -0600115pub struct TlvGen {
David Brown43cda332017-09-01 09:53:23 -0600116 flags: u32,
David Brown187dd882017-07-11 11:15:23 -0600117 kinds: Vec<TlvKinds>,
David Brown4243ab02017-07-11 12:24:23 -0600118 payload: Vec<u8>,
David Brown7a81c4b2019-07-29 15:20:21 -0600119 dependencies: Vec<Dependency>,
Fabio Utzig90f449e2019-10-24 07:43:53 -0300120 enc_key: Vec<u8>,
David Browne90b13f2019-12-06 15:04:00 -0700121 /// Should this signature be corrupted.
122 gen_corrupted: bool,
David Brown7a81c4b2019-07-29 15:20:21 -0600123}
124
David Brownc3898d62019-08-05 14:20:02 -0600125#[derive(Debug)]
David Brown7a81c4b2019-07-29 15:20:21 -0600126struct Dependency {
127 id: u8,
128 version: ImageVersion,
David Brown187dd882017-07-11 11:15:23 -0600129}
130
131impl TlvGen {
132 /// Construct a new tlv generator that will only contain a hash of the data.
David Brown7e701d82017-07-11 13:24:25 -0600133 #[allow(dead_code)]
David Brown187dd882017-07-11 11:15:23 -0600134 pub fn new_hash_only() -> TlvGen {
135 TlvGen {
David Brown187dd882017-07-11 11:15:23 -0600136 kinds: vec![TlvKinds::SHA256],
Fabio Utzig9a2b5de2019-11-22 12:50:02 -0300137 ..Default::default()
David Brown187dd882017-07-11 11:15:23 -0600138 }
139 }
140
David Brown7e701d82017-07-11 13:24:25 -0600141 #[allow(dead_code)]
142 pub fn new_rsa_pss() -> TlvGen {
143 TlvGen {
Fabio Utzig754438d2018-12-14 06:39:58 -0200144 kinds: vec![TlvKinds::SHA256, TlvKinds::RSA2048],
Fabio Utzig9a2b5de2019-11-22 12:50:02 -0300145 ..Default::default()
David Brown7e701d82017-07-11 13:24:25 -0600146 }
147 }
148
Fabio Utzig80fde2f2017-12-05 09:25:31 -0200149 #[allow(dead_code)]
Fabio Utzig39297432019-05-08 18:51:10 -0300150 pub fn new_rsa3072_pss() -> TlvGen {
151 TlvGen {
Fabio Utzig39297432019-05-08 18:51:10 -0300152 kinds: vec![TlvKinds::SHA256, TlvKinds::RSA3072],
Fabio Utzig9a2b5de2019-11-22 12:50:02 -0300153 ..Default::default()
Fabio Utzig39297432019-05-08 18:51:10 -0300154 }
155 }
156
157 #[allow(dead_code)]
Fabio Utzig80fde2f2017-12-05 09:25:31 -0200158 pub fn new_ecdsa() -> TlvGen {
159 TlvGen {
Fabio Utzig754438d2018-12-14 06:39:58 -0200160 kinds: vec![TlvKinds::SHA256, TlvKinds::ECDSA256],
Fabio Utzig9a2b5de2019-11-22 12:50:02 -0300161 ..Default::default()
Fabio Utzig80fde2f2017-12-05 09:25:31 -0200162 }
163 }
164
Fabio Utzig1e48b912018-09-18 09:04:18 -0300165 #[allow(dead_code)]
Roland Mikhel6205c102023-02-06 13:32:02 +0100166 pub fn new_generic_ecdsa() -> TlvGen {
167 TlvGen {
168 kinds: vec![TlvKinds::SHA256,TlvKinds::ECDSASIG],
169 ..Default::default()}
170 }
171
172 #[allow(dead_code)]
Fabio Utzig97710282019-05-24 17:44:49 -0300173 pub fn new_ed25519() -> TlvGen {
174 TlvGen {
Fabio Utzig97710282019-05-24 17:44:49 -0300175 kinds: vec![TlvKinds::SHA256, TlvKinds::ED25519],
Fabio Utzig9a2b5de2019-11-22 12:50:02 -0300176 ..Default::default()
Fabio Utzig97710282019-05-24 17:44:49 -0300177 }
178 }
179
180 #[allow(dead_code)]
Salome Thirot6fdbf552021-05-14 16:46:14 +0100181 pub fn new_enc_rsa(aes_key_size: u32) -> TlvGen {
182 let flag = if aes_key_size == 256 {
183 TlvFlags::ENCRYPTED_AES256 as u32
184 } else {
185 TlvFlags::ENCRYPTED_AES128 as u32
186 };
Fabio Utzig1e48b912018-09-18 09:04:18 -0300187 TlvGen {
Salome Thirot6fdbf552021-05-14 16:46:14 +0100188 flags: flag,
Fabio Utzig1e48b912018-09-18 09:04:18 -0300189 kinds: vec![TlvKinds::SHA256, TlvKinds::ENCRSA2048],
Fabio Utzig9a2b5de2019-11-22 12:50:02 -0300190 ..Default::default()
Fabio Utzig1e48b912018-09-18 09:04:18 -0300191 }
192 }
193
194 #[allow(dead_code)]
Salome Thirot6fdbf552021-05-14 16:46:14 +0100195 pub fn new_sig_enc_rsa(aes_key_size: u32) -> TlvGen {
196 let flag = if aes_key_size == 256 {
197 TlvFlags::ENCRYPTED_AES256 as u32
198 } else {
199 TlvFlags::ENCRYPTED_AES128 as u32
200 };
Fabio Utzig754438d2018-12-14 06:39:58 -0200201 TlvGen {
Salome Thirot6fdbf552021-05-14 16:46:14 +0100202 flags: flag,
Fabio Utzig754438d2018-12-14 06:39:58 -0200203 kinds: vec![TlvKinds::SHA256, TlvKinds::RSA2048, TlvKinds::ENCRSA2048],
Fabio Utzig9a2b5de2019-11-22 12:50:02 -0300204 ..Default::default()
Fabio Utzig754438d2018-12-14 06:39:58 -0200205 }
206 }
207
208 #[allow(dead_code)]
Salome Thirot6fdbf552021-05-14 16:46:14 +0100209 pub fn new_enc_kw(aes_key_size: u32) -> TlvGen {
210 let flag = if aes_key_size == 256 {
211 TlvFlags::ENCRYPTED_AES256 as u32
212 } else {
213 TlvFlags::ENCRYPTED_AES128 as u32
214 };
Fabio Utzig1e48b912018-09-18 09:04:18 -0300215 TlvGen {
Salome Thirot6fdbf552021-05-14 16:46:14 +0100216 flags: flag,
Salome Thirot0f641972021-05-14 11:19:55 +0100217 kinds: vec![TlvKinds::SHA256, TlvKinds::ENCKW],
Fabio Utzig9a2b5de2019-11-22 12:50:02 -0300218 ..Default::default()
Fabio Utzig1e48b912018-09-18 09:04:18 -0300219 }
220 }
221
Fabio Utzig251ef1d2018-12-18 17:20:19 -0200222 #[allow(dead_code)]
Salome Thirot6fdbf552021-05-14 16:46:14 +0100223 pub fn new_rsa_kw(aes_key_size: u32) -> TlvGen {
224 let flag = if aes_key_size == 256 {
225 TlvFlags::ENCRYPTED_AES256 as u32
226 } else {
227 TlvFlags::ENCRYPTED_AES128 as u32
228 };
Fabio Utzig251ef1d2018-12-18 17:20:19 -0200229 TlvGen {
Salome Thirot6fdbf552021-05-14 16:46:14 +0100230 flags: flag,
Salome Thirot0f641972021-05-14 11:19:55 +0100231 kinds: vec![TlvKinds::SHA256, TlvKinds::RSA2048, TlvKinds::ENCKW],
Fabio Utzig9a2b5de2019-11-22 12:50:02 -0300232 ..Default::default()
Fabio Utzig251ef1d2018-12-18 17:20:19 -0200233 }
234 }
235
Fabio Utzigb4d20c82018-12-27 16:08:39 -0200236 #[allow(dead_code)]
Salome Thirot6fdbf552021-05-14 16:46:14 +0100237 pub fn new_ecdsa_kw(aes_key_size: u32) -> TlvGen {
238 let flag = if aes_key_size == 256 {
239 TlvFlags::ENCRYPTED_AES256 as u32
240 } else {
241 TlvFlags::ENCRYPTED_AES128 as u32
242 };
Fabio Utzigb4d20c82018-12-27 16:08:39 -0200243 TlvGen {
Salome Thirot6fdbf552021-05-14 16:46:14 +0100244 flags: flag,
Salome Thirot0f641972021-05-14 11:19:55 +0100245 kinds: vec![TlvKinds::SHA256, TlvKinds::ECDSA256, TlvKinds::ENCKW],
Fabio Utzig9a2b5de2019-11-22 12:50:02 -0300246 ..Default::default()
Fabio Utzig90f449e2019-10-24 07:43:53 -0300247 }
248 }
249
250 #[allow(dead_code)]
Salome Thirot6fdbf552021-05-14 16:46:14 +0100251 pub fn new_ecies_p256(aes_key_size: u32) -> TlvGen {
252 let flag = if aes_key_size == 256 {
253 TlvFlags::ENCRYPTED_AES256 as u32
254 } else {
255 TlvFlags::ENCRYPTED_AES128 as u32
256 };
Fabio Utzig66b4caa2020-01-04 20:19:28 -0300257 TlvGen {
Salome Thirot6fdbf552021-05-14 16:46:14 +0100258 flags: flag,
Fabio Utzig66b4caa2020-01-04 20:19:28 -0300259 kinds: vec![TlvKinds::SHA256, TlvKinds::ENCEC256],
Fabio Utzig66b4caa2020-01-04 20:19:28 -0300260 ..Default::default()
261 }
262 }
263
264 #[allow(dead_code)]
Salome Thirot6fdbf552021-05-14 16:46:14 +0100265 pub fn new_ecdsa_ecies_p256(aes_key_size: u32) -> TlvGen {
266 let flag = if aes_key_size == 256 {
267 TlvFlags::ENCRYPTED_AES256 as u32
268 } else {
269 TlvFlags::ENCRYPTED_AES128 as u32
270 };
Fabio Utzig90f449e2019-10-24 07:43:53 -0300271 TlvGen {
Salome Thirot6fdbf552021-05-14 16:46:14 +0100272 flags: flag,
Fabio Utzig90f449e2019-10-24 07:43:53 -0300273 kinds: vec![TlvKinds::SHA256, TlvKinds::ECDSA256, TlvKinds::ENCEC256],
Fabio Utzig9a2b5de2019-11-22 12:50:02 -0300274 ..Default::default()
Fabio Utzigb4d20c82018-12-27 16:08:39 -0200275 }
276 }
Fabio Utzig3fa72ca2020-04-02 11:20:37 -0300277
278 #[allow(dead_code)]
Salome Thirot6fdbf552021-05-14 16:46:14 +0100279 pub fn new_ecies_x25519(aes_key_size: u32) -> TlvGen {
280 let flag = if aes_key_size == 256 {
281 TlvFlags::ENCRYPTED_AES256 as u32
282 } else {
283 TlvFlags::ENCRYPTED_AES128 as u32
284 };
Fabio Utzig3fa72ca2020-04-02 11:20:37 -0300285 TlvGen {
Salome Thirot6fdbf552021-05-14 16:46:14 +0100286 flags: flag,
Fabio Utzig3fa72ca2020-04-02 11:20:37 -0300287 kinds: vec![TlvKinds::SHA256, TlvKinds::ENCX25519],
288 ..Default::default()
289 }
290 }
291
292 #[allow(dead_code)]
Salome Thirot6fdbf552021-05-14 16:46:14 +0100293 pub fn new_ed25519_ecies_x25519(aes_key_size: u32) -> TlvGen {
294 let flag = if aes_key_size == 256 {
295 TlvFlags::ENCRYPTED_AES256 as u32
296 } else {
297 TlvFlags::ENCRYPTED_AES128 as u32
298 };
Fabio Utzig3fa72ca2020-04-02 11:20:37 -0300299 TlvGen {
Salome Thirot6fdbf552021-05-14 16:46:14 +0100300 flags: flag,
Fabio Utzig3fa72ca2020-04-02 11:20:37 -0300301 kinds: vec![TlvKinds::SHA256, TlvKinds::ED25519, TlvKinds::ENCX25519],
302 ..Default::default()
303 }
304 }
David Brown43643dd2019-01-11 15:43:28 -0700305}
306
307impl ManifestGen for TlvGen {
David Brownac46e262019-01-11 15:46:18 -0700308 fn get_magic(&self) -> u32 {
309 0x96f3b83d
310 }
311
David Brown43643dd2019-01-11 15:43:28 -0700312 /// Retrieve the header flags for this configuration. This can be called at any time.
313 fn get_flags(&self) -> u32 {
David Brown8a4e23b2021-06-11 10:29:01 -0600314 // For the RamLoad case, add in the flag for this feature.
315 if Caps::RamLoad.present() {
316 self.flags | (TlvFlags::RAM_LOAD as u32)
317 } else {
318 self.flags
319 }
David Brown43643dd2019-01-11 15:43:28 -0700320 }
David Brown187dd882017-07-11 11:15:23 -0600321
322 /// Add bytes to the covered hash.
David Brown43643dd2019-01-11 15:43:28 -0700323 fn add_bytes(&mut self, bytes: &[u8]) {
David Brown4243ab02017-07-11 12:24:23 -0600324 self.payload.extend_from_slice(bytes);
David Brown187dd882017-07-11 11:15:23 -0600325 }
326
David Brown7a81c4b2019-07-29 15:20:21 -0600327 fn protect_size(&self) -> u16 {
David Brown2b73ed92020-01-08 17:01:22 -0700328 if self.dependencies.is_empty() {
David Brown7a81c4b2019-07-29 15:20:21 -0600329 0
330 } else {
David Brown2b73ed92020-01-08 17:01:22 -0700331 // Include the header and space for each dependency.
332 4 + (self.dependencies.len() as u16) * (4 + 4 + 8)
David Brown7a81c4b2019-07-29 15:20:21 -0600333 }
334 }
335
336 fn add_dependency(&mut self, id: u8, version: &ImageVersion) {
David Brown7a81c4b2019-07-29 15:20:21 -0600337 self.dependencies.push(Dependency {
David Brown4dfb33c2021-03-10 05:15:45 -0700338 id,
David Brown7a81c4b2019-07-29 15:20:21 -0600339 version: version.clone(),
340 });
341 }
342
David Browne90b13f2019-12-06 15:04:00 -0700343 fn corrupt_sig(&mut self) {
344 self.gen_corrupted = true;
345 }
346
David Brownef4f0742021-10-22 17:09:50 -0600347 fn estimate_size(&self) -> usize {
348 // Begin the estimate with the 4 byte header.
349 let mut estimate = 4;
350 // A very poor estimate.
351
352 // Estimate the size of the image hash.
353 if self.kinds.contains(&TlvKinds::SHA256) {
354 estimate += 4 + 32;
355 }
356
357 // Add an estimate in for each of the signature algorithms.
358 if self.kinds.contains(&TlvKinds::RSA2048) {
359 estimate += 4 + 32; // keyhash
360 estimate += 4 + 256; // RSA2048
361 }
362 if self.kinds.contains(&TlvKinds::RSA3072) {
363 estimate += 4 + 32; // keyhash
364 estimate += 4 + 384; // RSA3072
365 }
366 if self.kinds.contains(&TlvKinds::ECDSA256) {
367 estimate += 4 + 32; // keyhash
368
369 // ECDSA signatures are encoded as ASN.1 with the x and y values stored as signed
370 // integers. As such, the size can vary by 2 bytes, if the 256-bit value has the high
371 // bit, it takes an extra 0 byte to avoid it being seen as a negative number.
372 estimate += 4 + 72; // ECDSA256 (varies)
373 }
374 if self.kinds.contains(&TlvKinds::ED25519) {
375 estimate += 4 + 32; // keyhash
376 estimate += 4 + 64; // ED25519 signature.
377 }
Roland Mikhel6205c102023-02-06 13:32:02 +0100378 if self.kinds.contains(&TlvKinds::ECDSASIG) {
379 estimate += 4 + 32; // keyhash
380 estimate += 4 + 72; // ECDSA256 (varies)
381 }
David Brownef4f0742021-10-22 17:09:50 -0600382
383 // Estimate encryption.
384 let flag = TlvFlags::ENCRYPTED_AES256 as u32;
385 let aes256 = (self.get_flags() & flag) == flag;
386
387 if self.kinds.contains(&TlvKinds::ENCRSA2048) {
388 estimate += 4 + 256;
389 }
390 if self.kinds.contains(&TlvKinds::ENCKW) {
391 estimate += 4 + if aes256 { 40 } else { 24 };
392 }
393 if self.kinds.contains(&TlvKinds::ENCEC256) {
394 estimate += 4 + if aes256 { 129 } else { 113 };
395 }
396 if self.kinds.contains(&TlvKinds::ENCX25519) {
397 estimate += 4 + if aes256 { 96 } else { 80 };
398 }
399
400 // Gather the size of the dependency information.
401 if self.protect_size() > 0 {
402 estimate += 4 + (16 * self.dependencies.len());
403 }
404
405 estimate
406 }
407
David Brown187dd882017-07-11 11:15:23 -0600408 /// Compute the TLV given the specified block of data.
David Brown43643dd2019-01-11 15:43:28 -0700409 fn make_tlv(self: Box<Self>) -> Vec<u8> {
David Brownef4f0742021-10-22 17:09:50 -0600410 let size_estimate = self.estimate_size();
411
Fabio Utzigea3d3ab2019-09-11 19:35:33 -0300412 let mut protected_tlv: Vec<u8> = vec![];
David Brown187dd882017-07-11 11:15:23 -0600413
David Brown2b73ed92020-01-08 17:01:22 -0700414 if self.protect_size() > 0 {
Fabio Utzigea3d3ab2019-09-11 19:35:33 -0300415 protected_tlv.push(0x08);
416 protected_tlv.push(0x69);
David Brown2b73ed92020-01-08 17:01:22 -0700417 let size = self.protect_size();
418 protected_tlv.write_u16::<LittleEndian>(size).unwrap();
Fabio Utzigea3d3ab2019-09-11 19:35:33 -0300419 for dep in &self.dependencies {
David Brown69721182019-12-04 14:50:52 -0700420 protected_tlv.write_u16::<LittleEndian>(TlvKinds::DEPENDENCY as u16).unwrap();
David Brown4fae8b82019-12-05 11:26:59 -0700421 protected_tlv.write_u16::<LittleEndian>(12).unwrap();
David Brownf5b33d82017-09-01 10:58:27 -0600422
Fabio Utzigea3d3ab2019-09-11 19:35:33 -0300423 // The dependency.
424 protected_tlv.push(dep.id);
David Brownf66b2052021-03-10 05:26:36 -0700425 protected_tlv.push(0);
426 protected_tlv.write_u16::<LittleEndian>(0).unwrap();
Fabio Utzigea3d3ab2019-09-11 19:35:33 -0300427 protected_tlv.push(dep.version.major);
428 protected_tlv.push(dep.version.minor);
429 protected_tlv.write_u16::<LittleEndian>(dep.version.revision).unwrap();
430 protected_tlv.write_u32::<LittleEndian>(dep.version.build_num).unwrap();
David Brown7a81c4b2019-07-29 15:20:21 -0600431 }
David Brown2b73ed92020-01-08 17:01:22 -0700432
433 assert_eq!(size, protected_tlv.len() as u16, "protected TLV length incorrect");
David Brown7a81c4b2019-07-29 15:20:21 -0600434 }
435
436 // Ring does the signature itself, which means that it must be
437 // given a full, contiguous payload. Although this does help from
438 // a correct usage perspective, it is fairly stupid from an
439 // efficiency view. If this is shown to be a performance issue
440 // with the tests, the protected data could be appended to the
441 // payload, and then removed after the signature is done. For now,
442 // just make a signed payload.
443 let mut sig_payload = self.payload.clone();
Fabio Utzigea3d3ab2019-09-11 19:35:33 -0300444 sig_payload.extend_from_slice(&protected_tlv);
445
446 let mut result: Vec<u8> = vec![];
447
448 // add back signed payload
449 result.extend_from_slice(&protected_tlv);
450
451 // add non-protected payload
David Brown3dc86c92020-01-08 17:22:55 -0700452 let npro_pos = result.len();
Fabio Utzigea3d3ab2019-09-11 19:35:33 -0300453 result.push(0x07);
454 result.push(0x69);
David Brown3dc86c92020-01-08 17:22:55 -0700455 // Placeholder for the size.
456 result.write_u16::<LittleEndian>(0).unwrap();
David Brown7a81c4b2019-07-29 15:20:21 -0600457
David Brown187dd882017-07-11 11:15:23 -0600458 if self.kinds.contains(&TlvKinds::SHA256) {
David Browne90b13f2019-12-06 15:04:00 -0700459 // If a signature is not requested, corrupt the hash we are
460 // generating. But, if there is a signature, output the
461 // correct hash. We want the hash test to pass so that the
462 // signature verification can be validated.
463 let mut corrupt_hash = self.gen_corrupted;
464 for k in &[TlvKinds::RSA2048, TlvKinds::RSA3072,
Roland Mikhel6205c102023-02-06 13:32:02 +0100465 TlvKinds::ECDSA256, TlvKinds::ED25519, TlvKinds::ECDSASIG]
David Browne90b13f2019-12-06 15:04:00 -0700466 {
467 if self.kinds.contains(k) {
468 corrupt_hash = false;
469 break;
470 }
471 }
472
473 if corrupt_hash {
474 sig_payload[0] ^= 1;
475 }
476
David Brown7a81c4b2019-07-29 15:20:21 -0600477 let hash = digest::digest(&digest::SHA256, &sig_payload);
David Brown8054ce22017-07-11 12:12:09 -0600478 let hash = hash.as_ref();
David Brown187dd882017-07-11 11:15:23 -0600479
David Brown8054ce22017-07-11 12:12:09 -0600480 assert!(hash.len() == 32);
David Brown69721182019-12-04 14:50:52 -0700481 result.write_u16::<LittleEndian>(TlvKinds::SHA256 as u16).unwrap();
David Brown4fae8b82019-12-05 11:26:59 -0700482 result.write_u16::<LittleEndian>(32).unwrap();
David Brown8054ce22017-07-11 12:12:09 -0600483 result.extend_from_slice(hash);
David Browne90b13f2019-12-06 15:04:00 -0700484
485 // Undo the corruption.
486 if corrupt_hash {
487 sig_payload[0] ^= 1;
488 }
489
490 }
491
492 if self.gen_corrupted {
493 // Corrupt what is signed by modifying the input to the
494 // signature code.
495 sig_payload[0] ^= 1;
David Brown187dd882017-07-11 11:15:23 -0600496 }
497
Fabio Utzig39297432019-05-08 18:51:10 -0300498 if self.kinds.contains(&TlvKinds::RSA2048) ||
499 self.kinds.contains(&TlvKinds::RSA3072) {
500
501 let is_rsa2048 = self.kinds.contains(&TlvKinds::RSA2048);
502
David Brown43cda332017-09-01 09:53:23 -0600503 // Output the hash of the public key.
Fabio Utzig39297432019-05-08 18:51:10 -0300504 let hash = if is_rsa2048 {
505 digest::digest(&digest::SHA256, RSA_PUB_KEY)
506 } else {
507 digest::digest(&digest::SHA256, RSA3072_PUB_KEY)
508 };
David Brown43cda332017-09-01 09:53:23 -0600509 let hash = hash.as_ref();
510
511 assert!(hash.len() == 32);
David Brown69721182019-12-04 14:50:52 -0700512 result.write_u16::<LittleEndian>(TlvKinds::KEYHASH as u16).unwrap();
David Brown4fae8b82019-12-05 11:26:59 -0700513 result.write_u16::<LittleEndian>(32).unwrap();
David Brown43cda332017-09-01 09:53:23 -0600514 result.extend_from_slice(hash);
515
David Brown7e701d82017-07-11 13:24:25 -0600516 // For now assume PSS.
Fabio Utzig39297432019-05-08 18:51:10 -0300517 let key_bytes = if is_rsa2048 {
518 pem::parse(include_bytes!("../../root-rsa-2048.pem").as_ref()).unwrap()
519 } else {
520 pem::parse(include_bytes!("../../root-rsa-3072.pem").as_ref()).unwrap()
521 };
David Brown7e701d82017-07-11 13:24:25 -0600522 assert_eq!(key_bytes.tag, "RSA PRIVATE KEY");
Fabio Utzig90f449e2019-10-24 07:43:53 -0300523 let key_pair = RsaKeyPair::from_der(&key_bytes.contents).unwrap();
David Brown7e701d82017-07-11 13:24:25 -0600524 let rng = rand::SystemRandom::new();
Fabio Utzig05ab0142018-07-10 09:15:28 -0300525 let mut signature = vec![0; key_pair.public_modulus_len()];
Fabio Utzig39297432019-05-08 18:51:10 -0300526 if is_rsa2048 {
527 assert_eq!(signature.len(), 256);
528 } else {
529 assert_eq!(signature.len(), 384);
530 }
David Brown7a81c4b2019-07-29 15:20:21 -0600531 key_pair.sign(&RSA_PSS_SHA256, &rng, &sig_payload, &mut signature).unwrap();
David Brown7e701d82017-07-11 13:24:25 -0600532
Fabio Utzig39297432019-05-08 18:51:10 -0300533 if is_rsa2048 {
David Brown69721182019-12-04 14:50:52 -0700534 result.write_u16::<LittleEndian>(TlvKinds::RSA2048 as u16).unwrap();
Fabio Utzig39297432019-05-08 18:51:10 -0300535 } else {
David Brown69721182019-12-04 14:50:52 -0700536 result.write_u16::<LittleEndian>(TlvKinds::RSA3072 as u16).unwrap();
Fabio Utzig39297432019-05-08 18:51:10 -0300537 }
David Brown91d68632019-07-29 14:32:13 -0600538 result.write_u16::<LittleEndian>(signature.len() as u16).unwrap();
David Brown7e701d82017-07-11 13:24:25 -0600539 result.extend_from_slice(&signature);
540 }
541
Roland Mikhel6205c102023-02-06 13:32:02 +0100542 if self.kinds.contains(&TlvKinds::ECDSASIG) {
543 let rng = rand::SystemRandom::new();
544 let keyhash = digest::digest(&digest::SHA256, ECDSA256_PUB_KEY);
545 let key_bytes = pem::parse(include_bytes!("../../root-ec-p256-pkcs8.pem").as_ref()).unwrap();
546 let sign_algo = &ECDSA_P256_SHA256_ASN1_SIGNING;
547 let key_pair = EcdsaKeyPair::from_pkcs8(sign_algo, &key_bytes.contents).unwrap();
548 let signature = key_pair.sign(&rng,&sig_payload).unwrap();
549
550 // Write public key
551 let keyhash_slice = keyhash.as_ref();
552 assert!(keyhash_slice.len() == 32);
553 result.write_u16::<LittleEndian>(TlvKinds::KEYHASH as u16).unwrap();
554 result.write_u16::<LittleEndian>(32).unwrap();
555 result.extend_from_slice(keyhash_slice);
556
557 // Write signature
558 result.write_u16::<LittleEndian>(TlvKinds::ECDSASIG as u16).unwrap();
559 let signature = signature.as_ref().to_vec();
560 result.write_u16::<LittleEndian>(signature.len() as u16).unwrap();
561 result.extend_from_slice(&signature);
562 }
563
Fabio Utzig80fde2f2017-12-05 09:25:31 -0200564 if self.kinds.contains(&TlvKinds::ECDSA256) {
565 let keyhash = digest::digest(&digest::SHA256, ECDSA256_PUB_KEY);
566 let keyhash = keyhash.as_ref();
567
568 assert!(keyhash.len() == 32);
David Brown69721182019-12-04 14:50:52 -0700569 result.write_u16::<LittleEndian>(TlvKinds::KEYHASH as u16).unwrap();
David Brown4fae8b82019-12-05 11:26:59 -0700570 result.write_u16::<LittleEndian>(32).unwrap();
Fabio Utzig80fde2f2017-12-05 09:25:31 -0200571 result.extend_from_slice(keyhash);
572
Fabio Utzig05ab0142018-07-10 09:15:28 -0300573 let key_bytes = pem::parse(include_bytes!("../../root-ec-p256-pkcs8.pem").as_ref()).unwrap();
574 assert_eq!(key_bytes.tag, "PRIVATE KEY");
Fabio Utzig80fde2f2017-12-05 09:25:31 -0200575
Fabio Utzig05ab0142018-07-10 09:15:28 -0300576 let key_pair = EcdsaKeyPair::from_pkcs8(&ECDSA_P256_SHA256_ASN1_SIGNING,
Fabio Utzig90f449e2019-10-24 07:43:53 -0300577 &key_bytes.contents).unwrap();
Fabio Utzig05ab0142018-07-10 09:15:28 -0300578 let rng = rand::SystemRandom::new();
Fabio Utzig90f449e2019-10-24 07:43:53 -0300579 let signature = key_pair.sign(&rng, &sig_payload).unwrap();
Fabio Utzig80fde2f2017-12-05 09:25:31 -0200580
David Brown69721182019-12-04 14:50:52 -0700581 result.write_u16::<LittleEndian>(TlvKinds::ECDSA256 as u16).unwrap();
Fabio Utzig05ab0142018-07-10 09:15:28 -0300582
David Browna4c58642019-12-12 17:28:33 -0700583 let signature = signature.as_ref().to_vec();
Fabio Utzig05ab0142018-07-10 09:15:28 -0300584
David Brown91d68632019-07-29 14:32:13 -0600585 result.write_u16::<LittleEndian>(signature.len() as u16).unwrap();
Fabio Utzig05ab0142018-07-10 09:15:28 -0300586 result.extend_from_slice(signature.as_ref());
Fabio Utzig80fde2f2017-12-05 09:25:31 -0200587 }
588
Fabio Utzig97710282019-05-24 17:44:49 -0300589 if self.kinds.contains(&TlvKinds::ED25519) {
590 let keyhash = digest::digest(&digest::SHA256, ED25519_PUB_KEY);
591 let keyhash = keyhash.as_ref();
592
593 assert!(keyhash.len() == 32);
David Brown69721182019-12-04 14:50:52 -0700594 result.write_u16::<LittleEndian>(TlvKinds::KEYHASH as u16).unwrap();
David Brown4fae8b82019-12-05 11:26:59 -0700595 result.write_u16::<LittleEndian>(32).unwrap();
Fabio Utzig97710282019-05-24 17:44:49 -0300596 result.extend_from_slice(keyhash);
597
David Brown7a81c4b2019-07-29 15:20:21 -0600598 let hash = digest::digest(&digest::SHA256, &sig_payload);
Fabio Utzig97710282019-05-24 17:44:49 -0300599 let hash = hash.as_ref();
600 assert!(hash.len() == 32);
601
602 let key_bytes = pem::parse(include_bytes!("../../root-ed25519.pem").as_ref()).unwrap();
603 assert_eq!(key_bytes.tag, "PRIVATE KEY");
604
Fabio Utzig90f449e2019-10-24 07:43:53 -0300605 let key_pair = Ed25519KeyPair::from_seed_and_public_key(
606 &key_bytes.contents[16..48], &ED25519_PUB_KEY[12..44]).unwrap();
Fabio Utzig97710282019-05-24 17:44:49 -0300607 let signature = key_pair.sign(&hash);
608
David Brown69721182019-12-04 14:50:52 -0700609 result.write_u16::<LittleEndian>(TlvKinds::ED25519 as u16).unwrap();
Fabio Utzig97710282019-05-24 17:44:49 -0300610
611 let signature = signature.as_ref().to_vec();
David Brown91d68632019-07-29 14:32:13 -0600612 result.write_u16::<LittleEndian>(signature.len() as u16).unwrap();
Fabio Utzig97710282019-05-24 17:44:49 -0300613 result.extend_from_slice(signature.as_ref());
614 }
615
Fabio Utzig1e48b912018-09-18 09:04:18 -0300616 if self.kinds.contains(&TlvKinds::ENCRSA2048) {
617 let key_bytes = pem::parse(include_bytes!("../../enc-rsa2048-pub.pem")
618 .as_ref()).unwrap();
619 assert_eq!(key_bytes.tag, "PUBLIC KEY");
620
Fabio Utzige84f0ef2019-11-22 12:29:32 -0300621 let cipherkey = self.get_enc_key();
622 let cipherkey = cipherkey.as_slice();
623 let encbuf = match c::rsa_oaep_encrypt(&key_bytes.contents, cipherkey) {
Fabio Utzig1e48b912018-09-18 09:04:18 -0300624 Ok(v) => v,
625 Err(_) => panic!("Failed to encrypt secret key"),
626 };
627
628 assert!(encbuf.len() == 256);
David Brown69721182019-12-04 14:50:52 -0700629 result.write_u16::<LittleEndian>(TlvKinds::ENCRSA2048 as u16).unwrap();
David Brown4fae8b82019-12-05 11:26:59 -0700630 result.write_u16::<LittleEndian>(256).unwrap();
Fabio Utzig1e48b912018-09-18 09:04:18 -0300631 result.extend_from_slice(&encbuf);
632 }
633
Salome Thirot0f641972021-05-14 11:19:55 +0100634 if self.kinds.contains(&TlvKinds::ENCKW) {
Salome Thirot6fdbf552021-05-14 16:46:14 +0100635 let flag = TlvFlags::ENCRYPTED_AES256 as u32;
636 let aes256 = (self.get_flags() & flag) == flag;
637 let key_bytes = if aes256 {
638 base64::decode(
639 include_str!("../../enc-aes256kw.b64").trim()).unwrap()
640 } else {
641 base64::decode(
642 include_str!("../../enc-aes128kw.b64").trim()).unwrap()
643 };
Fabio Utzige84f0ef2019-11-22 12:29:32 -0300644 let cipherkey = self.get_enc_key();
645 let cipherkey = cipherkey.as_slice();
Salome Thirot6fdbf552021-05-14 16:46:14 +0100646 let keylen = if aes256 { 32 } else { 16 };
647 let encbuf = match c::kw_encrypt(&key_bytes, cipherkey, keylen) {
Fabio Utzig1e48b912018-09-18 09:04:18 -0300648 Ok(v) => v,
649 Err(_) => panic!("Failed to encrypt secret key"),
650 };
651
Salome Thirot6fdbf552021-05-14 16:46:14 +0100652 let size = if aes256 { 40 } else { 24 };
653 assert!(encbuf.len() == size);
Salome Thirot0f641972021-05-14 11:19:55 +0100654 result.write_u16::<LittleEndian>(TlvKinds::ENCKW as u16).unwrap();
Salome Thirot6fdbf552021-05-14 16:46:14 +0100655 result.write_u16::<LittleEndian>(size as u16).unwrap();
Fabio Utzig1e48b912018-09-18 09:04:18 -0300656 result.extend_from_slice(&encbuf);
657 }
658
Fabio Utzig3fa72ca2020-04-02 11:20:37 -0300659 if self.kinds.contains(&TlvKinds::ENCEC256) || self.kinds.contains(&TlvKinds::ENCX25519) {
660 let key_bytes = if self.kinds.contains(&TlvKinds::ENCEC256) {
661 pem::parse(include_bytes!("../../enc-ec256-pub.pem").as_ref()).unwrap()
662 } else {
663 pem::parse(include_bytes!("../../enc-x25519-pub.pem").as_ref()).unwrap()
664 };
Fabio Utzig90f449e2019-10-24 07:43:53 -0300665 assert_eq!(key_bytes.tag, "PUBLIC KEY");
Fabio Utzig90f449e2019-10-24 07:43:53 -0300666 let rng = rand::SystemRandom::new();
Fabio Utzig3fa72ca2020-04-02 11:20:37 -0300667 let alg = if self.kinds.contains(&TlvKinds::ENCEC256) {
668 &agreement::ECDH_P256
669 } else {
670 &agreement::X25519
671 };
672 let pk = match agreement::EphemeralPrivateKey::generate(alg, &rng) {
Fabio Utzig90f449e2019-10-24 07:43:53 -0300673 Ok(v) => v,
674 Err(_) => panic!("Failed to generate ephemeral keypair"),
675 };
676
677 let pubk = match pk.compute_public_key() {
678 Ok(pubk) => pubk,
679 Err(_) => panic!("Failed computing ephemeral public key"),
680 };
681
Fabio Utzig3fa72ca2020-04-02 11:20:37 -0300682 let peer_pubk = if self.kinds.contains(&TlvKinds::ENCEC256) {
683 agreement::UnparsedPublicKey::new(&agreement::ECDH_P256, &key_bytes.contents[26..])
684 } else {
685 agreement::UnparsedPublicKey::new(&agreement::X25519, &key_bytes.contents[12..])
686 };
Fabio Utzig90f449e2019-10-24 07:43:53 -0300687
688 #[derive(Debug, PartialEq)]
689 struct OkmLen<T: core::fmt::Debug + PartialEq>(T);
690
691 impl hkdf::KeyType for OkmLen<usize> {
692 fn len(&self) -> usize {
693 self.0
694 }
695 }
696
Salome Thirot6fdbf552021-05-14 16:46:14 +0100697 let flag = TlvFlags::ENCRYPTED_AES256 as u32;
698 let aes256 = (self.get_flags() & flag) == flag;
699
Fabio Utzig90f449e2019-10-24 07:43:53 -0300700 let derived_key = match agreement::agree_ephemeral(
701 pk, &peer_pubk, ring::error::Unspecified, |shared| {
702 let salt = hkdf::Salt::new(hkdf::HKDF_SHA256, &[]);
703 let prk = salt.extract(&shared);
Salome Thirot6fdbf552021-05-14 16:46:14 +0100704 let okm_len = if aes256 { 64 } else { 48 };
705 let okm = match prk.expand(&[b"MCUBoot_ECIES_v1"], OkmLen(okm_len)) {
Fabio Utzig90f449e2019-10-24 07:43:53 -0300706 Ok(okm) => okm,
707 Err(_) => panic!("Failed building HKDF OKM"),
708 };
Salome Thirot6fdbf552021-05-14 16:46:14 +0100709 let mut buf = if aes256 { vec![0u8; 64] } else { vec![0u8; 48] };
Fabio Utzig90f449e2019-10-24 07:43:53 -0300710 match okm.fill(&mut buf) {
711 Ok(_) => Ok(buf),
712 Err(_) => panic!("Failed generating HKDF output"),
713 }
714 },
715 ) {
716 Ok(v) => v,
717 Err(_) => panic!("Failed building HKDF"),
718 };
719
Fabio Utzig90f449e2019-10-24 07:43:53 -0300720 let nonce = GenericArray::from_slice(&[0; 16]);
Fabio Utzig90f449e2019-10-24 07:43:53 -0300721 let mut cipherkey = self.get_enc_key();
Salome Thirot6fdbf552021-05-14 16:46:14 +0100722 if aes256 {
723 let key: &GenericArray<u8, U32> = GenericArray::from_slice(&derived_key[..32]);
David Brown9c6322f2021-08-19 13:03:39 -0600724 let block = Aes256::new(&key);
725 let mut cipher = Aes256Ctr::from_block_cipher(block, &nonce);
Salome Thirot6fdbf552021-05-14 16:46:14 +0100726 cipher.apply_keystream(&mut cipherkey);
727 } else {
728 let key: &GenericArray<u8, U16> = GenericArray::from_slice(&derived_key[..16]);
David Brown9c6322f2021-08-19 13:03:39 -0600729 let block = Aes128::new(&key);
730 let mut cipher = Aes128Ctr::from_block_cipher(block, &nonce);
Salome Thirot6fdbf552021-05-14 16:46:14 +0100731 cipher.apply_keystream(&mut cipherkey);
732 }
Fabio Utzig90f449e2019-10-24 07:43:53 -0300733
Salome Thirot6fdbf552021-05-14 16:46:14 +0100734 let size = if aes256 { 32 } else { 16 };
735 let key = hmac::Key::new(hmac::HMAC_SHA256, &derived_key[size..]);
Fabio Utzig90f449e2019-10-24 07:43:53 -0300736 let tag = hmac::sign(&key, &cipherkey);
737
738 let mut buf = vec![];
739 buf.append(&mut pubk.as_ref().to_vec());
740 buf.append(&mut tag.as_ref().to_vec());
741 buf.append(&mut cipherkey);
742
Fabio Utzig3fa72ca2020-04-02 11:20:37 -0300743 if self.kinds.contains(&TlvKinds::ENCEC256) {
Salome Thirot6fdbf552021-05-14 16:46:14 +0100744 let size = if aes256 { 129 } else { 113 };
745 assert!(buf.len() == size);
Fabio Utzig3fa72ca2020-04-02 11:20:37 -0300746 result.write_u16::<LittleEndian>(TlvKinds::ENCEC256 as u16).unwrap();
Salome Thirot6fdbf552021-05-14 16:46:14 +0100747 result.write_u16::<LittleEndian>(size as u16).unwrap();
Fabio Utzig3fa72ca2020-04-02 11:20:37 -0300748 } else {
Salome Thirot6fdbf552021-05-14 16:46:14 +0100749 let size = if aes256 { 96 } else { 80 };
750 assert!(buf.len() == size);
Fabio Utzig3fa72ca2020-04-02 11:20:37 -0300751 result.write_u16::<LittleEndian>(TlvKinds::ENCX25519 as u16).unwrap();
Salome Thirot6fdbf552021-05-14 16:46:14 +0100752 result.write_u16::<LittleEndian>(size as u16).unwrap();
Fabio Utzig3fa72ca2020-04-02 11:20:37 -0300753 }
Fabio Utzig90f449e2019-10-24 07:43:53 -0300754 result.extend_from_slice(&buf);
755 }
756
David Brown3dc86c92020-01-08 17:22:55 -0700757 // Patch the size back into the TLV header.
758 let size = (result.len() - npro_pos) as u16;
759 let mut size_buf = &mut result[npro_pos + 2 .. npro_pos + 4];
760 size_buf.write_u16::<LittleEndian>(size).unwrap();
761
David Brownb408b432021-10-27 15:55:39 -0600762 // ECDSA is stored as an ASN.1 integer. For a 128-bit value, this maximally results in 33
763 // bytes of storage for each of the two values. If the high bit is zero, it will take 32
764 // bytes, if the top 8 bits are zero, it will take 31 bits, and so on. The smaller size
765 // will occur with decreasing likelihood. We'll allow this to get a bit smaller, hopefully
766 // allowing the tests to pass with false failures rare. For this case, we'll handle up to
767 // the top 16 bits of both numbers being all zeros (1 in 2^32).
768 if !Caps::has_ecdsa() {
769 if size_estimate != result.len() {
770 panic!("Incorrect size estimate: {} (actual {})", size_estimate, result.len());
771 }
772 } else {
773 if size_estimate < result.len() || size_estimate > result.len() + 6 {
774 panic!("Incorrect size estimate: {} (actual {})", size_estimate, result.len());
775 }
David Brownef4f0742021-10-22 17:09:50 -0600776 }
777 if size_estimate != result.len() {
778 log::warn!("Size off: {} actual {}", size_estimate, result.len());
779 }
780
David Brown187dd882017-07-11 11:15:23 -0600781 result
782 }
Fabio Utzig90f449e2019-10-24 07:43:53 -0300783
Fabio Utzige84f0ef2019-11-22 12:29:32 -0300784 fn generate_enc_key(&mut self) {
785 let rng = rand::SystemRandom::new();
Salome Thirot6fdbf552021-05-14 16:46:14 +0100786 let flag = TlvFlags::ENCRYPTED_AES256 as u32;
787 let aes256 = (self.get_flags() & flag) == flag;
788 let mut buf = if aes256 {
789 vec![0u8; 32]
790 } else {
791 vec![0u8; 16]
792 };
David Brown26edaf32021-03-10 05:27:38 -0700793 if rng.fill(&mut buf).is_err() {
794 panic!("Error generating encrypted key");
Fabio Utzige84f0ef2019-11-22 12:29:32 -0300795 }
796 info!("New encryption key: {:02x?}", buf);
797 self.enc_key = buf;
Fabio Utzig90f449e2019-10-24 07:43:53 -0300798 }
799
800 fn get_enc_key(&self) -> Vec<u8> {
Salome Thirot6fdbf552021-05-14 16:46:14 +0100801 if self.enc_key.len() != 32 && self.enc_key.len() != 16 {
Fabio Utzige84f0ef2019-11-22 12:29:32 -0300802 panic!("No random key was generated");
803 }
804 self.enc_key.clone()
Fabio Utzig90f449e2019-10-24 07:43:53 -0300805 }
David Brown187dd882017-07-11 11:15:23 -0600806}
David Brown43cda332017-09-01 09:53:23 -0600807
808include!("rsa_pub_key-rs.txt");
Fabio Utzig39297432019-05-08 18:51:10 -0300809include!("rsa3072_pub_key-rs.txt");
Fabio Utzig80fde2f2017-12-05 09:25:31 -0200810include!("ecdsa_pub_key-rs.txt");
Fabio Utzig97710282019-05-24 17:44:49 -0300811include!("ed25519_pub_key-rs.txt");