1 // Copyright (c) 2017-2021 Linaro LTD
2 // Copyright (c) 2017-2020 JUUL Labs
3 // Copyright (c) 2021-2023 Arm Limited
4 //
5 // SPDX-License-Identifier: Apache-2.0
6 
7 //! 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 
17 use byteorder::{
18     LittleEndian, WriteBytesExt,
19 };
20 use cipher::FromBlockCipher;
21 use crate::caps::Caps;
22 use crate::image::ImageVersion;
23 use log::info;
24 use ring::{digest, rand, agreement, hkdf, hmac};
25 use ring::rand::SecureRandom;
26 use ring::signature::{
27     RsaKeyPair,
28     RSA_PSS_SHA256,
29     EcdsaKeyPair,
30     ECDSA_P256_SHA256_ASN1_SIGNING,
31     Ed25519KeyPair,
32 };
33 use aes::{
34     Aes128,
35     Aes128Ctr,
36     Aes256,
37     Aes256Ctr,
38     NewBlockCipher
39 };
40 use cipher::{
41     generic_array::GenericArray,
42     StreamCipher,
43 };
44 use mcuboot_sys::c;
45 use typenum::{U16, U32};
46 
47 #[repr(u16)]
48 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
49 #[allow(dead_code)] // TODO: For now
50 pub enum TlvKinds {
51     KEYHASH = 0x01,
52     SHA256 = 0x10,
53     RSA2048 = 0x20,
54     ECDSASIG = 0x22,
55     RSA3072 = 0x23,
56     ED25519 = 0x24,
57     ENCRSA2048 = 0x30,
58     ENCKW = 0x31,
59     ENCEC256 = 0x32,
60     ENCX25519 = 0x33,
61     DEPENDENCY = 0x40,
62 }
63 
64 #[allow(dead_code, non_camel_case_types)]
65 pub enum TlvFlags {
66     PIC = 0x01,
67     NON_BOOTABLE = 0x02,
68     ENCRYPTED_AES128 = 0x04,
69     ENCRYPTED_AES256 = 0x08,
70     RAM_LOAD = 0x20,
71 }
72 
73 /// A generator for manifests.  The format of the manifest can be either a
74 /// traditional "TLV" or a SUIT-style manifest.
75 pub trait ManifestGen {
76     /// Retrieve the header magic value for this manifest type.
get_magic(&self) -> u3277     fn get_magic(&self) -> u32;
78 
79     /// Retrieve the flags value for this particular manifest type.
get_flags(&self) -> u3280     fn get_flags(&self) -> u32;
81 
82     /// Retrieve the number of bytes of this manifest that is "protected".
83     /// This field is stored in the outside image header instead of the
84     /// manifest header.
protect_size(&self) -> u1685     fn protect_size(&self) -> u16;
86 
87     /// Add a dependency on another image.
add_dependency(&mut self, id: u8, version: &ImageVersion)88     fn add_dependency(&mut self, id: u8, version: &ImageVersion);
89 
90     /// Add a sequence of bytes to the payload that the manifest is
91     /// protecting.
add_bytes(&mut self, bytes: &[u8])92     fn add_bytes(&mut self, bytes: &[u8]);
93 
94     /// Set an internal flag indicating that the next `make_tlv` should
95     /// corrupt the signature.
corrupt_sig(&mut self)96     fn corrupt_sig(&mut self);
97 
98     /// Estimate the size of the TLV.  This can be called before the payload is added (but after
99     /// other information is added).  Some of the signature algorithms can generate variable sized
100     /// data, and therefore, this can slightly overestimate the size.
estimate_size(&self) -> usize101     fn estimate_size(&self) -> usize;
102 
103     /// Construct the manifest for this payload.
make_tlv(self: Box<Self>) -> Vec<u8>104     fn make_tlv(self: Box<Self>) -> Vec<u8>;
105 
106     /// Generate a new encryption random key
generate_enc_key(&mut self)107     fn generate_enc_key(&mut self);
108 
109     /// Return the current encryption key
get_enc_key(&self) -> Vec<u8>110     fn get_enc_key(&self) -> Vec<u8>;
111 }
112 
113 #[derive(Debug, Default)]
114 pub struct TlvGen {
115     flags: u32,
116     kinds: Vec<TlvKinds>,
117     payload: Vec<u8>,
118     dependencies: Vec<Dependency>,
119     enc_key: Vec<u8>,
120     /// Should this signature be corrupted.
121     gen_corrupted: bool,
122 }
123 
124 #[derive(Debug)]
125 struct Dependency {
126     id: u8,
127     version: ImageVersion,
128 }
129 
130 impl TlvGen {
131     /// Construct a new tlv generator that will only contain a hash of the data.
132     #[allow(dead_code)]
new_hash_only() -> TlvGen133     pub fn new_hash_only() -> TlvGen {
134         TlvGen {
135             kinds: vec![TlvKinds::SHA256],
136             ..Default::default()
137         }
138     }
139 
140     #[allow(dead_code)]
new_rsa_pss() -> TlvGen141     pub fn new_rsa_pss() -> TlvGen {
142         TlvGen {
143             kinds: vec![TlvKinds::SHA256, TlvKinds::RSA2048],
144             ..Default::default()
145         }
146     }
147 
148     #[allow(dead_code)]
new_rsa3072_pss() -> TlvGen149     pub fn new_rsa3072_pss() -> TlvGen {
150         TlvGen {
151             kinds: vec![TlvKinds::SHA256, TlvKinds::RSA3072],
152             ..Default::default()
153         }
154     }
155 
156     #[allow(dead_code)]
new_ecdsa() -> TlvGen157     pub fn new_ecdsa() -> TlvGen {
158         TlvGen {
159             kinds: vec![TlvKinds::SHA256, TlvKinds::ECDSASIG],
160             ..Default::default()
161         }
162     }
163 
164     #[allow(dead_code)]
new_ed25519() -> TlvGen165     pub fn new_ed25519() -> TlvGen {
166         TlvGen {
167             kinds: vec![TlvKinds::SHA256, TlvKinds::ED25519],
168             ..Default::default()
169         }
170     }
171 
172     #[allow(dead_code)]
new_enc_rsa(aes_key_size: u32) -> TlvGen173     pub fn new_enc_rsa(aes_key_size: u32) -> TlvGen {
174         let flag = if aes_key_size == 256 {
175             TlvFlags::ENCRYPTED_AES256 as u32
176         } else {
177             TlvFlags::ENCRYPTED_AES128 as u32
178         };
179         TlvGen {
180             flags: flag,
181             kinds: vec![TlvKinds::SHA256, TlvKinds::ENCRSA2048],
182             ..Default::default()
183         }
184     }
185 
186     #[allow(dead_code)]
new_sig_enc_rsa(aes_key_size: u32) -> TlvGen187     pub fn new_sig_enc_rsa(aes_key_size: u32) -> TlvGen {
188         let flag = if aes_key_size == 256 {
189             TlvFlags::ENCRYPTED_AES256 as u32
190         } else {
191             TlvFlags::ENCRYPTED_AES128 as u32
192         };
193         TlvGen {
194             flags: flag,
195             kinds: vec![TlvKinds::SHA256, TlvKinds::RSA2048, TlvKinds::ENCRSA2048],
196             ..Default::default()
197         }
198     }
199 
200     #[allow(dead_code)]
new_enc_kw(aes_key_size: u32) -> TlvGen201     pub fn new_enc_kw(aes_key_size: u32) -> TlvGen {
202         let flag = if aes_key_size == 256 {
203             TlvFlags::ENCRYPTED_AES256 as u32
204         } else {
205             TlvFlags::ENCRYPTED_AES128 as u32
206         };
207         TlvGen {
208             flags: flag,
209             kinds: vec![TlvKinds::SHA256, TlvKinds::ENCKW],
210             ..Default::default()
211         }
212     }
213 
214     #[allow(dead_code)]
new_rsa_kw(aes_key_size: u32) -> TlvGen215     pub fn new_rsa_kw(aes_key_size: u32) -> TlvGen {
216         let flag = if aes_key_size == 256 {
217             TlvFlags::ENCRYPTED_AES256 as u32
218         } else {
219             TlvFlags::ENCRYPTED_AES128 as u32
220         };
221         TlvGen {
222             flags: flag,
223             kinds: vec![TlvKinds::SHA256, TlvKinds::RSA2048, TlvKinds::ENCKW],
224             ..Default::default()
225         }
226     }
227 
228     #[allow(dead_code)]
new_ecdsa_kw(aes_key_size: u32) -> TlvGen229     pub fn new_ecdsa_kw(aes_key_size: u32) -> TlvGen {
230         let flag = if aes_key_size == 256 {
231             TlvFlags::ENCRYPTED_AES256 as u32
232         } else {
233             TlvFlags::ENCRYPTED_AES128 as u32
234         };
235         TlvGen {
236             flags: flag,
237             kinds: vec![TlvKinds::SHA256, TlvKinds::ECDSASIG, TlvKinds::ENCKW],
238             ..Default::default()
239         }
240     }
241 
242     #[allow(dead_code)]
new_ecies_p256(aes_key_size: u32) -> TlvGen243     pub fn new_ecies_p256(aes_key_size: u32) -> TlvGen {
244         let flag = if aes_key_size == 256 {
245             TlvFlags::ENCRYPTED_AES256 as u32
246         } else {
247             TlvFlags::ENCRYPTED_AES128 as u32
248         };
249         TlvGen {
250             flags: flag,
251             kinds: vec![TlvKinds::SHA256, TlvKinds::ENCEC256],
252             ..Default::default()
253         }
254     }
255 
256     #[allow(dead_code)]
new_ecdsa_ecies_p256(aes_key_size: u32) -> TlvGen257     pub fn new_ecdsa_ecies_p256(aes_key_size: u32) -> TlvGen {
258         let flag = if aes_key_size == 256 {
259             TlvFlags::ENCRYPTED_AES256 as u32
260         } else {
261             TlvFlags::ENCRYPTED_AES128 as u32
262         };
263         TlvGen {
264             flags: flag,
265             kinds: vec![TlvKinds::SHA256, TlvKinds::ECDSASIG, TlvKinds::ENCEC256],
266             ..Default::default()
267         }
268     }
269 
270     #[allow(dead_code)]
new_ecies_x25519(aes_key_size: u32) -> TlvGen271     pub fn new_ecies_x25519(aes_key_size: u32) -> TlvGen {
272         let flag = if aes_key_size == 256 {
273             TlvFlags::ENCRYPTED_AES256 as u32
274         } else {
275             TlvFlags::ENCRYPTED_AES128 as u32
276         };
277         TlvGen {
278             flags: flag,
279             kinds: vec![TlvKinds::SHA256, TlvKinds::ENCX25519],
280             ..Default::default()
281         }
282     }
283 
284     #[allow(dead_code)]
new_ed25519_ecies_x25519(aes_key_size: u32) -> TlvGen285     pub fn new_ed25519_ecies_x25519(aes_key_size: u32) -> TlvGen {
286         let flag = if aes_key_size == 256 {
287             TlvFlags::ENCRYPTED_AES256 as u32
288         } else {
289             TlvFlags::ENCRYPTED_AES128 as u32
290         };
291         TlvGen {
292             flags: flag,
293             kinds: vec![TlvKinds::SHA256, TlvKinds::ED25519, TlvKinds::ENCX25519],
294             ..Default::default()
295         }
296     }
297 }
298 
299 impl ManifestGen for TlvGen {
get_magic(&self) -> u32300     fn get_magic(&self) -> u32 {
301         0x96f3b83d
302     }
303 
304     /// Retrieve the header flags for this configuration.  This can be called at any time.
get_flags(&self) -> u32305     fn get_flags(&self) -> u32 {
306         // For the RamLoad case, add in the flag for this feature.
307         if Caps::RamLoad.present() {
308             self.flags | (TlvFlags::RAM_LOAD as u32)
309         } else {
310             self.flags
311         }
312     }
313 
314     /// Add bytes to the covered hash.
add_bytes(&mut self, bytes: &[u8])315     fn add_bytes(&mut self, bytes: &[u8]) {
316         self.payload.extend_from_slice(bytes);
317     }
318 
protect_size(&self) -> u16319     fn protect_size(&self) -> u16 {
320         if self.dependencies.is_empty() {
321             0
322         } else {
323             // Include the header and space for each dependency.
324             4 + (self.dependencies.len() as u16) * (4 + 4 + 8)
325         }
326     }
327 
add_dependency(&mut self, id: u8, version: &ImageVersion)328     fn add_dependency(&mut self, id: u8, version: &ImageVersion) {
329         self.dependencies.push(Dependency {
330             id,
331             version: version.clone(),
332         });
333     }
334 
corrupt_sig(&mut self)335     fn corrupt_sig(&mut self) {
336         self.gen_corrupted = true;
337     }
338 
estimate_size(&self) -> usize339     fn estimate_size(&self) -> usize {
340         // Begin the estimate with the 4 byte header.
341         let mut estimate = 4;
342         // A very poor estimate.
343 
344         // Estimate the size of the image hash.
345         if self.kinds.contains(&TlvKinds::SHA256) {
346             estimate += 4 + 32;
347         }
348 
349         // Add an estimate in for each of the signature algorithms.
350         if self.kinds.contains(&TlvKinds::RSA2048) {
351             estimate += 4 + 32; // keyhash
352             estimate += 4 + 256; // RSA2048
353         }
354         if self.kinds.contains(&TlvKinds::RSA3072) {
355             estimate += 4 + 32; // keyhash
356             estimate += 4 + 384; // RSA3072
357         }
358         if self.kinds.contains(&TlvKinds::ED25519) {
359             estimate += 4 + 32; // keyhash
360             estimate += 4 + 64; // ED25519 signature.
361         }
362         if self.kinds.contains(&TlvKinds::ECDSASIG) {
363             estimate += 4 + 32; // keyhash
364 
365             // ECDSA signatures are encoded as ASN.1 with the x and y values stored as signed
366             // integers.  As such, the size can vary by 2 bytes, if the 256-bit value has the high
367             // bit, it takes an extra 0 byte to avoid it being seen as a negative number.
368             estimate += 4 + 72; // ECDSA256 (varies)
369         }
370 
371         // Estimate encryption.
372         let flag = TlvFlags::ENCRYPTED_AES256 as u32;
373         let aes256 = (self.get_flags() & flag) == flag;
374 
375         if self.kinds.contains(&TlvKinds::ENCRSA2048) {
376             estimate += 4 + 256;
377         }
378         if self.kinds.contains(&TlvKinds::ENCKW) {
379             estimate += 4 + if aes256 { 40 } else { 24 };
380         }
381         if self.kinds.contains(&TlvKinds::ENCEC256) {
382             estimate += 4 + if aes256 { 129 } else { 113 };
383         }
384         if self.kinds.contains(&TlvKinds::ENCX25519) {
385             estimate += 4 + if aes256 { 96 } else { 80 };
386         }
387 
388         // Gather the size of the dependency information.
389         if self.protect_size() > 0 {
390             estimate += 4 + (16 * self.dependencies.len());
391         }
392 
393         estimate
394     }
395 
396     /// Compute the TLV given the specified block of data.
make_tlv(self: Box<Self>) -> Vec<u8>397     fn make_tlv(self: Box<Self>) -> Vec<u8> {
398         let size_estimate = self.estimate_size();
399 
400         let mut protected_tlv: Vec<u8> = vec![];
401 
402         if self.protect_size() > 0 {
403             protected_tlv.push(0x08);
404             protected_tlv.push(0x69);
405             let size = self.protect_size();
406             protected_tlv.write_u16::<LittleEndian>(size).unwrap();
407             for dep in &self.dependencies {
408                 protected_tlv.write_u16::<LittleEndian>(TlvKinds::DEPENDENCY as u16).unwrap();
409                 protected_tlv.write_u16::<LittleEndian>(12).unwrap();
410 
411                 // The dependency.
412                 protected_tlv.push(dep.id);
413                 protected_tlv.push(0);
414                 protected_tlv.write_u16::<LittleEndian>(0).unwrap();
415                 protected_tlv.push(dep.version.major);
416                 protected_tlv.push(dep.version.minor);
417                 protected_tlv.write_u16::<LittleEndian>(dep.version.revision).unwrap();
418                 protected_tlv.write_u32::<LittleEndian>(dep.version.build_num).unwrap();
419             }
420 
421             assert_eq!(size, protected_tlv.len() as u16, "protected TLV length incorrect");
422         }
423 
424         // Ring does the signature itself, which means that it must be
425         // given a full, contiguous payload.  Although this does help from
426         // a correct usage perspective, it is fairly stupid from an
427         // efficiency view.  If this is shown to be a performance issue
428         // with the tests, the protected data could be appended to the
429         // payload, and then removed after the signature is done.  For now,
430         // just make a signed payload.
431         let mut sig_payload = self.payload.clone();
432         sig_payload.extend_from_slice(&protected_tlv);
433 
434         let mut result: Vec<u8> = vec![];
435 
436         // add back signed payload
437         result.extend_from_slice(&protected_tlv);
438 
439         // add non-protected payload
440         let npro_pos = result.len();
441         result.push(0x07);
442         result.push(0x69);
443         // Placeholder for the size.
444         result.write_u16::<LittleEndian>(0).unwrap();
445 
446         if self.kinds.contains(&TlvKinds::SHA256) {
447             // If a signature is not requested, corrupt the hash we are
448             // generating.  But, if there is a signature, output the
449             // correct hash.  We want the hash test to pass so that the
450             // signature verification can be validated.
451             let mut corrupt_hash = self.gen_corrupted;
452             for k in &[TlvKinds::RSA2048, TlvKinds::RSA3072,
453                 TlvKinds::ED25519, TlvKinds::ECDSASIG]
454             {
455                 if self.kinds.contains(k) {
456                     corrupt_hash = false;
457                     break;
458                 }
459             }
460 
461             if corrupt_hash {
462                 sig_payload[0] ^= 1;
463             }
464 
465             let hash = digest::digest(&digest::SHA256, &sig_payload);
466             let hash = hash.as_ref();
467 
468             assert!(hash.len() == 32);
469             result.write_u16::<LittleEndian>(TlvKinds::SHA256 as u16).unwrap();
470             result.write_u16::<LittleEndian>(32).unwrap();
471             result.extend_from_slice(hash);
472 
473             // Undo the corruption.
474             if corrupt_hash {
475                 sig_payload[0] ^= 1;
476             }
477 
478         }
479 
480         if self.gen_corrupted {
481             // Corrupt what is signed by modifying the input to the
482             // signature code.
483             sig_payload[0] ^= 1;
484         }
485 
486         if self.kinds.contains(&TlvKinds::RSA2048) ||
487             self.kinds.contains(&TlvKinds::RSA3072) {
488 
489             let is_rsa2048 = self.kinds.contains(&TlvKinds::RSA2048);
490 
491             // Output the hash of the public key.
492             let hash = if is_rsa2048 {
493                 digest::digest(&digest::SHA256, RSA_PUB_KEY)
494             } else {
495                 digest::digest(&digest::SHA256, RSA3072_PUB_KEY)
496             };
497             let hash = hash.as_ref();
498 
499             assert!(hash.len() == 32);
500             result.write_u16::<LittleEndian>(TlvKinds::KEYHASH as u16).unwrap();
501             result.write_u16::<LittleEndian>(32).unwrap();
502             result.extend_from_slice(hash);
503 
504             // For now assume PSS.
505             let key_bytes = if is_rsa2048 {
506                 pem::parse(include_bytes!("../../root-rsa-2048.pem").as_ref()).unwrap()
507             } else {
508                 pem::parse(include_bytes!("../../root-rsa-3072.pem").as_ref()).unwrap()
509             };
510             assert_eq!(key_bytes.tag, "RSA PRIVATE KEY");
511             let key_pair = RsaKeyPair::from_der(&key_bytes.contents).unwrap();
512             let rng = rand::SystemRandom::new();
513             let mut signature = vec![0; key_pair.public_modulus_len()];
514             if is_rsa2048 {
515                 assert_eq!(signature.len(), 256);
516             } else {
517                 assert_eq!(signature.len(), 384);
518             }
519             key_pair.sign(&RSA_PSS_SHA256, &rng, &sig_payload, &mut signature).unwrap();
520 
521             if is_rsa2048 {
522                 result.write_u16::<LittleEndian>(TlvKinds::RSA2048 as u16).unwrap();
523             } else {
524                 result.write_u16::<LittleEndian>(TlvKinds::RSA3072 as u16).unwrap();
525             }
526             result.write_u16::<LittleEndian>(signature.len() as u16).unwrap();
527             result.extend_from_slice(&signature);
528         }
529 
530         if self.kinds.contains(&TlvKinds::ECDSASIG) {
531             let rng = rand::SystemRandom::new();
532             let keyhash = digest::digest(&digest::SHA256, ECDSA256_PUB_KEY);
533             let key_bytes = pem::parse(include_bytes!("../../root-ec-p256-pkcs8.pem").as_ref()).unwrap();
534             let sign_algo = &ECDSA_P256_SHA256_ASN1_SIGNING;
535             let key_pair = EcdsaKeyPair::from_pkcs8(sign_algo, &key_bytes.contents).unwrap();
536             let signature = key_pair.sign(&rng,&sig_payload).unwrap();
537 
538             // Write public key
539             let keyhash_slice = keyhash.as_ref();
540             assert!(keyhash_slice.len() == 32);
541             result.write_u16::<LittleEndian>(TlvKinds::KEYHASH as u16).unwrap();
542             result.write_u16::<LittleEndian>(32).unwrap();
543             result.extend_from_slice(keyhash_slice);
544 
545             // Write signature
546             result.write_u16::<LittleEndian>(TlvKinds::ECDSASIG as u16).unwrap();
547             let signature = signature.as_ref().to_vec();
548             result.write_u16::<LittleEndian>(signature.len() as u16).unwrap();
549             result.extend_from_slice(&signature);
550         }
551         if self.kinds.contains(&TlvKinds::ED25519) {
552             let keyhash = digest::digest(&digest::SHA256, ED25519_PUB_KEY);
553             let keyhash = keyhash.as_ref();
554 
555             assert!(keyhash.len() == 32);
556             result.write_u16::<LittleEndian>(TlvKinds::KEYHASH as u16).unwrap();
557             result.write_u16::<LittleEndian>(32).unwrap();
558             result.extend_from_slice(keyhash);
559 
560             let hash = digest::digest(&digest::SHA256, &sig_payload);
561             let hash = hash.as_ref();
562             assert!(hash.len() == 32);
563 
564             let key_bytes = pem::parse(include_bytes!("../../root-ed25519.pem").as_ref()).unwrap();
565             assert_eq!(key_bytes.tag, "PRIVATE KEY");
566 
567             let key_pair = Ed25519KeyPair::from_seed_and_public_key(
568                 &key_bytes.contents[16..48], &ED25519_PUB_KEY[12..44]).unwrap();
569             let signature = key_pair.sign(&hash);
570 
571             result.write_u16::<LittleEndian>(TlvKinds::ED25519 as u16).unwrap();
572 
573             let signature = signature.as_ref().to_vec();
574             result.write_u16::<LittleEndian>(signature.len() as u16).unwrap();
575             result.extend_from_slice(signature.as_ref());
576         }
577 
578         if self.kinds.contains(&TlvKinds::ENCRSA2048) {
579             let key_bytes = pem::parse(include_bytes!("../../enc-rsa2048-pub.pem")
580                                        .as_ref()).unwrap();
581             assert_eq!(key_bytes.tag, "PUBLIC KEY");
582 
583             let cipherkey = self.get_enc_key();
584             let cipherkey = cipherkey.as_slice();
585             let encbuf = match c::rsa_oaep_encrypt(&key_bytes.contents, cipherkey) {
586                 Ok(v) => v,
587                 Err(_) => panic!("Failed to encrypt secret key"),
588             };
589 
590             assert!(encbuf.len() == 256);
591             result.write_u16::<LittleEndian>(TlvKinds::ENCRSA2048 as u16).unwrap();
592             result.write_u16::<LittleEndian>(256).unwrap();
593             result.extend_from_slice(&encbuf);
594         }
595 
596         if self.kinds.contains(&TlvKinds::ENCKW) {
597             let flag = TlvFlags::ENCRYPTED_AES256 as u32;
598             let aes256 = (self.get_flags() & flag) == flag;
599             let key_bytes = if aes256 {
600                 base64::decode(
601                     include_str!("../../enc-aes256kw.b64").trim()).unwrap()
602             } else {
603                 base64::decode(
604                     include_str!("../../enc-aes128kw.b64").trim()).unwrap()
605             };
606             let cipherkey = self.get_enc_key();
607             let cipherkey = cipherkey.as_slice();
608             let keylen = if aes256 { 32 } else { 16 };
609             let encbuf = match c::kw_encrypt(&key_bytes, cipherkey, keylen) {
610                 Ok(v) => v,
611                 Err(_) => panic!("Failed to encrypt secret key"),
612             };
613 
614             let size = if aes256 { 40 } else { 24 };
615             assert!(encbuf.len() == size);
616             result.write_u16::<LittleEndian>(TlvKinds::ENCKW as u16).unwrap();
617             result.write_u16::<LittleEndian>(size as u16).unwrap();
618             result.extend_from_slice(&encbuf);
619         }
620 
621         if self.kinds.contains(&TlvKinds::ENCEC256) || self.kinds.contains(&TlvKinds::ENCX25519) {
622             let key_bytes = if self.kinds.contains(&TlvKinds::ENCEC256) {
623                 pem::parse(include_bytes!("../../enc-ec256-pub.pem").as_ref()).unwrap()
624             } else {
625                 pem::parse(include_bytes!("../../enc-x25519-pub.pem").as_ref()).unwrap()
626             };
627             assert_eq!(key_bytes.tag, "PUBLIC KEY");
628             let rng = rand::SystemRandom::new();
629             let alg = if self.kinds.contains(&TlvKinds::ENCEC256) {
630                 &agreement::ECDH_P256
631             } else {
632                 &agreement::X25519
633             };
634             let pk = match agreement::EphemeralPrivateKey::generate(alg, &rng) {
635                 Ok(v) => v,
636                 Err(_) => panic!("Failed to generate ephemeral keypair"),
637             };
638 
639             let pubk = match pk.compute_public_key() {
640                 Ok(pubk) => pubk,
641                 Err(_) => panic!("Failed computing ephemeral public key"),
642             };
643 
644             let peer_pubk = if self.kinds.contains(&TlvKinds::ENCEC256) {
645                 agreement::UnparsedPublicKey::new(&agreement::ECDH_P256, &key_bytes.contents[26..])
646             } else {
647                 agreement::UnparsedPublicKey::new(&agreement::X25519, &key_bytes.contents[12..])
648             };
649 
650             #[derive(Debug, PartialEq)]
651             struct OkmLen<T: core::fmt::Debug + PartialEq>(T);
652 
653             impl hkdf::KeyType for OkmLen<usize> {
654                 fn len(&self) -> usize {
655                     self.0
656                 }
657             }
658 
659             let flag = TlvFlags::ENCRYPTED_AES256 as u32;
660             let aes256 = (self.get_flags() & flag) == flag;
661 
662             let derived_key = match agreement::agree_ephemeral(
663                 pk, &peer_pubk, ring::error::Unspecified, |shared| {
664                     let salt = hkdf::Salt::new(hkdf::HKDF_SHA256, &[]);
665                     let prk = salt.extract(&shared);
666                     let okm_len = if aes256 { 64 } else { 48 };
667                     let okm = match prk.expand(&[b"MCUBoot_ECIES_v1"], OkmLen(okm_len)) {
668                         Ok(okm) => okm,
669                         Err(_) => panic!("Failed building HKDF OKM"),
670                     };
671                     let mut buf = if aes256 { vec![0u8; 64] } else { vec![0u8; 48] };
672                     match okm.fill(&mut buf) {
673                         Ok(_) => Ok(buf),
674                         Err(_) => panic!("Failed generating HKDF output"),
675                     }
676                 },
677             ) {
678                 Ok(v) => v,
679                 Err(_) => panic!("Failed building HKDF"),
680             };
681 
682             let nonce = GenericArray::from_slice(&[0; 16]);
683             let mut cipherkey = self.get_enc_key();
684             if aes256 {
685                 let key: &GenericArray<u8, U32> = GenericArray::from_slice(&derived_key[..32]);
686                 let block = Aes256::new(&key);
687                 let mut cipher = Aes256Ctr::from_block_cipher(block, &nonce);
688                 cipher.apply_keystream(&mut cipherkey);
689             } else {
690                 let key: &GenericArray<u8, U16> = GenericArray::from_slice(&derived_key[..16]);
691                 let block = Aes128::new(&key);
692                 let mut cipher = Aes128Ctr::from_block_cipher(block, &nonce);
693                 cipher.apply_keystream(&mut cipherkey);
694             }
695 
696             let size = if aes256 { 32 } else { 16 };
697             let key = hmac::Key::new(hmac::HMAC_SHA256, &derived_key[size..]);
698             let tag = hmac::sign(&key, &cipherkey);
699 
700             let mut buf = vec![];
701             buf.append(&mut pubk.as_ref().to_vec());
702             buf.append(&mut tag.as_ref().to_vec());
703             buf.append(&mut cipherkey);
704 
705             if self.kinds.contains(&TlvKinds::ENCEC256) {
706                 let size = if aes256 { 129 } else { 113 };
707                 assert!(buf.len() == size);
708                 result.write_u16::<LittleEndian>(TlvKinds::ENCEC256 as u16).unwrap();
709                 result.write_u16::<LittleEndian>(size as u16).unwrap();
710             } else {
711                 let size = if aes256 { 96 } else { 80 };
712                 assert!(buf.len() == size);
713                 result.write_u16::<LittleEndian>(TlvKinds::ENCX25519 as u16).unwrap();
714                 result.write_u16::<LittleEndian>(size as u16).unwrap();
715             }
716             result.extend_from_slice(&buf);
717         }
718 
719         // Patch the size back into the TLV header.
720         let size = (result.len() - npro_pos) as u16;
721         let mut size_buf = &mut result[npro_pos + 2 .. npro_pos + 4];
722         size_buf.write_u16::<LittleEndian>(size).unwrap();
723 
724         // ECDSA is stored as an ASN.1 integer.  For a 128-bit value, this maximally results in 33
725         // bytes of storage for each of the two values.  If the high bit is zero, it will take 32
726         // bytes, if the top 8 bits are zero, it will take 31 bits, and so on.  The smaller size
727         // will occur with decreasing likelihood.  We'll allow this to get a bit smaller, hopefully
728         // allowing the tests to pass with false failures rare.  For this case, we'll handle up to
729         // the top 16 bits of both numbers being all zeros (1 in 2^32).
730         if !Caps::has_ecdsa() {
731             if size_estimate != result.len() {
732                 panic!("Incorrect size estimate: {} (actual {})", size_estimate, result.len());
733             }
734         } else {
735             if size_estimate < result.len() || size_estimate > result.len() + 6 {
736                 panic!("Incorrect size estimate: {} (actual {})", size_estimate, result.len());
737             }
738         }
739         if size_estimate != result.len() {
740             log::warn!("Size off: {} actual {}", size_estimate, result.len());
741         }
742 
743         result
744     }
745 
generate_enc_key(&mut self)746     fn generate_enc_key(&mut self) {
747         let rng = rand::SystemRandom::new();
748         let flag = TlvFlags::ENCRYPTED_AES256 as u32;
749         let aes256 = (self.get_flags() & flag) == flag;
750         let mut buf = if aes256 {
751             vec![0u8; 32]
752         } else {
753             vec![0u8; 16]
754         };
755         if rng.fill(&mut buf).is_err() {
756             panic!("Error generating encrypted key");
757         }
758         info!("New encryption key: {:02x?}", buf);
759         self.enc_key = buf;
760     }
761 
get_enc_key(&self) -> Vec<u8>762     fn get_enc_key(&self) -> Vec<u8> {
763         if self.enc_key.len() != 32 && self.enc_key.len() != 16 {
764             panic!("No random key was generated");
765         }
766         self.enc_key.clone()
767     }
768 }
769 
770 include!("rsa_pub_key-rs.txt");
771 include!("rsa3072_pub_key-rs.txt");
772 include!("ecdsa_pub_key-rs.txt");
773 include!("ed25519_pub_key-rs.txt");
774