blob: 99c02d96afb918ed97b64f6aee3b923cd2c04e6c [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 Vincze4395b802023-04-27 16:11:49 +020054 ECDSASIG = 0x22,
Fabio Utzig39297432019-05-08 18:51:10 -030055 RSA3072 = 0x23,
Fabio Utzig97710282019-05-24 17:44:49 -030056 ED25519 = 0x24,
Fabio Utzig1e48b912018-09-18 09:04:18 -030057 ENCRSA2048 = 0x30,
Salome Thirot0f641972021-05-14 11:19:55 +010058 ENCKW = 0x31,
Fabio Utzig90f449e2019-10-24 07:43:53 -030059 ENCEC256 = 0x32,
Fabio Utzig3fa72ca2020-04-02 11:20:37 -030060 ENCX25519 = 0x33,
David Brown7a81c4b2019-07-29 15:20:21 -060061 DEPENDENCY = 0x40,
Roland Mikheld6703522023-04-27 14:24:30 +020062 SECCNT = 0x50,
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>;
Roland Mikheld6703522023-04-27 14:24:30 +0200112
113 /// Set the security counter to the specified value.
114 fn set_security_counter(&mut self, security_cnt: Option<u32>);
David Brown43643dd2019-01-11 15:43:28 -0700115}
116
Fabio Utzig9a2b5de2019-11-22 12:50:02 -0300117#[derive(Debug, Default)]
David Brown187dd882017-07-11 11:15:23 -0600118pub struct TlvGen {
David Brown43cda332017-09-01 09:53:23 -0600119 flags: u32,
David Brown187dd882017-07-11 11:15:23 -0600120 kinds: Vec<TlvKinds>,
David Brown4243ab02017-07-11 12:24:23 -0600121 payload: Vec<u8>,
David Brown7a81c4b2019-07-29 15:20:21 -0600122 dependencies: Vec<Dependency>,
Fabio Utzig90f449e2019-10-24 07:43:53 -0300123 enc_key: Vec<u8>,
David Browne90b13f2019-12-06 15:04:00 -0700124 /// Should this signature be corrupted.
125 gen_corrupted: bool,
Roland Mikheld6703522023-04-27 14:24:30 +0200126 security_cnt: Option<u32>,
David Brown7a81c4b2019-07-29 15:20:21 -0600127}
128
David Brownc3898d62019-08-05 14:20:02 -0600129#[derive(Debug)]
David Brown7a81c4b2019-07-29 15:20:21 -0600130struct Dependency {
131 id: u8,
132 version: ImageVersion,
David Brown187dd882017-07-11 11:15:23 -0600133}
134
135impl TlvGen {
136 /// Construct a new tlv generator that will only contain a hash of the data.
David Brown7e701d82017-07-11 13:24:25 -0600137 #[allow(dead_code)]
David Brown187dd882017-07-11 11:15:23 -0600138 pub fn new_hash_only() -> TlvGen {
139 TlvGen {
David Brown187dd882017-07-11 11:15:23 -0600140 kinds: vec![TlvKinds::SHA256],
Fabio Utzig9a2b5de2019-11-22 12:50:02 -0300141 ..Default::default()
David Brown187dd882017-07-11 11:15:23 -0600142 }
143 }
144
David Brown7e701d82017-07-11 13:24:25 -0600145 #[allow(dead_code)]
146 pub fn new_rsa_pss() -> TlvGen {
147 TlvGen {
Fabio Utzig754438d2018-12-14 06:39:58 -0200148 kinds: vec![TlvKinds::SHA256, TlvKinds::RSA2048],
Fabio Utzig9a2b5de2019-11-22 12:50:02 -0300149 ..Default::default()
David Brown7e701d82017-07-11 13:24:25 -0600150 }
151 }
152
Fabio Utzig80fde2f2017-12-05 09:25:31 -0200153 #[allow(dead_code)]
Fabio Utzig39297432019-05-08 18:51:10 -0300154 pub fn new_rsa3072_pss() -> TlvGen {
155 TlvGen {
Fabio Utzig39297432019-05-08 18:51:10 -0300156 kinds: vec![TlvKinds::SHA256, TlvKinds::RSA3072],
Fabio Utzig9a2b5de2019-11-22 12:50:02 -0300157 ..Default::default()
Fabio Utzig39297432019-05-08 18:51:10 -0300158 }
159 }
160
161 #[allow(dead_code)]
Fabio Utzig80fde2f2017-12-05 09:25:31 -0200162 pub fn new_ecdsa() -> TlvGen {
163 TlvGen {
Roland Mikhel30978512023-02-08 14:06:58 +0100164 kinds: vec![TlvKinds::SHA256, TlvKinds::ECDSASIG],
Fabio Utzig9a2b5de2019-11-22 12:50:02 -0300165 ..Default::default()
Fabio Utzig80fde2f2017-12-05 09:25:31 -0200166 }
167 }
168
Fabio Utzig1e48b912018-09-18 09:04:18 -0300169 #[allow(dead_code)]
Fabio Utzig97710282019-05-24 17:44:49 -0300170 pub fn new_ed25519() -> TlvGen {
171 TlvGen {
Fabio Utzig97710282019-05-24 17:44:49 -0300172 kinds: vec![TlvKinds::SHA256, TlvKinds::ED25519],
Fabio Utzig9a2b5de2019-11-22 12:50:02 -0300173 ..Default::default()
Fabio Utzig97710282019-05-24 17:44:49 -0300174 }
175 }
176
177 #[allow(dead_code)]
Salome Thirot6fdbf552021-05-14 16:46:14 +0100178 pub fn new_enc_rsa(aes_key_size: u32) -> TlvGen {
179 let flag = if aes_key_size == 256 {
180 TlvFlags::ENCRYPTED_AES256 as u32
181 } else {
182 TlvFlags::ENCRYPTED_AES128 as u32
183 };
Fabio Utzig1e48b912018-09-18 09:04:18 -0300184 TlvGen {
Salome Thirot6fdbf552021-05-14 16:46:14 +0100185 flags: flag,
Fabio Utzig1e48b912018-09-18 09:04:18 -0300186 kinds: vec![TlvKinds::SHA256, TlvKinds::ENCRSA2048],
Fabio Utzig9a2b5de2019-11-22 12:50:02 -0300187 ..Default::default()
Fabio Utzig1e48b912018-09-18 09:04:18 -0300188 }
189 }
190
191 #[allow(dead_code)]
Salome Thirot6fdbf552021-05-14 16:46:14 +0100192 pub fn new_sig_enc_rsa(aes_key_size: u32) -> TlvGen {
193 let flag = if aes_key_size == 256 {
194 TlvFlags::ENCRYPTED_AES256 as u32
195 } else {
196 TlvFlags::ENCRYPTED_AES128 as u32
197 };
Fabio Utzig754438d2018-12-14 06:39:58 -0200198 TlvGen {
Salome Thirot6fdbf552021-05-14 16:46:14 +0100199 flags: flag,
Fabio Utzig754438d2018-12-14 06:39:58 -0200200 kinds: vec![TlvKinds::SHA256, TlvKinds::RSA2048, TlvKinds::ENCRSA2048],
Fabio Utzig9a2b5de2019-11-22 12:50:02 -0300201 ..Default::default()
Fabio Utzig754438d2018-12-14 06:39:58 -0200202 }
203 }
204
205 #[allow(dead_code)]
Salome Thirot6fdbf552021-05-14 16:46:14 +0100206 pub fn new_enc_kw(aes_key_size: u32) -> TlvGen {
207 let flag = if aes_key_size == 256 {
208 TlvFlags::ENCRYPTED_AES256 as u32
209 } else {
210 TlvFlags::ENCRYPTED_AES128 as u32
211 };
Fabio Utzig1e48b912018-09-18 09:04:18 -0300212 TlvGen {
Salome Thirot6fdbf552021-05-14 16:46:14 +0100213 flags: flag,
Salome Thirot0f641972021-05-14 11:19:55 +0100214 kinds: vec![TlvKinds::SHA256, TlvKinds::ENCKW],
Fabio Utzig9a2b5de2019-11-22 12:50:02 -0300215 ..Default::default()
Fabio Utzig1e48b912018-09-18 09:04:18 -0300216 }
217 }
218
Fabio Utzig251ef1d2018-12-18 17:20:19 -0200219 #[allow(dead_code)]
Salome Thirot6fdbf552021-05-14 16:46:14 +0100220 pub fn new_rsa_kw(aes_key_size: u32) -> TlvGen {
221 let flag = if aes_key_size == 256 {
222 TlvFlags::ENCRYPTED_AES256 as u32
223 } else {
224 TlvFlags::ENCRYPTED_AES128 as u32
225 };
Fabio Utzig251ef1d2018-12-18 17:20:19 -0200226 TlvGen {
Salome Thirot6fdbf552021-05-14 16:46:14 +0100227 flags: flag,
Salome Thirot0f641972021-05-14 11:19:55 +0100228 kinds: vec![TlvKinds::SHA256, TlvKinds::RSA2048, TlvKinds::ENCKW],
Fabio Utzig9a2b5de2019-11-22 12:50:02 -0300229 ..Default::default()
Fabio Utzig251ef1d2018-12-18 17:20:19 -0200230 }
231 }
232
Fabio Utzigb4d20c82018-12-27 16:08:39 -0200233 #[allow(dead_code)]
Salome Thirot6fdbf552021-05-14 16:46:14 +0100234 pub fn new_ecdsa_kw(aes_key_size: u32) -> TlvGen {
235 let flag = if aes_key_size == 256 {
236 TlvFlags::ENCRYPTED_AES256 as u32
237 } else {
238 TlvFlags::ENCRYPTED_AES128 as u32
239 };
Fabio Utzigb4d20c82018-12-27 16:08:39 -0200240 TlvGen {
Salome Thirot6fdbf552021-05-14 16:46:14 +0100241 flags: flag,
Roland Mikhel30978512023-02-08 14:06:58 +0100242 kinds: vec![TlvKinds::SHA256, TlvKinds::ECDSASIG, TlvKinds::ENCKW],
Fabio Utzig9a2b5de2019-11-22 12:50:02 -0300243 ..Default::default()
Fabio Utzig90f449e2019-10-24 07:43:53 -0300244 }
245 }
246
247 #[allow(dead_code)]
Salome Thirot6fdbf552021-05-14 16:46:14 +0100248 pub fn new_ecies_p256(aes_key_size: u32) -> TlvGen {
249 let flag = if aes_key_size == 256 {
250 TlvFlags::ENCRYPTED_AES256 as u32
251 } else {
252 TlvFlags::ENCRYPTED_AES128 as u32
253 };
Fabio Utzig66b4caa2020-01-04 20:19:28 -0300254 TlvGen {
Salome Thirot6fdbf552021-05-14 16:46:14 +0100255 flags: flag,
Fabio Utzig66b4caa2020-01-04 20:19:28 -0300256 kinds: vec![TlvKinds::SHA256, TlvKinds::ENCEC256],
Fabio Utzig66b4caa2020-01-04 20:19:28 -0300257 ..Default::default()
258 }
259 }
260
261 #[allow(dead_code)]
Salome Thirot6fdbf552021-05-14 16:46:14 +0100262 pub fn new_ecdsa_ecies_p256(aes_key_size: u32) -> TlvGen {
263 let flag = if aes_key_size == 256 {
264 TlvFlags::ENCRYPTED_AES256 as u32
265 } else {
266 TlvFlags::ENCRYPTED_AES128 as u32
267 };
Fabio Utzig90f449e2019-10-24 07:43:53 -0300268 TlvGen {
Salome Thirot6fdbf552021-05-14 16:46:14 +0100269 flags: flag,
Roland Mikhel30978512023-02-08 14:06:58 +0100270 kinds: vec![TlvKinds::SHA256, TlvKinds::ECDSASIG, TlvKinds::ENCEC256],
Fabio Utzig9a2b5de2019-11-22 12:50:02 -0300271 ..Default::default()
Fabio Utzigb4d20c82018-12-27 16:08:39 -0200272 }
273 }
Fabio Utzig3fa72ca2020-04-02 11:20:37 -0300274
275 #[allow(dead_code)]
Salome Thirot6fdbf552021-05-14 16:46:14 +0100276 pub fn new_ecies_x25519(aes_key_size: u32) -> TlvGen {
277 let flag = if aes_key_size == 256 {
278 TlvFlags::ENCRYPTED_AES256 as u32
279 } else {
280 TlvFlags::ENCRYPTED_AES128 as u32
281 };
Fabio Utzig3fa72ca2020-04-02 11:20:37 -0300282 TlvGen {
Salome Thirot6fdbf552021-05-14 16:46:14 +0100283 flags: flag,
Fabio Utzig3fa72ca2020-04-02 11:20:37 -0300284 kinds: vec![TlvKinds::SHA256, TlvKinds::ENCX25519],
285 ..Default::default()
286 }
287 }
288
289 #[allow(dead_code)]
Salome Thirot6fdbf552021-05-14 16:46:14 +0100290 pub fn new_ed25519_ecies_x25519(aes_key_size: u32) -> TlvGen {
291 let flag = if aes_key_size == 256 {
292 TlvFlags::ENCRYPTED_AES256 as u32
293 } else {
294 TlvFlags::ENCRYPTED_AES128 as u32
295 };
Fabio Utzig3fa72ca2020-04-02 11:20:37 -0300296 TlvGen {
Salome Thirot6fdbf552021-05-14 16:46:14 +0100297 flags: flag,
Fabio Utzig3fa72ca2020-04-02 11:20:37 -0300298 kinds: vec![TlvKinds::SHA256, TlvKinds::ED25519, TlvKinds::ENCX25519],
299 ..Default::default()
300 }
301 }
Roland Mikheld6703522023-04-27 14:24:30 +0200302
303 #[allow(dead_code)]
304 pub fn new_sec_cnt() -> TlvGen {
305 TlvGen {
306 kinds: vec![TlvKinds::SHA256, TlvKinds::SECCNT],
307 ..Default::default()
308 }
309 }
310
David Brown43643dd2019-01-11 15:43:28 -0700311}
312
313impl ManifestGen for TlvGen {
David Brownac46e262019-01-11 15:46:18 -0700314 fn get_magic(&self) -> u32 {
315 0x96f3b83d
316 }
317
David Brown43643dd2019-01-11 15:43:28 -0700318 /// Retrieve the header flags for this configuration. This can be called at any time.
319 fn get_flags(&self) -> u32 {
David Brown8a4e23b2021-06-11 10:29:01 -0600320 // For the RamLoad case, add in the flag for this feature.
321 if Caps::RamLoad.present() {
322 self.flags | (TlvFlags::RAM_LOAD as u32)
323 } else {
324 self.flags
325 }
David Brown43643dd2019-01-11 15:43:28 -0700326 }
David Brown187dd882017-07-11 11:15:23 -0600327
328 /// Add bytes to the covered hash.
David Brown43643dd2019-01-11 15:43:28 -0700329 fn add_bytes(&mut self, bytes: &[u8]) {
David Brown4243ab02017-07-11 12:24:23 -0600330 self.payload.extend_from_slice(bytes);
David Brown187dd882017-07-11 11:15:23 -0600331 }
332
David Brown7a81c4b2019-07-29 15:20:21 -0600333 fn protect_size(&self) -> u16 {
Roland Mikheld6703522023-04-27 14:24:30 +0200334 let mut size = 0;
335 if !self.dependencies.is_empty() || (Caps::HwRollbackProtection.present() && self.security_cnt.is_some()) {
336 // include the TLV area header.
337 size += 4;
338 // add space for each dependency.
339 size += (self.dependencies.len() as u16) * (4 + std::mem::size_of::<Dependency>() as u16);
340 if Caps::HwRollbackProtection.present() && self.security_cnt.is_some() {
341 size += 4 + 4;
342 }
David Brown7a81c4b2019-07-29 15:20:21 -0600343 }
Roland Mikheld6703522023-04-27 14:24:30 +0200344 size
David Brown7a81c4b2019-07-29 15:20:21 -0600345 }
346
347 fn add_dependency(&mut self, id: u8, version: &ImageVersion) {
David Brown7a81c4b2019-07-29 15:20:21 -0600348 self.dependencies.push(Dependency {
David Brown4dfb33c2021-03-10 05:15:45 -0700349 id,
David Brown7a81c4b2019-07-29 15:20:21 -0600350 version: version.clone(),
351 });
352 }
353
David Browne90b13f2019-12-06 15:04:00 -0700354 fn corrupt_sig(&mut self) {
355 self.gen_corrupted = true;
356 }
357
David Brownef4f0742021-10-22 17:09:50 -0600358 fn estimate_size(&self) -> usize {
359 // Begin the estimate with the 4 byte header.
360 let mut estimate = 4;
361 // A very poor estimate.
362
363 // Estimate the size of the image hash.
364 if self.kinds.contains(&TlvKinds::SHA256) {
365 estimate += 4 + 32;
366 }
367
368 // Add an estimate in for each of the signature algorithms.
369 if self.kinds.contains(&TlvKinds::RSA2048) {
370 estimate += 4 + 32; // keyhash
371 estimate += 4 + 256; // RSA2048
372 }
373 if self.kinds.contains(&TlvKinds::RSA3072) {
374 estimate += 4 + 32; // keyhash
375 estimate += 4 + 384; // RSA3072
376 }
David Brownef4f0742021-10-22 17:09:50 -0600377 if self.kinds.contains(&TlvKinds::ED25519) {
378 estimate += 4 + 32; // keyhash
379 estimate += 4 + 64; // ED25519 signature.
380 }
Roland Mikhel6205c102023-02-06 13:32:02 +0100381 if self.kinds.contains(&TlvKinds::ECDSASIG) {
382 estimate += 4 + 32; // keyhash
Roland Mikhel30978512023-02-08 14:06:58 +0100383
384 // ECDSA signatures are encoded as ASN.1 with the x and y values stored as signed
385 // integers. As such, the size can vary by 2 bytes, if the 256-bit value has the high
386 // bit, it takes an extra 0 byte to avoid it being seen as a negative number.
Roland Mikhel6205c102023-02-06 13:32:02 +0100387 estimate += 4 + 72; // ECDSA256 (varies)
388 }
David Brownef4f0742021-10-22 17:09:50 -0600389
390 // Estimate encryption.
391 let flag = TlvFlags::ENCRYPTED_AES256 as u32;
392 let aes256 = (self.get_flags() & flag) == flag;
393
394 if self.kinds.contains(&TlvKinds::ENCRSA2048) {
395 estimate += 4 + 256;
396 }
397 if self.kinds.contains(&TlvKinds::ENCKW) {
398 estimate += 4 + if aes256 { 40 } else { 24 };
399 }
400 if self.kinds.contains(&TlvKinds::ENCEC256) {
401 estimate += 4 + if aes256 { 129 } else { 113 };
402 }
403 if self.kinds.contains(&TlvKinds::ENCX25519) {
404 estimate += 4 + if aes256 { 96 } else { 80 };
405 }
406
Roland Mikheld6703522023-04-27 14:24:30 +0200407 // Gather the size of the protected TLV area.
408 estimate += self.protect_size() as usize;
David Brownef4f0742021-10-22 17:09:50 -0600409
410 estimate
411 }
412
David Brown187dd882017-07-11 11:15:23 -0600413 /// Compute the TLV given the specified block of data.
David Brown43643dd2019-01-11 15:43:28 -0700414 fn make_tlv(self: Box<Self>) -> Vec<u8> {
David Brownef4f0742021-10-22 17:09:50 -0600415 let size_estimate = self.estimate_size();
416
Fabio Utzigea3d3ab2019-09-11 19:35:33 -0300417 let mut protected_tlv: Vec<u8> = vec![];
David Brown187dd882017-07-11 11:15:23 -0600418
David Brown2b73ed92020-01-08 17:01:22 -0700419 if self.protect_size() > 0 {
Fabio Utzigea3d3ab2019-09-11 19:35:33 -0300420 protected_tlv.push(0x08);
421 protected_tlv.push(0x69);
David Brown2b73ed92020-01-08 17:01:22 -0700422 let size = self.protect_size();
423 protected_tlv.write_u16::<LittleEndian>(size).unwrap();
Fabio Utzigea3d3ab2019-09-11 19:35:33 -0300424 for dep in &self.dependencies {
David Brown69721182019-12-04 14:50:52 -0700425 protected_tlv.write_u16::<LittleEndian>(TlvKinds::DEPENDENCY as u16).unwrap();
David Brown4fae8b82019-12-05 11:26:59 -0700426 protected_tlv.write_u16::<LittleEndian>(12).unwrap();
David Brownf5b33d82017-09-01 10:58:27 -0600427
Fabio Utzigea3d3ab2019-09-11 19:35:33 -0300428 // The dependency.
429 protected_tlv.push(dep.id);
David Brownf66b2052021-03-10 05:26:36 -0700430 protected_tlv.push(0);
431 protected_tlv.write_u16::<LittleEndian>(0).unwrap();
Fabio Utzigea3d3ab2019-09-11 19:35:33 -0300432 protected_tlv.push(dep.version.major);
433 protected_tlv.push(dep.version.minor);
434 protected_tlv.write_u16::<LittleEndian>(dep.version.revision).unwrap();
435 protected_tlv.write_u32::<LittleEndian>(dep.version.build_num).unwrap();
David Brown7a81c4b2019-07-29 15:20:21 -0600436 }
David Brown2b73ed92020-01-08 17:01:22 -0700437
Roland Mikheld6703522023-04-27 14:24:30 +0200438 // Security counter has to be at the protected TLV area also
439 if Caps::HwRollbackProtection.present() && self.security_cnt.is_some() {
440 protected_tlv.write_u16::<LittleEndian>(TlvKinds::SECCNT as u16).unwrap();
441 protected_tlv.write_u16::<LittleEndian>(std::mem::size_of::<u32>() as u16).unwrap();
442 protected_tlv.write_u32::<LittleEndian>(self.security_cnt.unwrap() as u32).unwrap();
443 }
444
David Brown2b73ed92020-01-08 17:01:22 -0700445 assert_eq!(size, protected_tlv.len() as u16, "protected TLV length incorrect");
David Brown7a81c4b2019-07-29 15:20:21 -0600446 }
447
448 // Ring does the signature itself, which means that it must be
449 // given a full, contiguous payload. Although this does help from
450 // a correct usage perspective, it is fairly stupid from an
451 // efficiency view. If this is shown to be a performance issue
452 // with the tests, the protected data could be appended to the
453 // payload, and then removed after the signature is done. For now,
454 // just make a signed payload.
455 let mut sig_payload = self.payload.clone();
Fabio Utzigea3d3ab2019-09-11 19:35:33 -0300456 sig_payload.extend_from_slice(&protected_tlv);
457
458 let mut result: Vec<u8> = vec![];
459
460 // add back signed payload
461 result.extend_from_slice(&protected_tlv);
462
463 // add non-protected payload
David Brown3dc86c92020-01-08 17:22:55 -0700464 let npro_pos = result.len();
Fabio Utzigea3d3ab2019-09-11 19:35:33 -0300465 result.push(0x07);
466 result.push(0x69);
David Brown3dc86c92020-01-08 17:22:55 -0700467 // Placeholder for the size.
468 result.write_u16::<LittleEndian>(0).unwrap();
David Brown7a81c4b2019-07-29 15:20:21 -0600469
David Brown187dd882017-07-11 11:15:23 -0600470 if self.kinds.contains(&TlvKinds::SHA256) {
David Browne90b13f2019-12-06 15:04:00 -0700471 // If a signature is not requested, corrupt the hash we are
472 // generating. But, if there is a signature, output the
473 // correct hash. We want the hash test to pass so that the
474 // signature verification can be validated.
475 let mut corrupt_hash = self.gen_corrupted;
476 for k in &[TlvKinds::RSA2048, TlvKinds::RSA3072,
Roland Mikhel30978512023-02-08 14:06:58 +0100477 TlvKinds::ED25519, TlvKinds::ECDSASIG]
David Browne90b13f2019-12-06 15:04:00 -0700478 {
479 if self.kinds.contains(k) {
480 corrupt_hash = false;
481 break;
482 }
483 }
484
485 if corrupt_hash {
486 sig_payload[0] ^= 1;
487 }
488
David Brown7a81c4b2019-07-29 15:20:21 -0600489 let hash = digest::digest(&digest::SHA256, &sig_payload);
David Brown8054ce22017-07-11 12:12:09 -0600490 let hash = hash.as_ref();
David Brown187dd882017-07-11 11:15:23 -0600491
David Brown8054ce22017-07-11 12:12:09 -0600492 assert!(hash.len() == 32);
David Brown69721182019-12-04 14:50:52 -0700493 result.write_u16::<LittleEndian>(TlvKinds::SHA256 as u16).unwrap();
David Brown4fae8b82019-12-05 11:26:59 -0700494 result.write_u16::<LittleEndian>(32).unwrap();
David Brown8054ce22017-07-11 12:12:09 -0600495 result.extend_from_slice(hash);
David Browne90b13f2019-12-06 15:04:00 -0700496
497 // Undo the corruption.
498 if corrupt_hash {
499 sig_payload[0] ^= 1;
500 }
501
502 }
503
504 if self.gen_corrupted {
505 // Corrupt what is signed by modifying the input to the
506 // signature code.
507 sig_payload[0] ^= 1;
David Brown187dd882017-07-11 11:15:23 -0600508 }
509
Fabio Utzig39297432019-05-08 18:51:10 -0300510 if self.kinds.contains(&TlvKinds::RSA2048) ||
511 self.kinds.contains(&TlvKinds::RSA3072) {
512
513 let is_rsa2048 = self.kinds.contains(&TlvKinds::RSA2048);
514
David Brown43cda332017-09-01 09:53:23 -0600515 // Output the hash of the public key.
Fabio Utzig39297432019-05-08 18:51:10 -0300516 let hash = if is_rsa2048 {
517 digest::digest(&digest::SHA256, RSA_PUB_KEY)
518 } else {
519 digest::digest(&digest::SHA256, RSA3072_PUB_KEY)
520 };
David Brown43cda332017-09-01 09:53:23 -0600521 let hash = hash.as_ref();
522
523 assert!(hash.len() == 32);
David Brown69721182019-12-04 14:50:52 -0700524 result.write_u16::<LittleEndian>(TlvKinds::KEYHASH as u16).unwrap();
David Brown4fae8b82019-12-05 11:26:59 -0700525 result.write_u16::<LittleEndian>(32).unwrap();
David Brown43cda332017-09-01 09:53:23 -0600526 result.extend_from_slice(hash);
527
David Brown7e701d82017-07-11 13:24:25 -0600528 // For now assume PSS.
Fabio Utzig39297432019-05-08 18:51:10 -0300529 let key_bytes = if is_rsa2048 {
530 pem::parse(include_bytes!("../../root-rsa-2048.pem").as_ref()).unwrap()
531 } else {
532 pem::parse(include_bytes!("../../root-rsa-3072.pem").as_ref()).unwrap()
533 };
David Brown7e701d82017-07-11 13:24:25 -0600534 assert_eq!(key_bytes.tag, "RSA PRIVATE KEY");
Fabio Utzig90f449e2019-10-24 07:43:53 -0300535 let key_pair = RsaKeyPair::from_der(&key_bytes.contents).unwrap();
David Brown7e701d82017-07-11 13:24:25 -0600536 let rng = rand::SystemRandom::new();
Fabio Utzig05ab0142018-07-10 09:15:28 -0300537 let mut signature = vec![0; key_pair.public_modulus_len()];
Fabio Utzig39297432019-05-08 18:51:10 -0300538 if is_rsa2048 {
539 assert_eq!(signature.len(), 256);
540 } else {
541 assert_eq!(signature.len(), 384);
542 }
David Brown7a81c4b2019-07-29 15:20:21 -0600543 key_pair.sign(&RSA_PSS_SHA256, &rng, &sig_payload, &mut signature).unwrap();
David Brown7e701d82017-07-11 13:24:25 -0600544
Fabio Utzig39297432019-05-08 18:51:10 -0300545 if is_rsa2048 {
David Brown69721182019-12-04 14:50:52 -0700546 result.write_u16::<LittleEndian>(TlvKinds::RSA2048 as u16).unwrap();
Fabio Utzig39297432019-05-08 18:51:10 -0300547 } else {
David Brown69721182019-12-04 14:50:52 -0700548 result.write_u16::<LittleEndian>(TlvKinds::RSA3072 as u16).unwrap();
Fabio Utzig39297432019-05-08 18:51:10 -0300549 }
David Brown91d68632019-07-29 14:32:13 -0600550 result.write_u16::<LittleEndian>(signature.len() as u16).unwrap();
David Brown7e701d82017-07-11 13:24:25 -0600551 result.extend_from_slice(&signature);
552 }
553
Roland Mikhel6205c102023-02-06 13:32:02 +0100554 if self.kinds.contains(&TlvKinds::ECDSASIG) {
555 let rng = rand::SystemRandom::new();
556 let keyhash = digest::digest(&digest::SHA256, ECDSA256_PUB_KEY);
557 let key_bytes = pem::parse(include_bytes!("../../root-ec-p256-pkcs8.pem").as_ref()).unwrap();
558 let sign_algo = &ECDSA_P256_SHA256_ASN1_SIGNING;
559 let key_pair = EcdsaKeyPair::from_pkcs8(sign_algo, &key_bytes.contents).unwrap();
560 let signature = key_pair.sign(&rng,&sig_payload).unwrap();
561
562 // Write public key
563 let keyhash_slice = keyhash.as_ref();
564 assert!(keyhash_slice.len() == 32);
565 result.write_u16::<LittleEndian>(TlvKinds::KEYHASH as u16).unwrap();
566 result.write_u16::<LittleEndian>(32).unwrap();
567 result.extend_from_slice(keyhash_slice);
568
569 // Write signature
570 result.write_u16::<LittleEndian>(TlvKinds::ECDSASIG as u16).unwrap();
571 let signature = signature.as_ref().to_vec();
572 result.write_u16::<LittleEndian>(signature.len() as u16).unwrap();
573 result.extend_from_slice(&signature);
574 }
Fabio Utzig97710282019-05-24 17:44:49 -0300575 if self.kinds.contains(&TlvKinds::ED25519) {
576 let keyhash = digest::digest(&digest::SHA256, ED25519_PUB_KEY);
577 let keyhash = keyhash.as_ref();
578
579 assert!(keyhash.len() == 32);
David Brown69721182019-12-04 14:50:52 -0700580 result.write_u16::<LittleEndian>(TlvKinds::KEYHASH as u16).unwrap();
David Brown4fae8b82019-12-05 11:26:59 -0700581 result.write_u16::<LittleEndian>(32).unwrap();
Fabio Utzig97710282019-05-24 17:44:49 -0300582 result.extend_from_slice(keyhash);
583
David Brown7a81c4b2019-07-29 15:20:21 -0600584 let hash = digest::digest(&digest::SHA256, &sig_payload);
Fabio Utzig97710282019-05-24 17:44:49 -0300585 let hash = hash.as_ref();
586 assert!(hash.len() == 32);
587
588 let key_bytes = pem::parse(include_bytes!("../../root-ed25519.pem").as_ref()).unwrap();
589 assert_eq!(key_bytes.tag, "PRIVATE KEY");
590
Fabio Utzig90f449e2019-10-24 07:43:53 -0300591 let key_pair = Ed25519KeyPair::from_seed_and_public_key(
592 &key_bytes.contents[16..48], &ED25519_PUB_KEY[12..44]).unwrap();
Fabio Utzig97710282019-05-24 17:44:49 -0300593 let signature = key_pair.sign(&hash);
594
David Brown69721182019-12-04 14:50:52 -0700595 result.write_u16::<LittleEndian>(TlvKinds::ED25519 as u16).unwrap();
Fabio Utzig97710282019-05-24 17:44:49 -0300596
597 let signature = signature.as_ref().to_vec();
David Brown91d68632019-07-29 14:32:13 -0600598 result.write_u16::<LittleEndian>(signature.len() as u16).unwrap();
Fabio Utzig97710282019-05-24 17:44:49 -0300599 result.extend_from_slice(signature.as_ref());
600 }
601
Fabio Utzig1e48b912018-09-18 09:04:18 -0300602 if self.kinds.contains(&TlvKinds::ENCRSA2048) {
603 let key_bytes = pem::parse(include_bytes!("../../enc-rsa2048-pub.pem")
604 .as_ref()).unwrap();
605 assert_eq!(key_bytes.tag, "PUBLIC KEY");
606
Fabio Utzige84f0ef2019-11-22 12:29:32 -0300607 let cipherkey = self.get_enc_key();
608 let cipherkey = cipherkey.as_slice();
609 let encbuf = match c::rsa_oaep_encrypt(&key_bytes.contents, cipherkey) {
Fabio Utzig1e48b912018-09-18 09:04:18 -0300610 Ok(v) => v,
611 Err(_) => panic!("Failed to encrypt secret key"),
612 };
613
614 assert!(encbuf.len() == 256);
David Brown69721182019-12-04 14:50:52 -0700615 result.write_u16::<LittleEndian>(TlvKinds::ENCRSA2048 as u16).unwrap();
David Brown4fae8b82019-12-05 11:26:59 -0700616 result.write_u16::<LittleEndian>(256).unwrap();
Fabio Utzig1e48b912018-09-18 09:04:18 -0300617 result.extend_from_slice(&encbuf);
618 }
619
Salome Thirot0f641972021-05-14 11:19:55 +0100620 if self.kinds.contains(&TlvKinds::ENCKW) {
Salome Thirot6fdbf552021-05-14 16:46:14 +0100621 let flag = TlvFlags::ENCRYPTED_AES256 as u32;
622 let aes256 = (self.get_flags() & flag) == flag;
623 let key_bytes = if aes256 {
624 base64::decode(
625 include_str!("../../enc-aes256kw.b64").trim()).unwrap()
626 } else {
627 base64::decode(
628 include_str!("../../enc-aes128kw.b64").trim()).unwrap()
629 };
Fabio Utzige84f0ef2019-11-22 12:29:32 -0300630 let cipherkey = self.get_enc_key();
631 let cipherkey = cipherkey.as_slice();
Salome Thirot6fdbf552021-05-14 16:46:14 +0100632 let keylen = if aes256 { 32 } else { 16 };
633 let encbuf = match c::kw_encrypt(&key_bytes, cipherkey, keylen) {
Fabio Utzig1e48b912018-09-18 09:04:18 -0300634 Ok(v) => v,
635 Err(_) => panic!("Failed to encrypt secret key"),
636 };
637
Salome Thirot6fdbf552021-05-14 16:46:14 +0100638 let size = if aes256 { 40 } else { 24 };
639 assert!(encbuf.len() == size);
Salome Thirot0f641972021-05-14 11:19:55 +0100640 result.write_u16::<LittleEndian>(TlvKinds::ENCKW as u16).unwrap();
Salome Thirot6fdbf552021-05-14 16:46:14 +0100641 result.write_u16::<LittleEndian>(size as u16).unwrap();
Fabio Utzig1e48b912018-09-18 09:04:18 -0300642 result.extend_from_slice(&encbuf);
643 }
644
Fabio Utzig3fa72ca2020-04-02 11:20:37 -0300645 if self.kinds.contains(&TlvKinds::ENCEC256) || self.kinds.contains(&TlvKinds::ENCX25519) {
646 let key_bytes = if self.kinds.contains(&TlvKinds::ENCEC256) {
647 pem::parse(include_bytes!("../../enc-ec256-pub.pem").as_ref()).unwrap()
648 } else {
649 pem::parse(include_bytes!("../../enc-x25519-pub.pem").as_ref()).unwrap()
650 };
Fabio Utzig90f449e2019-10-24 07:43:53 -0300651 assert_eq!(key_bytes.tag, "PUBLIC KEY");
Fabio Utzig90f449e2019-10-24 07:43:53 -0300652 let rng = rand::SystemRandom::new();
Fabio Utzig3fa72ca2020-04-02 11:20:37 -0300653 let alg = if self.kinds.contains(&TlvKinds::ENCEC256) {
654 &agreement::ECDH_P256
655 } else {
656 &agreement::X25519
657 };
658 let pk = match agreement::EphemeralPrivateKey::generate(alg, &rng) {
Fabio Utzig90f449e2019-10-24 07:43:53 -0300659 Ok(v) => v,
660 Err(_) => panic!("Failed to generate ephemeral keypair"),
661 };
662
663 let pubk = match pk.compute_public_key() {
664 Ok(pubk) => pubk,
665 Err(_) => panic!("Failed computing ephemeral public key"),
666 };
667
Fabio Utzig3fa72ca2020-04-02 11:20:37 -0300668 let peer_pubk = if self.kinds.contains(&TlvKinds::ENCEC256) {
669 agreement::UnparsedPublicKey::new(&agreement::ECDH_P256, &key_bytes.contents[26..])
670 } else {
671 agreement::UnparsedPublicKey::new(&agreement::X25519, &key_bytes.contents[12..])
672 };
Fabio Utzig90f449e2019-10-24 07:43:53 -0300673
674 #[derive(Debug, PartialEq)]
675 struct OkmLen<T: core::fmt::Debug + PartialEq>(T);
676
677 impl hkdf::KeyType for OkmLen<usize> {
678 fn len(&self) -> usize {
679 self.0
680 }
681 }
682
Salome Thirot6fdbf552021-05-14 16:46:14 +0100683 let flag = TlvFlags::ENCRYPTED_AES256 as u32;
684 let aes256 = (self.get_flags() & flag) == flag;
685
Fabio Utzig90f449e2019-10-24 07:43:53 -0300686 let derived_key = match agreement::agree_ephemeral(
687 pk, &peer_pubk, ring::error::Unspecified, |shared| {
688 let salt = hkdf::Salt::new(hkdf::HKDF_SHA256, &[]);
689 let prk = salt.extract(&shared);
Salome Thirot6fdbf552021-05-14 16:46:14 +0100690 let okm_len = if aes256 { 64 } else { 48 };
691 let okm = match prk.expand(&[b"MCUBoot_ECIES_v1"], OkmLen(okm_len)) {
Fabio Utzig90f449e2019-10-24 07:43:53 -0300692 Ok(okm) => okm,
693 Err(_) => panic!("Failed building HKDF OKM"),
694 };
Salome Thirot6fdbf552021-05-14 16:46:14 +0100695 let mut buf = if aes256 { vec![0u8; 64] } else { vec![0u8; 48] };
Fabio Utzig90f449e2019-10-24 07:43:53 -0300696 match okm.fill(&mut buf) {
697 Ok(_) => Ok(buf),
698 Err(_) => panic!("Failed generating HKDF output"),
699 }
700 },
701 ) {
702 Ok(v) => v,
703 Err(_) => panic!("Failed building HKDF"),
704 };
705
Fabio Utzig90f449e2019-10-24 07:43:53 -0300706 let nonce = GenericArray::from_slice(&[0; 16]);
Fabio Utzig90f449e2019-10-24 07:43:53 -0300707 let mut cipherkey = self.get_enc_key();
Salome Thirot6fdbf552021-05-14 16:46:14 +0100708 if aes256 {
709 let key: &GenericArray<u8, U32> = GenericArray::from_slice(&derived_key[..32]);
David Brown9c6322f2021-08-19 13:03:39 -0600710 let block = Aes256::new(&key);
711 let mut cipher = Aes256Ctr::from_block_cipher(block, &nonce);
Salome Thirot6fdbf552021-05-14 16:46:14 +0100712 cipher.apply_keystream(&mut cipherkey);
713 } else {
714 let key: &GenericArray<u8, U16> = GenericArray::from_slice(&derived_key[..16]);
David Brown9c6322f2021-08-19 13:03:39 -0600715 let block = Aes128::new(&key);
716 let mut cipher = Aes128Ctr::from_block_cipher(block, &nonce);
Salome Thirot6fdbf552021-05-14 16:46:14 +0100717 cipher.apply_keystream(&mut cipherkey);
718 }
Fabio Utzig90f449e2019-10-24 07:43:53 -0300719
Salome Thirot6fdbf552021-05-14 16:46:14 +0100720 let size = if aes256 { 32 } else { 16 };
721 let key = hmac::Key::new(hmac::HMAC_SHA256, &derived_key[size..]);
Fabio Utzig90f449e2019-10-24 07:43:53 -0300722 let tag = hmac::sign(&key, &cipherkey);
723
724 let mut buf = vec![];
725 buf.append(&mut pubk.as_ref().to_vec());
726 buf.append(&mut tag.as_ref().to_vec());
727 buf.append(&mut cipherkey);
728
Fabio Utzig3fa72ca2020-04-02 11:20:37 -0300729 if self.kinds.contains(&TlvKinds::ENCEC256) {
Salome Thirot6fdbf552021-05-14 16:46:14 +0100730 let size = if aes256 { 129 } else { 113 };
731 assert!(buf.len() == size);
Fabio Utzig3fa72ca2020-04-02 11:20:37 -0300732 result.write_u16::<LittleEndian>(TlvKinds::ENCEC256 as u16).unwrap();
Salome Thirot6fdbf552021-05-14 16:46:14 +0100733 result.write_u16::<LittleEndian>(size as u16).unwrap();
Fabio Utzig3fa72ca2020-04-02 11:20:37 -0300734 } else {
Salome Thirot6fdbf552021-05-14 16:46:14 +0100735 let size = if aes256 { 96 } else { 80 };
736 assert!(buf.len() == size);
Fabio Utzig3fa72ca2020-04-02 11:20:37 -0300737 result.write_u16::<LittleEndian>(TlvKinds::ENCX25519 as u16).unwrap();
Salome Thirot6fdbf552021-05-14 16:46:14 +0100738 result.write_u16::<LittleEndian>(size as u16).unwrap();
Fabio Utzig3fa72ca2020-04-02 11:20:37 -0300739 }
Fabio Utzig90f449e2019-10-24 07:43:53 -0300740 result.extend_from_slice(&buf);
741 }
742
David Brown3dc86c92020-01-08 17:22:55 -0700743 // Patch the size back into the TLV header.
744 let size = (result.len() - npro_pos) as u16;
745 let mut size_buf = &mut result[npro_pos + 2 .. npro_pos + 4];
746 size_buf.write_u16::<LittleEndian>(size).unwrap();
747
David Brownb408b432021-10-27 15:55:39 -0600748 // ECDSA is stored as an ASN.1 integer. For a 128-bit value, this maximally results in 33
749 // bytes of storage for each of the two values. If the high bit is zero, it will take 32
750 // bytes, if the top 8 bits are zero, it will take 31 bits, and so on. The smaller size
751 // will occur with decreasing likelihood. We'll allow this to get a bit smaller, hopefully
752 // allowing the tests to pass with false failures rare. For this case, we'll handle up to
753 // the top 16 bits of both numbers being all zeros (1 in 2^32).
754 if !Caps::has_ecdsa() {
755 if size_estimate != result.len() {
756 panic!("Incorrect size estimate: {} (actual {})", size_estimate, result.len());
757 }
758 } else {
759 if size_estimate < result.len() || size_estimate > result.len() + 6 {
760 panic!("Incorrect size estimate: {} (actual {})", size_estimate, result.len());
761 }
David Brownef4f0742021-10-22 17:09:50 -0600762 }
763 if size_estimate != result.len() {
764 log::warn!("Size off: {} actual {}", size_estimate, result.len());
765 }
766
David Brown187dd882017-07-11 11:15:23 -0600767 result
768 }
Fabio Utzig90f449e2019-10-24 07:43:53 -0300769
Fabio Utzige84f0ef2019-11-22 12:29:32 -0300770 fn generate_enc_key(&mut self) {
771 let rng = rand::SystemRandom::new();
Salome Thirot6fdbf552021-05-14 16:46:14 +0100772 let flag = TlvFlags::ENCRYPTED_AES256 as u32;
773 let aes256 = (self.get_flags() & flag) == flag;
774 let mut buf = if aes256 {
775 vec![0u8; 32]
776 } else {
777 vec![0u8; 16]
778 };
David Brown26edaf32021-03-10 05:27:38 -0700779 if rng.fill(&mut buf).is_err() {
780 panic!("Error generating encrypted key");
Fabio Utzige84f0ef2019-11-22 12:29:32 -0300781 }
782 info!("New encryption key: {:02x?}", buf);
783 self.enc_key = buf;
Fabio Utzig90f449e2019-10-24 07:43:53 -0300784 }
785
786 fn get_enc_key(&self) -> Vec<u8> {
Salome Thirot6fdbf552021-05-14 16:46:14 +0100787 if self.enc_key.len() != 32 && self.enc_key.len() != 16 {
Fabio Utzige84f0ef2019-11-22 12:29:32 -0300788 panic!("No random key was generated");
789 }
790 self.enc_key.clone()
Fabio Utzig90f449e2019-10-24 07:43:53 -0300791 }
Roland Mikheld6703522023-04-27 14:24:30 +0200792
793 fn set_security_counter(&mut self, security_cnt: Option<u32>) {
794 self.security_cnt = security_cnt;
795 }
David Brown187dd882017-07-11 11:15:23 -0600796}
David Brown43cda332017-09-01 09:53:23 -0600797
798include!("rsa_pub_key-rs.txt");
Fabio Utzig39297432019-05-08 18:51:10 -0300799include!("rsa3072_pub_key-rs.txt");
Fabio Utzig80fde2f2017-12-05 09:25:31 -0200800include!("ecdsa_pub_key-rs.txt");
Fabio Utzig97710282019-05-24 17:44:49 -0300801include!("ed25519_pub_key-rs.txt");