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