blob: 8d21e84839d26d74dfc18d79a505cf8d0c91952e [file] [log] [blame]
David Brown187dd882017-07-11 11:15:23 -06001//! TLV Support
2//!
3//! mcuboot images are followed immediately by a list of TLV items that contain integrity
4//! information about the image. Their generation is made a little complicated because the size of
5//! the TLV block is in the image header, which is included in the hash. Since some signatures can
6//! vary in size, we just make them the largest size possible.
7//!
8//! Because of this header, we have to make two passes. The first pass will compute the size of
9//! the TLV, and the second pass will build the data for the TLV.
10
David Brown91d68632019-07-29 14:32:13 -060011use byteorder::{
12 LittleEndian, WriteBytesExt,
13};
David Brown7a81c4b2019-07-29 15:20:21 -060014use crate::image::ImageVersion;
David Brown7e701d82017-07-11 13:24:25 -060015use pem;
Fabio Utzig1e48b912018-09-18 09:04:18 -030016use base64;
Fabio Utzig05ab0142018-07-10 09:15:28 -030017use ring::{digest, rand};
18use ring::signature::{
19 RsaKeyPair,
20 RSA_PSS_SHA256,
21 EcdsaKeyPair,
22 ECDSA_P256_SHA256_ASN1_SIGNING,
Fabio Utzig97710282019-05-24 17:44:49 -030023 Ed25519KeyPair,
Fabio Utzig05ab0142018-07-10 09:15:28 -030024};
David Brown7e701d82017-07-11 13:24:25 -060025use untrusted;
Fabio Utzig80fde2f2017-12-05 09:25:31 -020026use mcuboot_sys::c;
David Brown187dd882017-07-11 11:15:23 -060027
David Brown187dd882017-07-11 11:15:23 -060028#[repr(u8)]
David Brownc3898d62019-08-05 14:20:02 -060029#[derive(Copy, Clone, Debug, PartialEq, Eq)]
David Brown187dd882017-07-11 11:15:23 -060030#[allow(dead_code)] // TODO: For now
31pub enum TlvKinds {
David Brown43cda332017-09-01 09:53:23 -060032 KEYHASH = 0x01,
David Brown27648b82017-08-31 10:40:29 -060033 SHA256 = 0x10,
34 RSA2048 = 0x20,
35 ECDSA224 = 0x21,
36 ECDSA256 = 0x22,
Fabio Utzig39297432019-05-08 18:51:10 -030037 RSA3072 = 0x23,
Fabio Utzig97710282019-05-24 17:44:49 -030038 ED25519 = 0x24,
Fabio Utzig1e48b912018-09-18 09:04:18 -030039 ENCRSA2048 = 0x30,
40 ENCKW128 = 0x31,
David Brown7a81c4b2019-07-29 15:20:21 -060041 DEPENDENCY = 0x40,
Fabio Utzig1e48b912018-09-18 09:04:18 -030042}
43
44#[allow(dead_code, non_camel_case_types)]
45pub enum TlvFlags {
46 PIC = 0x01,
47 NON_BOOTABLE = 0x02,
48 ENCRYPTED = 0x04,
49 RAM_LOAD = 0x20,
David Brown187dd882017-07-11 11:15:23 -060050}
51
David Brown43643dd2019-01-11 15:43:28 -070052/// A generator for manifests. The format of the manifest can be either a
53/// traditional "TLV" or a SUIT-style manifest.
54pub trait ManifestGen {
David Brownac46e262019-01-11 15:46:18 -070055 /// Retrieve the header magic value for this manifest type.
56 fn get_magic(&self) -> u32;
57
David Brown43643dd2019-01-11 15:43:28 -070058 /// Retrieve the flags value for this particular manifest type.
59 fn get_flags(&self) -> u32;
60
David Brown7a81c4b2019-07-29 15:20:21 -060061 /// Retrieve the number of bytes of this manifest that is "protected".
62 /// This field is stored in the outside image header instead of the
63 /// manifest header.
64 fn protect_size(&self) -> u16;
65
66 /// Add a dependency on another image.
67 fn add_dependency(&mut self, id: u8, version: &ImageVersion);
68
David Brown43643dd2019-01-11 15:43:28 -070069 /// Add a sequence of bytes to the payload that the manifest is
70 /// protecting.
71 fn add_bytes(&mut self, bytes: &[u8]);
72
73 /// Construct the manifest for this payload.
74 fn make_tlv(self: Box<Self>) -> Vec<u8>;
75}
76
David Brownc3898d62019-08-05 14:20:02 -060077#[derive(Debug)]
David Brown187dd882017-07-11 11:15:23 -060078pub struct TlvGen {
David Brown43cda332017-09-01 09:53:23 -060079 flags: u32,
David Brown187dd882017-07-11 11:15:23 -060080 kinds: Vec<TlvKinds>,
David Brown7a81c4b2019-07-29 15:20:21 -060081 /// The total size of the payload.
David Brown187dd882017-07-11 11:15:23 -060082 size: u16,
David Brown7a81c4b2019-07-29 15:20:21 -060083 /// Extra bytes of the TLV that are protected.
84 protect_size: u16,
David Brown4243ab02017-07-11 12:24:23 -060085 payload: Vec<u8>,
David Brown7a81c4b2019-07-29 15:20:21 -060086 dependencies: Vec<Dependency>,
87}
88
David Brownc3898d62019-08-05 14:20:02 -060089#[derive(Debug)]
David Brown7a81c4b2019-07-29 15:20:21 -060090struct Dependency {
91 id: u8,
92 version: ImageVersion,
David Brown187dd882017-07-11 11:15:23 -060093}
94
Fabio Utzig1e48b912018-09-18 09:04:18 -030095pub const AES_SEC_KEY: &[u8; 16] = b"0123456789ABCDEF";
96
David Brown187dd882017-07-11 11:15:23 -060097impl TlvGen {
98 /// Construct a new tlv generator that will only contain a hash of the data.
David Brown7e701d82017-07-11 13:24:25 -060099 #[allow(dead_code)]
David Brown187dd882017-07-11 11:15:23 -0600100 pub fn new_hash_only() -> TlvGen {
101 TlvGen {
David Brown43cda332017-09-01 09:53:23 -0600102 flags: 0,
David Brown187dd882017-07-11 11:15:23 -0600103 kinds: vec![TlvKinds::SHA256],
104 size: 4 + 32,
David Brown7a81c4b2019-07-29 15:20:21 -0600105 protect_size: 0,
David Brown4243ab02017-07-11 12:24:23 -0600106 payload: vec![],
David Brown7a81c4b2019-07-29 15:20:21 -0600107 dependencies: vec![],
David Brown187dd882017-07-11 11:15:23 -0600108 }
109 }
110
David Brown7e701d82017-07-11 13:24:25 -0600111 #[allow(dead_code)]
112 pub fn new_rsa_pss() -> TlvGen {
113 TlvGen {
David Brown43cda332017-09-01 09:53:23 -0600114 flags: 0,
Fabio Utzig754438d2018-12-14 06:39:58 -0200115 kinds: vec![TlvKinds::SHA256, TlvKinds::RSA2048],
116 size: 4 + 32 + 4 + 32 + 4 + 256,
David Brown7a81c4b2019-07-29 15:20:21 -0600117 protect_size: 0,
David Brown7e701d82017-07-11 13:24:25 -0600118 payload: vec![],
David Brown7a81c4b2019-07-29 15:20:21 -0600119 dependencies: vec![],
David Brown7e701d82017-07-11 13:24:25 -0600120 }
121 }
122
Fabio Utzig80fde2f2017-12-05 09:25:31 -0200123 #[allow(dead_code)]
Fabio Utzig39297432019-05-08 18:51:10 -0300124 pub fn new_rsa3072_pss() -> TlvGen {
125 TlvGen {
126 flags: 0,
127 kinds: vec![TlvKinds::SHA256, TlvKinds::RSA3072],
128 size: 4 + 32 + 4 + 32 + 4 + 384,
David Brown7a81c4b2019-07-29 15:20:21 -0600129 protect_size: 0,
Fabio Utzig39297432019-05-08 18:51:10 -0300130 payload: vec![],
David Brown7a81c4b2019-07-29 15:20:21 -0600131 dependencies: vec![],
Fabio Utzig39297432019-05-08 18:51:10 -0300132 }
133 }
134
135 #[allow(dead_code)]
Fabio Utzig80fde2f2017-12-05 09:25:31 -0200136 pub fn new_ecdsa() -> TlvGen {
137 TlvGen {
138 flags: 0,
Fabio Utzig754438d2018-12-14 06:39:58 -0200139 kinds: vec![TlvKinds::SHA256, TlvKinds::ECDSA256],
140 size: 4 + 32 + 4 + 32 + 4 + 72,
David Brown7a81c4b2019-07-29 15:20:21 -0600141 protect_size: 0,
Fabio Utzig80fde2f2017-12-05 09:25:31 -0200142 payload: vec![],
David Brown7a81c4b2019-07-29 15:20:21 -0600143 dependencies: vec![],
Fabio Utzig80fde2f2017-12-05 09:25:31 -0200144 }
145 }
146
Fabio Utzig1e48b912018-09-18 09:04:18 -0300147 #[allow(dead_code)]
Fabio Utzig97710282019-05-24 17:44:49 -0300148 pub fn new_ed25519() -> TlvGen {
149 TlvGen {
150 flags: 0,
151 kinds: vec![TlvKinds::SHA256, TlvKinds::ED25519],
152 size: 4 + 32 + 4 + 32 + 4 + 64,
David Brown7a81c4b2019-07-29 15:20:21 -0600153 protect_size: 0,
Fabio Utzig97710282019-05-24 17:44:49 -0300154 payload: vec![],
David Brown7a81c4b2019-07-29 15:20:21 -0600155 dependencies: vec![],
Fabio Utzig97710282019-05-24 17:44:49 -0300156 }
157 }
158
159 #[allow(dead_code)]
Fabio Utzig1e48b912018-09-18 09:04:18 -0300160 pub fn new_enc_rsa() -> TlvGen {
161 TlvGen {
162 flags: TlvFlags::ENCRYPTED as u32,
163 kinds: vec![TlvKinds::SHA256, TlvKinds::ENCRSA2048],
164 size: 4 + 32 + 4 + 256,
David Brown7a81c4b2019-07-29 15:20:21 -0600165 protect_size: 0,
Fabio Utzig1e48b912018-09-18 09:04:18 -0300166 payload: vec![],
David Brown7a81c4b2019-07-29 15:20:21 -0600167 dependencies: vec![],
Fabio Utzig1e48b912018-09-18 09:04:18 -0300168 }
169 }
170
171 #[allow(dead_code)]
Fabio Utzig754438d2018-12-14 06:39:58 -0200172 pub fn new_sig_enc_rsa() -> TlvGen {
173 TlvGen {
174 flags: TlvFlags::ENCRYPTED as u32,
175 kinds: vec![TlvKinds::SHA256, TlvKinds::RSA2048, TlvKinds::ENCRSA2048],
176 size: 4 + 32 + 4 + 32 + 4 + 256 + 4 + 256,
David Brown7a81c4b2019-07-29 15:20:21 -0600177 protect_size: 0,
Fabio Utzig754438d2018-12-14 06:39:58 -0200178 payload: vec![],
David Brown7a81c4b2019-07-29 15:20:21 -0600179 dependencies: vec![],
Fabio Utzig754438d2018-12-14 06:39:58 -0200180 }
181 }
182
183 #[allow(dead_code)]
Fabio Utzig1e48b912018-09-18 09:04:18 -0300184 pub fn new_enc_kw() -> TlvGen {
185 TlvGen {
186 flags: TlvFlags::ENCRYPTED as u32,
187 kinds: vec![TlvKinds::SHA256, TlvKinds::ENCKW128],
188 size: 4 + 32 + 4 + 24,
David Brown7a81c4b2019-07-29 15:20:21 -0600189 protect_size: 0,
Fabio Utzig1e48b912018-09-18 09:04:18 -0300190 payload: vec![],
David Brown7a81c4b2019-07-29 15:20:21 -0600191 dependencies: vec![],
Fabio Utzig1e48b912018-09-18 09:04:18 -0300192 }
193 }
194
Fabio Utzig251ef1d2018-12-18 17:20:19 -0200195 #[allow(dead_code)]
196 pub fn new_rsa_kw() -> TlvGen {
197 TlvGen {
198 flags: TlvFlags::ENCRYPTED as u32,
199 kinds: vec![TlvKinds::SHA256, TlvKinds::RSA2048, TlvKinds::ENCKW128],
200 size: 4 + 32 + 4 + 32 + 4 + 256 + 4 + 24,
David Brown7a81c4b2019-07-29 15:20:21 -0600201 protect_size: 0,
Fabio Utzig251ef1d2018-12-18 17:20:19 -0200202 payload: vec![],
David Brown7a81c4b2019-07-29 15:20:21 -0600203 dependencies: vec![],
Fabio Utzig251ef1d2018-12-18 17:20:19 -0200204 }
205 }
206
Fabio Utzigb4d20c82018-12-27 16:08:39 -0200207 #[allow(dead_code)]
208 pub fn new_ecdsa_kw() -> TlvGen {
209 TlvGen {
210 flags: TlvFlags::ENCRYPTED as u32,
211 kinds: vec![TlvKinds::SHA256, TlvKinds::ECDSA256, TlvKinds::ENCKW128],
212 size: 4 + 32 + 4 + 32 + 4 + 72 + 4 + 24,
David Brown7a81c4b2019-07-29 15:20:21 -0600213 protect_size: 0,
Fabio Utzigb4d20c82018-12-27 16:08:39 -0200214 payload: vec![],
David Brown7a81c4b2019-07-29 15:20:21 -0600215 dependencies: vec![],
Fabio Utzigb4d20c82018-12-27 16:08:39 -0200216 }
217 }
218
David Brown187dd882017-07-11 11:15:23 -0600219 /// Retrieve the size that the TLV will occupy. This can be called at any time.
220 pub fn get_size(&self) -> u16 {
David Brownf5b33d82017-09-01 10:58:27 -0600221 4 + self.size
David Brown187dd882017-07-11 11:15:23 -0600222 }
David Brown43643dd2019-01-11 15:43:28 -0700223}
224
225impl ManifestGen for TlvGen {
David Brownac46e262019-01-11 15:46:18 -0700226 fn get_magic(&self) -> u32 {
227 0x96f3b83d
228 }
229
David Brown43643dd2019-01-11 15:43:28 -0700230 /// Retrieve the header flags for this configuration. This can be called at any time.
231 fn get_flags(&self) -> u32 {
232 self.flags
233 }
David Brown187dd882017-07-11 11:15:23 -0600234
235 /// Add bytes to the covered hash.
David Brown43643dd2019-01-11 15:43:28 -0700236 fn add_bytes(&mut self, bytes: &[u8]) {
David Brown4243ab02017-07-11 12:24:23 -0600237 self.payload.extend_from_slice(bytes);
David Brown187dd882017-07-11 11:15:23 -0600238 }
239
David Brown7a81c4b2019-07-29 15:20:21 -0600240 fn protect_size(&self) -> u16 {
241 if self.protect_size == 0 {
242 0
243 } else {
244 // Include the protected size, as well as the TLV header.
245 4 + self.protect_size
246 }
247 }
248
249 fn add_dependency(&mut self, id: u8, version: &ImageVersion) {
250 let my_size = 4 + 4 + 8;
251 self.protect_size += my_size;
252 self.size += my_size;
253 self.dependencies.push(Dependency {
254 id: id,
255 version: version.clone(),
256 });
257 }
258
David Brown187dd882017-07-11 11:15:23 -0600259 /// Compute the TLV given the specified block of data.
David Brown43643dd2019-01-11 15:43:28 -0700260 fn make_tlv(self: Box<Self>) -> Vec<u8> {
Fabio Utzigea3d3ab2019-09-11 19:35:33 -0300261 let mut protected_tlv: Vec<u8> = vec![];
David Brown187dd882017-07-11 11:15:23 -0600262
Fabio Utzigea3d3ab2019-09-11 19:35:33 -0300263 if self.protect_size > 0 {
264 protected_tlv.push(0x08);
265 protected_tlv.push(0x69);
266 protected_tlv.write_u16::<LittleEndian>(self.protect_size()).unwrap();
267 for dep in &self.dependencies {
268 protected_tlv.push(TlvKinds::DEPENDENCY as u8);
269 protected_tlv.push(0);
270 protected_tlv.push(12);
271 protected_tlv.push(0);
David Brownf5b33d82017-09-01 10:58:27 -0600272
Fabio Utzigea3d3ab2019-09-11 19:35:33 -0300273 // The dependency.
274 protected_tlv.push(dep.id);
275 for _ in 0 .. 3 {
276 protected_tlv.push(0);
277 }
278 protected_tlv.push(dep.version.major);
279 protected_tlv.push(dep.version.minor);
280 protected_tlv.write_u16::<LittleEndian>(dep.version.revision).unwrap();
281 protected_tlv.write_u32::<LittleEndian>(dep.version.build_num).unwrap();
David Brown7a81c4b2019-07-29 15:20:21 -0600282 }
David Brown7a81c4b2019-07-29 15:20:21 -0600283 }
284
285 // Ring does the signature itself, which means that it must be
286 // given a full, contiguous payload. Although this does help from
287 // a correct usage perspective, it is fairly stupid from an
288 // efficiency view. If this is shown to be a performance issue
289 // with the tests, the protected data could be appended to the
290 // payload, and then removed after the signature is done. For now,
291 // just make a signed payload.
292 let mut sig_payload = self.payload.clone();
Fabio Utzigea3d3ab2019-09-11 19:35:33 -0300293 sig_payload.extend_from_slice(&protected_tlv);
294
295 let mut result: Vec<u8> = vec![];
296
297 // add back signed payload
298 result.extend_from_slice(&protected_tlv);
299
300 // add non-protected payload
301 result.push(0x07);
302 result.push(0x69);
303 result.write_u16::<LittleEndian>(self.get_size()).unwrap();
David Brown7a81c4b2019-07-29 15:20:21 -0600304
David Brown187dd882017-07-11 11:15:23 -0600305 if self.kinds.contains(&TlvKinds::SHA256) {
David Brown7a81c4b2019-07-29 15:20:21 -0600306 let hash = digest::digest(&digest::SHA256, &sig_payload);
David Brown8054ce22017-07-11 12:12:09 -0600307 let hash = hash.as_ref();
David Brown187dd882017-07-11 11:15:23 -0600308
David Brown8054ce22017-07-11 12:12:09 -0600309 assert!(hash.len() == 32);
David Brown187dd882017-07-11 11:15:23 -0600310 result.push(TlvKinds::SHA256 as u8);
311 result.push(0);
312 result.push(32);
313 result.push(0);
David Brown8054ce22017-07-11 12:12:09 -0600314 result.extend_from_slice(hash);
David Brown187dd882017-07-11 11:15:23 -0600315 }
316
Fabio Utzig39297432019-05-08 18:51:10 -0300317 if self.kinds.contains(&TlvKinds::RSA2048) ||
318 self.kinds.contains(&TlvKinds::RSA3072) {
319
320 let is_rsa2048 = self.kinds.contains(&TlvKinds::RSA2048);
321
David Brown43cda332017-09-01 09:53:23 -0600322 // Output the hash of the public key.
Fabio Utzig39297432019-05-08 18:51:10 -0300323 let hash = if is_rsa2048 {
324 digest::digest(&digest::SHA256, RSA_PUB_KEY)
325 } else {
326 digest::digest(&digest::SHA256, RSA3072_PUB_KEY)
327 };
David Brown43cda332017-09-01 09:53:23 -0600328 let hash = hash.as_ref();
329
330 assert!(hash.len() == 32);
331 result.push(TlvKinds::KEYHASH as u8);
332 result.push(0);
333 result.push(32);
334 result.push(0);
335 result.extend_from_slice(hash);
336
David Brown7e701d82017-07-11 13:24:25 -0600337 // For now assume PSS.
Fabio Utzig39297432019-05-08 18:51:10 -0300338 let key_bytes = if is_rsa2048 {
339 pem::parse(include_bytes!("../../root-rsa-2048.pem").as_ref()).unwrap()
340 } else {
341 pem::parse(include_bytes!("../../root-rsa-3072.pem").as_ref()).unwrap()
342 };
David Brown7e701d82017-07-11 13:24:25 -0600343 assert_eq!(key_bytes.tag, "RSA PRIVATE KEY");
344 let key_bytes = untrusted::Input::from(&key_bytes.contents);
Fabio Utzig05ab0142018-07-10 09:15:28 -0300345 let key_pair = RsaKeyPair::from_der(key_bytes).unwrap();
David Brown7e701d82017-07-11 13:24:25 -0600346 let rng = rand::SystemRandom::new();
Fabio Utzig05ab0142018-07-10 09:15:28 -0300347 let mut signature = vec![0; key_pair.public_modulus_len()];
Fabio Utzig39297432019-05-08 18:51:10 -0300348 if is_rsa2048 {
349 assert_eq!(signature.len(), 256);
350 } else {
351 assert_eq!(signature.len(), 384);
352 }
David Brown7a81c4b2019-07-29 15:20:21 -0600353 key_pair.sign(&RSA_PSS_SHA256, &rng, &sig_payload, &mut signature).unwrap();
David Brown7e701d82017-07-11 13:24:25 -0600354
Fabio Utzig39297432019-05-08 18:51:10 -0300355 if is_rsa2048 {
356 result.push(TlvKinds::RSA2048 as u8);
357 } else {
358 result.push(TlvKinds::RSA3072 as u8);
359 }
David Brown7e701d82017-07-11 13:24:25 -0600360 result.push(0);
David Brown91d68632019-07-29 14:32:13 -0600361 result.write_u16::<LittleEndian>(signature.len() as u16).unwrap();
David Brown7e701d82017-07-11 13:24:25 -0600362 result.extend_from_slice(&signature);
363 }
364
Fabio Utzig80fde2f2017-12-05 09:25:31 -0200365 if self.kinds.contains(&TlvKinds::ECDSA256) {
366 let keyhash = digest::digest(&digest::SHA256, ECDSA256_PUB_KEY);
367 let keyhash = keyhash.as_ref();
368
369 assert!(keyhash.len() == 32);
370 result.push(TlvKinds::KEYHASH as u8);
371 result.push(0);
372 result.push(32);
373 result.push(0);
374 result.extend_from_slice(keyhash);
375
Fabio Utzig05ab0142018-07-10 09:15:28 -0300376 let key_bytes = pem::parse(include_bytes!("../../root-ec-p256-pkcs8.pem").as_ref()).unwrap();
377 assert_eq!(key_bytes.tag, "PRIVATE KEY");
Fabio Utzig80fde2f2017-12-05 09:25:31 -0200378
Fabio Utzig05ab0142018-07-10 09:15:28 -0300379 let key_bytes = untrusted::Input::from(&key_bytes.contents);
380 let key_pair = EcdsaKeyPair::from_pkcs8(&ECDSA_P256_SHA256_ASN1_SIGNING,
381 key_bytes).unwrap();
382 let rng = rand::SystemRandom::new();
David Brown7a81c4b2019-07-29 15:20:21 -0600383 let payload = untrusted::Input::from(&sig_payload);
Fabio Utzig05ab0142018-07-10 09:15:28 -0300384 let signature = key_pair.sign(&rng, payload).unwrap();
Fabio Utzig80fde2f2017-12-05 09:25:31 -0200385
386 result.push(TlvKinds::ECDSA256 as u8);
387 result.push(0);
Fabio Utzig05ab0142018-07-10 09:15:28 -0300388
389 // signature must be padded...
390 let mut signature = signature.as_ref().to_vec();
391 while signature.len() < 72 {
392 signature.push(0);
393 signature[1] += 1;
394 }
395
David Brown91d68632019-07-29 14:32:13 -0600396 result.write_u16::<LittleEndian>(signature.len() as u16).unwrap();
Fabio Utzig05ab0142018-07-10 09:15:28 -0300397 result.extend_from_slice(signature.as_ref());
Fabio Utzig80fde2f2017-12-05 09:25:31 -0200398 }
399
Fabio Utzig97710282019-05-24 17:44:49 -0300400 if self.kinds.contains(&TlvKinds::ED25519) {
401 let keyhash = digest::digest(&digest::SHA256, ED25519_PUB_KEY);
402 let keyhash = keyhash.as_ref();
403
404 assert!(keyhash.len() == 32);
405 result.push(TlvKinds::KEYHASH as u8);
406 result.push(0);
407 result.push(32);
408 result.push(0);
409 result.extend_from_slice(keyhash);
410
David Brown7a81c4b2019-07-29 15:20:21 -0600411 let hash = digest::digest(&digest::SHA256, &sig_payload);
Fabio Utzig97710282019-05-24 17:44:49 -0300412 let hash = hash.as_ref();
413 assert!(hash.len() == 32);
414
415 let key_bytes = pem::parse(include_bytes!("../../root-ed25519.pem").as_ref()).unwrap();
416 assert_eq!(key_bytes.tag, "PRIVATE KEY");
417
418 let seed = untrusted::Input::from(&key_bytes.contents[16..48]);
419 let public = untrusted::Input::from(&ED25519_PUB_KEY[12..44]);
420 let key_pair = Ed25519KeyPair::from_seed_and_public_key(seed, public).unwrap();
421 let signature = key_pair.sign(&hash);
422
423 result.push(TlvKinds::ED25519 as u8);
424 result.push(0);
425
426 let signature = signature.as_ref().to_vec();
David Brown91d68632019-07-29 14:32:13 -0600427 result.write_u16::<LittleEndian>(signature.len() as u16).unwrap();
Fabio Utzig97710282019-05-24 17:44:49 -0300428 result.extend_from_slice(signature.as_ref());
429 }
430
Fabio Utzig1e48b912018-09-18 09:04:18 -0300431 if self.kinds.contains(&TlvKinds::ENCRSA2048) {
432 let key_bytes = pem::parse(include_bytes!("../../enc-rsa2048-pub.pem")
433 .as_ref()).unwrap();
434 assert_eq!(key_bytes.tag, "PUBLIC KEY");
435
436 let encbuf = match c::rsa_oaep_encrypt(&key_bytes.contents, AES_SEC_KEY) {
437 Ok(v) => v,
438 Err(_) => panic!("Failed to encrypt secret key"),
439 };
440
441 assert!(encbuf.len() == 256);
442 result.push(TlvKinds::ENCRSA2048 as u8);
443 result.push(0);
444 result.push(0);
445 result.push(1);
446 result.extend_from_slice(&encbuf);
447 }
448
449 if self.kinds.contains(&TlvKinds::ENCKW128) {
450 let key_bytes = base64::decode(
451 include_str!("../../enc-aes128kw.b64").trim()).unwrap();
452
453 let encbuf = match c::kw_encrypt(&key_bytes, AES_SEC_KEY) {
454 Ok(v) => v,
455 Err(_) => panic!("Failed to encrypt secret key"),
456 };
457
458 assert!(encbuf.len() == 24);
459 result.push(TlvKinds::ENCKW128 as u8);
460 result.push(0);
461 result.push(24);
462 result.push(0);
463 result.extend_from_slice(&encbuf);
464 }
465
David Brown187dd882017-07-11 11:15:23 -0600466 result
467 }
468}
David Brown43cda332017-09-01 09:53:23 -0600469
470include!("rsa_pub_key-rs.txt");
Fabio Utzig39297432019-05-08 18:51:10 -0300471include!("rsa3072_pub_key-rs.txt");
Fabio Utzig80fde2f2017-12-05 09:25:31 -0200472include!("ecdsa_pub_key-rs.txt");
Fabio Utzig97710282019-05-24 17:44:49 -0300473include!("ed25519_pub_key-rs.txt");