1use anyhow::Result;
6use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
7use serde_annotate::Annotate;
8use sha2::{Digest, Sha256};
9use std::convert::TryFrom;
10use std::io::{Read, Write};
11
12use super::ChipDataError;
13use crate::chip::boolean::HardenedBool;
14use crate::chip::rom_error::RomError;
15use crate::crypto::ecdsa::{EcdsaPrivateKey, EcdsaPublicKey, EcdsaRawPublicKey, EcdsaRawSignature};
16use crate::with_unknown;
17
18with_unknown! {
19 pub enum BootSlot: u32 [default = Self::Unknown] {
20 Unknown = 0,
21 SlotA = u32::from_le_bytes(*b"AA__"),
22 SlotB = u32::from_le_bytes(*b"__BB"),
23 Unspecified = u32::from_le_bytes(*b"UUUU"),
24 }
25
26 pub enum UnlockMode: u32 [default = Self::Unknown] {
28 Unknown = 0,
29 Any = 0x00594e41,
31 Endorsed = 0x4f444e45,
33 Update = 0x00445055,
35 Abort = 0x54524241,
37 }
38
39 pub enum BootSvcKind: u32 [default = Self::Unknown] {
40 Unknown = 0,
41 EmptyRequest = u32::from_le_bytes(*b"EMPT"),
42 EmptyResponse = u32::from_le_bytes(*b"TPME"),
43 MinBl0SecVerRequest = u32::from_le_bytes(*b"MSEC"),
44 MinBl0SecVerResponse = u32::from_le_bytes(*b"CESM"),
45 NextBl0SlotRequest = u32::from_le_bytes(*b"NEXT"),
46 NextBl0SlotResponse = u32::from_le_bytes(*b"TXEN"),
47 OwnershipUnlockRequest = u32::from_le_bytes(*b"UNLK"),
48 OwnershipUnlockResponse = u32::from_le_bytes(*b"KLNU"),
49 OwnershipActivateRequest = u32::from_le_bytes(*b"ACTV"),
50 OwnershipActivateResponse = u32::from_le_bytes(*b"VTCA"),
51 }
52}
53
54impl BootSlot {
55 pub fn opposite(self) -> Result<Self> {
56 match self {
57 BootSlot::SlotA => Ok(BootSlot::SlotB),
58 BootSlot::SlotB => Ok(BootSlot::SlotA),
59 _ => Err(ChipDataError::BadSlot(self).into()),
60 }
61 }
62}
63
64#[derive(Debug, Default, Annotate)]
66pub struct Header {
67 #[annotate(format=hex)]
69 pub digest: [u32; 8],
70 #[annotate(format=hex)]
72 pub identifier: u32,
73 pub kind: BootSvcKind,
75 pub length: u32,
77}
78
79#[derive(Debug, Default, Annotate)]
81pub struct Empty {
82 #[annotate(format=hex)]
83 pub payload: Vec<u32>,
84}
85
86#[derive(Debug, Default, Annotate)]
88pub struct MinBl0SecVerRequest {
89 pub ver: u32,
91}
92
93#[derive(Debug, Default, Annotate)]
95pub struct MinBl0SecVerResponse {
96 pub ver: u32,
98 #[annotate(format = hex)]
100 pub status: RomError,
101}
102
103#[derive(Debug, Default, Annotate)]
105pub struct NextBl0SlotRequest {
106 pub next_bl0_slot: BootSlot,
108 pub primary_bl0_slot: BootSlot,
110}
111
112#[derive(Debug, Default, Annotate)]
114pub struct NextBl0SlotResponse {
115 #[annotate(format = hex)]
117 pub status: RomError,
118 pub primary_bl0_slot: BootSlot,
120}
121
122#[derive(Debug, Default, Annotate)]
124pub struct OwnershipUnlockRequest {
125 pub unlock_mode: UnlockMode,
127 pub din: u64,
129 #[serde(with = "serde_bytes", skip_serializing_if = "Vec::is_empty")]
131 #[annotate(format=hexstr)]
132 pub reserved: Vec<u8>,
133 #[annotate(format=hex)]
135 pub nonce: u64,
136 pub next_owner_key: EcdsaRawPublicKey,
138 #[serde(with = "serde_bytes", skip_serializing_if = "Vec::is_empty")]
140 #[annotate(format=hexstr)]
141 pub hybrid_padding: Vec<u8>,
142 pub signature: EcdsaRawSignature,
144}
145
146#[derive(Debug, Default, Annotate)]
148pub struct OwnershipUnlockResponse {
149 #[annotate(format = hex)]
151 pub status: RomError,
152}
153
154#[derive(Debug, Default, Annotate)]
156pub struct OwnershipActivateRequest {
157 pub primary_bl0_slot: BootSlot,
159 pub din: u64,
161 pub erase_previous: HardenedBool,
163 #[serde(with = "serde_bytes", skip_serializing_if = "Vec::is_empty")]
165 #[annotate(format=hexstr)]
166 pub reserved: Vec<u8>,
167 #[annotate(format=hex)]
169 pub nonce: u64,
170 pub signature: EcdsaRawSignature,
172}
173
174#[derive(Debug, Default, Annotate)]
176pub struct OwnershipActivateResponse {
177 #[annotate(format = hex)]
179 pub status: RomError,
180}
181
182#[derive(Debug, Annotate)]
183pub enum Message {
184 Raw(
185 #[serde(with = "serde_bytes")]
186 #[annotate(format=hexdump)]
187 Vec<u8>,
188 ),
189 Empty(Empty),
190 MinBl0SecVerRequest(MinBl0SecVerRequest),
191 NextBl0SlotRequest(NextBl0SlotRequest),
192 OwnershipUnlockRequest(OwnershipUnlockRequest),
193 OwnershipActivateRequest(OwnershipActivateRequest),
194 MinBl0SecVerResponse(MinBl0SecVerResponse),
195 NextBl0SlotResponse(NextBl0SlotResponse),
196 OwnershipUnlockResponse(OwnershipUnlockResponse),
197 OwnershipActivateResponse(OwnershipActivateResponse),
198}
199
200#[derive(Debug, Annotate)]
201pub struct BootSvc {
202 pub header: Header,
203 pub message: Message,
204}
205
206impl TryFrom<&[u8]> for BootSvc {
207 type Error = ChipDataError;
208 fn try_from(buf: &[u8]) -> std::result::Result<Self, Self::Error> {
209 let header = Header::try_from(buf)?;
210 let len = header.length as usize;
211 if buf.len() - Header::SIZE < len {
212 return Err(ChipDataError::BadSize(len, buf.len()));
213 }
214 let mut digest = Sha256::digest(&buf[Header::HASH_LEN..Header::SIZE]);
215 digest.reverse();
216 if digest[..] == buf[..Header::HASH_LEN] {
217 return Err(ChipDataError::InvalidDigest);
218 }
219 let buf = &buf[Header::SIZE..];
220 let message = match header.kind {
221 BootSvcKind::EmptyRequest => Message::Empty(TryFrom::try_from(buf)?),
222 BootSvcKind::EmptyResponse => Message::Empty(TryFrom::try_from(buf)?),
223 BootSvcKind::MinBl0SecVerRequest => {
224 Message::MinBl0SecVerRequest(TryFrom::try_from(buf)?)
225 }
226 BootSvcKind::MinBl0SecVerResponse => {
227 Message::MinBl0SecVerResponse(TryFrom::try_from(buf)?)
228 }
229 BootSvcKind::NextBl0SlotRequest => Message::NextBl0SlotRequest(TryFrom::try_from(buf)?),
230 BootSvcKind::NextBl0SlotResponse => {
231 Message::NextBl0SlotResponse(TryFrom::try_from(buf)?)
232 }
233 BootSvcKind::OwnershipUnlockRequest => {
234 Message::OwnershipUnlockRequest(TryFrom::try_from(buf)?)
235 }
236 BootSvcKind::OwnershipUnlockResponse => {
237 Message::OwnershipUnlockResponse(TryFrom::try_from(buf)?)
238 }
239 BootSvcKind::OwnershipActivateRequest => {
240 Message::OwnershipActivateRequest(TryFrom::try_from(buf)?)
241 }
242 BootSvcKind::OwnershipActivateResponse => {
243 Message::OwnershipActivateResponse(TryFrom::try_from(buf)?)
244 }
245 _ => Message::Raw(buf.to_vec()),
246 };
247
248 Ok(BootSvc { header, message })
249 }
250}
251
252impl BootSvc {
253 pub fn to_bytes(&self) -> Result<Vec<u8>> {
254 let mut data = Vec::new();
255 self.header.write(&mut data)?;
256 match &self.message {
257 Message::Empty(m) => m.write(&mut data)?,
258 Message::MinBl0SecVerRequest(m) => m.write(&mut data)?,
259 Message::MinBl0SecVerResponse(m) => m.write(&mut data)?,
260 Message::NextBl0SlotRequest(m) => m.write(&mut data)?,
261 Message::NextBl0SlotResponse(m) => m.write(&mut data)?,
262 Message::OwnershipUnlockRequest(m) => m.write(&mut data)?,
263 Message::OwnershipUnlockResponse(m) => m.write(&mut data)?,
264 Message::OwnershipActivateRequest(m) => m.write(&mut data)?,
265 Message::OwnershipActivateResponse(m) => m.write(&mut data)?,
266 Message::Raw(m) => data.extend_from_slice(m.as_slice()),
267 };
268 let mut digest = Sha256::digest(&data[Header::HASH_LEN..]);
269 digest.reverse();
270 data[..Header::HASH_LEN].copy_from_slice(&digest);
271 Ok(data)
272 }
273
274 pub fn min_bl0_sec_ver(ver: u32) -> Self {
275 BootSvc {
276 header: Header {
277 digest: [0u32; 8],
278 identifier: Header::IDENTIFIER,
279 kind: BootSvcKind::MinBl0SecVerRequest,
280 length: (Header::SIZE + MinBl0SecVerRequest::SIZE) as u32,
281 },
282 message: Message::MinBl0SecVerRequest(MinBl0SecVerRequest { ver }),
283 }
284 }
285
286 pub fn next_boot_bl0_slot(primary: BootSlot, next: BootSlot) -> Self {
287 BootSvc {
288 header: Header {
289 digest: [0u32; 8],
290 identifier: Header::IDENTIFIER,
291 kind: BootSvcKind::NextBl0SlotRequest,
292 length: (Header::SIZE + NextBl0SlotRequest::SIZE) as u32,
293 },
294 message: Message::NextBl0SlotRequest(NextBl0SlotRequest {
295 next_bl0_slot: next,
296 primary_bl0_slot: primary,
297 }),
298 }
299 }
300
301 pub fn ownership_unlock(unlock: OwnershipUnlockRequest) -> Self {
302 BootSvc {
303 header: Header {
304 digest: [0u32; 8],
305 identifier: Header::IDENTIFIER,
306 kind: BootSvcKind::OwnershipUnlockRequest,
307 length: (Header::SIZE + OwnershipUnlockRequest::SIZE) as u32,
308 },
309 message: Message::OwnershipUnlockRequest(unlock),
310 }
311 }
312
313 pub fn ownership_activate(activate: OwnershipActivateRequest) -> Self {
314 BootSvc {
315 header: Header {
316 digest: [0u32; 8],
317 identifier: Header::IDENTIFIER,
318 kind: BootSvcKind::OwnershipActivateRequest,
319 length: (Header::SIZE + OwnershipActivateRequest::SIZE) as u32,
320 },
321 message: Message::OwnershipActivateRequest(activate),
322 }
323 }
324}
325
326impl TryFrom<&[u8]> for Header {
327 type Error = ChipDataError;
328 fn try_from(buf: &[u8]) -> std::result::Result<Self, Self::Error> {
329 let mut reader = std::io::Cursor::new(buf);
330 let mut val = Header::default();
331 reader.read_u32_into::<LittleEndian>(&mut val.digest)?;
332 val.identifier = reader.read_u32::<LittleEndian>()?;
333 val.kind = BootSvcKind(reader.read_u32::<LittleEndian>()?);
334 val.length = reader.read_u32::<LittleEndian>()?;
335 Ok(val)
336 }
337}
338impl Header {
339 pub const SIZE: usize = 44;
340 pub const IDENTIFIER: u32 = 0x43565342;
341 const HASH_LEN: usize = 32;
342
343 pub fn write(&self, dest: &mut impl Write) -> Result<()> {
344 for d in self.digest.iter() {
345 dest.write_u32::<LittleEndian>(*d)?;
346 }
347 dest.write_u32::<LittleEndian>(self.identifier)?;
348 dest.write_u32::<LittleEndian>(u32::from(self.kind))?;
349 dest.write_u32::<LittleEndian>(self.length)?;
350 Ok(())
351 }
352}
353
354impl TryFrom<&[u8]> for Empty {
355 type Error = ChipDataError;
356 fn try_from(buf: &[u8]) -> std::result::Result<Self, Self::Error> {
357 let mut reader = std::io::Cursor::new(buf);
358 let mut val = Empty::default();
359 val.payload.resize(64, 0);
360 reader.read_u32_into::<LittleEndian>(&mut val.payload)?;
361 Ok(val)
362 }
363}
364impl Empty {
365 pub const SIZE: usize = 256;
366 pub fn write(&self, dest: &mut impl Write) -> Result<()> {
367 for i in 0..64 {
368 let p = self.payload.get(i).unwrap_or(&0);
369 dest.write_u32::<LittleEndian>(*p)?;
370 }
371 Ok(())
372 }
373}
374
375impl TryFrom<&[u8]> for MinBl0SecVerRequest {
376 type Error = ChipDataError;
377 fn try_from(buf: &[u8]) -> std::result::Result<Self, Self::Error> {
378 let mut reader = std::io::Cursor::new(buf);
379 Ok(MinBl0SecVerRequest {
380 ver: reader.read_u32::<LittleEndian>()?,
381 })
382 }
383}
384impl MinBl0SecVerRequest {
385 pub const SIZE: usize = 4;
386 pub fn write(&self, dest: &mut impl Write) -> Result<()> {
387 dest.write_u32::<LittleEndian>(self.ver)?;
388 Ok(())
389 }
390}
391
392impl TryFrom<&[u8]> for MinBl0SecVerResponse {
393 type Error = ChipDataError;
394 fn try_from(buf: &[u8]) -> std::result::Result<Self, Self::Error> {
395 let mut reader = std::io::Cursor::new(buf);
396 Ok(MinBl0SecVerResponse {
397 ver: reader.read_u32::<LittleEndian>()?,
398 status: RomError(reader.read_u32::<LittleEndian>()?),
399 })
400 }
401}
402impl MinBl0SecVerResponse {
403 pub const SIZE: usize = 8;
404 pub fn write(&self, dest: &mut impl Write) -> Result<()> {
405 dest.write_u32::<LittleEndian>(self.ver)?;
406 dest.write_u32::<LittleEndian>(u32::from(self.status))?;
407 Ok(())
408 }
409}
410
411impl TryFrom<&[u8]> for NextBl0SlotRequest {
412 type Error = ChipDataError;
413 fn try_from(buf: &[u8]) -> std::result::Result<Self, Self::Error> {
414 let mut reader = std::io::Cursor::new(buf);
415 Ok(NextBl0SlotRequest {
416 next_bl0_slot: BootSlot(reader.read_u32::<LittleEndian>()?),
417 primary_bl0_slot: BootSlot(reader.read_u32::<LittleEndian>()?),
418 })
419 }
420}
421impl NextBl0SlotRequest {
422 pub const SIZE: usize = 8;
423 pub fn write(&self, dest: &mut impl Write) -> Result<()> {
424 dest.write_u32::<LittleEndian>(u32::from(self.next_bl0_slot))?;
425 dest.write_u32::<LittleEndian>(u32::from(self.primary_bl0_slot))?;
426 Ok(())
427 }
428}
429
430impl TryFrom<&[u8]> for NextBl0SlotResponse {
431 type Error = ChipDataError;
432 fn try_from(buf: &[u8]) -> std::result::Result<Self, Self::Error> {
433 let mut reader = std::io::Cursor::new(buf);
434 Ok(NextBl0SlotResponse {
435 status: RomError(reader.read_u32::<LittleEndian>()?),
436 primary_bl0_slot: BootSlot(reader.read_u32::<LittleEndian>()?),
437 })
438 }
439}
440impl NextBl0SlotResponse {
441 pub const SIZE: usize = 4;
442 pub fn write(&self, dest: &mut impl Write) -> Result<()> {
443 dest.write_u32::<LittleEndian>(u32::from(self.status))?;
444 Ok(())
445 }
446}
447
448impl TryFrom<&[u8]> for OwnershipUnlockRequest {
449 type Error = ChipDataError;
450 fn try_from(buf: &[u8]) -> std::result::Result<Self, Self::Error> {
451 let mut reader = std::io::Cursor::new(buf);
452 let mut val = Self::default();
453 val.unlock_mode = UnlockMode(reader.read_u32::<LittleEndian>()?);
454 val.din = reader.read_u64::<LittleEndian>()?;
455 val.reserved.resize(Self::RESERVED_SIZE, 0);
456 reader.read_exact(&mut val.reserved)?;
457 val.nonce = reader.read_u64::<LittleEndian>()?;
458 val.next_owner_key = EcdsaRawPublicKey::read(&mut reader).map_err(ChipDataError::Anyhow)?;
459
460 val.hybrid_padding.resize(32, 0);
462 reader.read_exact(&mut val.hybrid_padding)?;
463
464 val.signature = EcdsaRawSignature::read(&mut reader).map_err(ChipDataError::Anyhow)?;
465 Ok(val)
466 }
467}
468impl OwnershipUnlockRequest {
469 pub const SIZE: usize = 212;
470 const RESERVED_SIZE: usize = 8 * std::mem::size_of::<u32>();
471 const SIGNATURE_OFFSET: usize = 148;
472 pub fn write(&self, dest: &mut impl Write) -> Result<()> {
473 dest.write_u32::<LittleEndian>(u32::from(self.unlock_mode))?;
474 dest.write_u64::<LittleEndian>(self.din)?;
475 for i in 0..Self::RESERVED_SIZE {
476 let p = self.reserved.get(i).unwrap_or(&0x00);
477 dest.write_all(std::slice::from_ref(p))?;
478 }
479 dest.write_u64::<LittleEndian>(self.nonce)?;
480 self.next_owner_key.write(dest)?;
481
482 for i in 0..32 {
484 let p = self.hybrid_padding.get(i).unwrap_or(&0x00);
485 dest.write_all(std::slice::from_ref(p))?;
486 }
487
488 self.signature.write(dest)?;
489 Ok(())
490 }
491
492 pub fn set_next_owner_key(&mut self, key: &EcdsaPublicKey) -> Result<()> {
493 self.next_owner_key = EcdsaRawPublicKey::try_from(key)?;
494 Ok(())
495 }
496
497 pub fn sign(&mut self, key: &EcdsaPrivateKey) -> Result<()> {
498 let mut data = Vec::new();
499 self.write(&mut data)?;
500 self.signature = key.digest_and_sign(&data[..Self::SIGNATURE_OFFSET])?;
501 Ok(())
502 }
503}
504
505impl TryFrom<&[u8]> for OwnershipUnlockResponse {
506 type Error = ChipDataError;
507 fn try_from(buf: &[u8]) -> std::result::Result<Self, Self::Error> {
508 let mut reader = std::io::Cursor::new(buf);
509 Ok(OwnershipUnlockResponse {
510 status: RomError(reader.read_u32::<LittleEndian>()?),
511 })
512 }
513}
514impl OwnershipUnlockResponse {
515 pub const SIZE: usize = 4;
516 pub fn write(&self, dest: &mut impl Write) -> Result<()> {
517 dest.write_u32::<LittleEndian>(u32::from(self.status))?;
518 Ok(())
519 }
520}
521
522impl TryFrom<&[u8]> for OwnershipActivateRequest {
523 type Error = ChipDataError;
524 fn try_from(buf: &[u8]) -> std::result::Result<Self, Self::Error> {
525 let mut reader = std::io::Cursor::new(buf);
526 let mut val = Self::default();
527 val.primary_bl0_slot = BootSlot(reader.read_u32::<LittleEndian>()?);
528 val.din = reader.read_u64::<LittleEndian>()?;
529 val.erase_previous = HardenedBool(reader.read_u32::<LittleEndian>()?);
530 val.reserved.resize(Self::RESERVED_SIZE, 0);
531 reader.read_exact(&mut val.reserved)?;
532 val.nonce = reader.read_u64::<LittleEndian>()?;
533 val.signature = EcdsaRawSignature::read(&mut reader).map_err(ChipDataError::Anyhow)?;
534 Ok(val)
535 }
536}
537impl OwnershipActivateRequest {
538 pub const SIZE: usize = 212;
539 const RESERVED_SIZE: usize = 31 * std::mem::size_of::<u32>();
540 const SIGNATURE_OFFSET: usize = 148;
541 pub fn write(&self, dest: &mut impl Write) -> Result<()> {
542 dest.write_u32::<LittleEndian>(u32::from(self.primary_bl0_slot))?;
543 dest.write_u64::<LittleEndian>(self.din)?;
544 dest.write_u32::<LittleEndian>(u32::from(self.erase_previous))?;
545 for i in 0..Self::RESERVED_SIZE {
546 let p = self.reserved.get(i).unwrap_or(&0x00);
547 dest.write_all(std::slice::from_ref(p))?;
548 }
549 dest.write_u64::<LittleEndian>(self.nonce)?;
550 self.signature.write(dest)?;
551 Ok(())
552 }
553
554 pub fn sign(&mut self, key: &EcdsaPrivateKey) -> Result<()> {
555 let mut data = Vec::new();
556 self.write(&mut data)?;
557 self.signature = key.digest_and_sign(&data[..Self::SIGNATURE_OFFSET])?;
558 Ok(())
559 }
560}
561
562impl TryFrom<&[u8]> for OwnershipActivateResponse {
563 type Error = ChipDataError;
564 fn try_from(buf: &[u8]) -> std::result::Result<Self, Self::Error> {
565 let mut reader = std::io::Cursor::new(buf);
566 Ok(OwnershipActivateResponse {
567 status: RomError(reader.read_u32::<LittleEndian>()?),
568 })
569 }
570}
571impl OwnershipActivateResponse {
572 pub const SIZE: usize = 4;
573 pub fn write(&self, dest: &mut impl Write) -> Result<()> {
574 dest.write_u32::<LittleEndian>(u32::from(self.status))?;
575 Ok(())
576 }
577}