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