Skip to content

Commit 72c9ca0

Browse files
committed
feat: brought updates from tock-tbf into tbf-parser
1 parent 7203555 commit 72c9ca0

3 files changed

Lines changed: 115 additions & 11 deletions

File tree

tbf-parser/src/parse.rs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ pub fn parse_tbf_header(
143143
types::TbfHeaderV2StoragePermissions<8>,
144144
> = None;
145145
let mut kernel_version: Option<types::TbfHeaderV2KernelVersion> = None;
146+
let mut short_id: Option<types::TbfHeaderV2ShortId> = None;
146147

147148
// Iterate the remainder of the header looking for TLV entries.
148149
while !remaining.is_empty() {
@@ -282,6 +283,22 @@ pub fn parse_tbf_header(
282283
}
283284
}
284285

286+
types::TbfHeaderTypes::TbfHeaderShortId => {
287+
let entry_len = mem::size_of::<types::TbfHeaderV2ShortId>();
288+
if tlv_header.length as usize == entry_len {
289+
short_id = Some(
290+
remaining
291+
.get(0..entry_len)
292+
.ok_or(types::TbfParseError::NotEnoughFlash)?
293+
.try_into()?,
294+
);
295+
} else {
296+
return Err(types::TbfParseError::BadTlvEntry(
297+
tlv_header.tipe as usize,
298+
));
299+
}
300+
}
301+
285302
_ => {}
286303
}
287304

@@ -303,6 +320,7 @@ pub fn parse_tbf_header(
303320
permissions: permissions_pointer,
304321
storage_permissions: storage_permissions_pointer,
305322
kernel_version,
323+
short_id,
306324
};
307325

308326
Ok(types::TbfHeader::TbfHeaderV2(tbf_header))
@@ -332,4 +350,4 @@ pub fn parse_tbf_footer(
332350
}
333351
_ => Err(types::TbfParseError::BadTlvEntry(tlv_header.tipe as usize)),
334352
}
335-
}
353+
}

tbf-parser/src/types.rs

Lines changed: 95 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -94,19 +94,21 @@ impl fmt::Debug for TbfParseError {
9494
match self {
9595
TbfParseError::NotEnoughFlash => write!(f, "Buffer too short to parse TBF header"),
9696
TbfParseError::UnsupportedVersion(version) => {
97-
write!(f, "TBF version {version} unsupported")
97+
write!(f, "TBF version {} unsupported", version)
9898
}
9999
TbfParseError::ChecksumMismatch(app, calc) => write!(
100100
f,
101-
"Checksum verification failed: app:{app:#x}, calc:{calc:#x}"
101+
"Checksum verification failed: app:{:#x}, calc:{:#x}",
102+
app, calc
102103
),
103-
TbfParseError::BadTlvEntry(tipe) => write!(f, "TLV entry type {tipe} is invalid"),
104+
TbfParseError::BadTlvEntry(tipe) => write!(f, "TLV entry type {} is invalid", tipe),
104105
TbfParseError::BadProcessName => write!(f, "Process name not UTF-8"),
105106
TbfParseError::InternalError => write!(f, "Internal kernel error. This is a bug."),
106107
TbfParseError::TooManyEntries(tipe) => {
107108
write!(
108109
f,
109-
"There are too many variable entries of {tipe} for Tock to parse"
110+
"There are too many variable entries of {} for Tock to parse",
111+
tipe
110112
)
111113
}
112114
TbfParseError::PackageNameTooLong => write!(f, "The package name is too long."),
@@ -137,6 +139,7 @@ pub enum TbfHeaderTypes {
137139
TbfHeaderStoragePermissions = 7,
138140
TbfHeaderKernelVersion = 8,
139141
TbfHeaderProgram = 9,
142+
TbfHeaderShortId = 10,
140143
TbfFooterCredentials = 128,
141144

142145
/// Some field in the header that we do not understand. Since the TLV format
@@ -254,6 +257,14 @@ pub struct TbfHeaderV2KernelVersion {
254257
minor: u16,
255258
}
256259

260+
/// The v2 ShortId for apps.
261+
///
262+
/// Header to specify a fixed ShortID for an app.
263+
#[derive(Clone, Copy, Debug)]
264+
pub struct TbfHeaderV2ShortId {
265+
short_id: Option<core::num::NonZeroU32>,
266+
}
267+
257268
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
258269
pub enum TbfFooterV2CredentialsType {
259270
Reserved = 0,
@@ -262,6 +273,7 @@ pub enum TbfFooterV2CredentialsType {
262273
SHA256 = 3,
263274
SHA384 = 4,
264275
SHA512 = 5,
276+
EcdsaNistP256 = 6,
265277
}
266278

267279
/// Reference: https://github.com/tock/tock/blob/master/doc/reference/trd-appid.md#52-credentials-footer
@@ -274,6 +286,7 @@ pub enum TbfFooterV2Credentials {
274286
SHA256(TbfFooterV2SHA<32>),
275287
SHA384(TbfFooterV2SHA<48>),
276288
SHA512(TbfFooterV2SHA<64>),
289+
EcdsaNistP256(TbfFooterV2Ecdsa<256>),
277290
}
278291

279292
#[derive(Clone, Copy, Debug)]
@@ -287,6 +300,14 @@ pub struct TbfFooterV2RSA<const L: usize> {
287300
signature: [u8; L],
288301
}
289302

303+
#[derive(Clone, Copy, Debug)]
304+
pub struct TbfFooterV2Ecdsa<const L: usize> {
305+
public_key_x: [u8; 32],
306+
public_key_y: [u8; 32],
307+
signature_r: [u8; 32],
308+
signature_s: [u8; 32],
309+
}
310+
290311
impl<const L: usize> TbfFooterV2SHA<L> {
291312
pub fn get_format(&self) -> Result<TbfFooterV2CredentialsType, TbfParseError> {
292313
match L {
@@ -320,7 +341,28 @@ impl<const L: usize> TbfFooterV2RSA<L> {
320341
}
321342
}
322343

323-
// Conversion functions from slices to the various TBF fields.
344+
impl<const L: usize> TbfFooterV2Ecdsa<L>{
345+
pub fn get_format(&self) -> Result<TbfFooterV2CredentialsType, TbfParseError> {
346+
Ok(TbfFooterV2CredentialsType::EcdsaNistP256)
347+
}
348+
349+
pub fn get_public_key_x(&self) -> &[u8; 32] {
350+
&self.public_key_x
351+
}
352+
353+
pub fn get_public_key_y(&self) -> &[u8; 32] {
354+
&self.public_key_y
355+
}
356+
357+
pub fn get_signature_r(&self) -> &[u8; 32] {
358+
&self.signature_r
359+
}
360+
361+
pub fn get_signature_s(&self) -> &[u8; 32] {
362+
&self.signature_s
363+
}
364+
}
365+
324366

325367
impl core::convert::TryFrom<&[u8]> for TbfHeaderV2Base {
326368
type Error = TbfParseError;
@@ -372,6 +414,7 @@ impl core::convert::TryFrom<u16> for TbfHeaderTypes {
372414
7 => Ok(TbfHeaderTypes::TbfHeaderStoragePermissions),
373415
8 => Ok(TbfHeaderTypes::TbfHeaderKernelVersion),
374416
9 => Ok(TbfHeaderTypes::TbfHeaderProgram),
417+
10 => Ok(TbfHeaderTypes::TbfHeaderShortId),
375418
128 => Ok(TbfHeaderTypes::TbfFooterCredentials),
376419
_ => Ok(TbfHeaderTypes::Unknown),
377420
}
@@ -675,6 +718,20 @@ impl core::convert::TryFrom<&[u8]> for TbfHeaderV2KernelVersion {
675718
}
676719
}
677720

721+
impl core::convert::TryFrom<&[u8]> for TbfHeaderV2ShortId {
722+
type Error = TbfParseError;
723+
724+
fn try_from(b: &[u8]) -> Result<TbfHeaderV2ShortId, Self::Error> {
725+
Ok(TbfHeaderV2ShortId {
726+
short_id: core::num::NonZeroU32::new(u32::from_le_bytes(
727+
b.get(0..4)
728+
.ok_or(TbfParseError::InternalError)?
729+
.try_into()?,
730+
)),
731+
})
732+
}
733+
}
734+
678735
impl core::convert::TryFrom<&[u8]> for TbfFooterV2Credentials {
679736
type Error = TbfParseError;
680737

@@ -691,6 +748,7 @@ impl core::convert::TryFrom<&[u8]> for TbfFooterV2Credentials {
691748
3 => TbfFooterV2CredentialsType::SHA256,
692749
4 => TbfFooterV2CredentialsType::SHA384,
693750
5 => TbfFooterV2CredentialsType::SHA512,
751+
6 => TbfFooterV2CredentialsType::EcdsaNistP256,
694752
_ => {
695753
return Err(TbfParseError::InternalError);
696754
}
@@ -702,6 +760,7 @@ impl core::convert::TryFrom<&[u8]> for TbfFooterV2Credentials {
702760
TbfFooterV2CredentialsType::SHA256 => 32,
703761
TbfFooterV2CredentialsType::SHA384 => 48,
704762
TbfFooterV2CredentialsType::SHA512 => 64,
763+
TbfFooterV2CredentialsType::EcdsaNistP256 => 64,
705764
};
706765

707766
let data = b
@@ -747,6 +806,22 @@ impl core::convert::TryFrom<&[u8]> for TbfFooterV2Credentials {
747806
.map_err(|_| TbfParseError::InternalError)?,
748807
}))
749808
}
809+
TbfFooterV2CredentialsType::EcdsaNistP256 => {
810+
Ok(TbfFooterV2Credentials::EcdsaNistP256(TbfFooterV2Ecdsa {
811+
public_key_x: data[0..32]
812+
.try_into()
813+
.map_err(|_| TbfParseError::InternalError)?,
814+
public_key_y: data[32..64]
815+
.try_into()
816+
.map_err(|_| TbfParseError::InternalError)?,
817+
signature_r: data[64..96]
818+
.try_into()
819+
.map_err(|_| TbfParseError::InternalError)?,
820+
signature_s: data[96..128]
821+
.try_into()
822+
.map_err(|_| TbfParseError::InternalError)?,
823+
}))
824+
}
750825
}
751826
}
752827
}
@@ -760,6 +835,7 @@ impl TbfFooterV2Credentials {
760835
TbfFooterV2Credentials::SHA256(_) => "SHA256",
761836
TbfFooterV2Credentials::SHA384(_) => "SHA384",
762837
TbfFooterV2Credentials::SHA512(_) => "SHA512",
838+
TbfFooterV2Credentials::EcdsaNistP256(_) => "EcdsaNistP256",
763839
}
764840
}
765841
}
@@ -794,6 +870,7 @@ pub struct TbfHeaderV2 {
794870
pub(crate) permissions: Option<TbfHeaderV2Permissions<8>>,
795871
pub(crate) storage_permissions: Option<TbfHeaderV2StoragePermissions<NUM_STORAGE_PERMISSIONS>>,
796872
pub(crate) kernel_version: Option<TbfHeaderV2KernelVersion>,
873+
pub(crate) short_id: Option<TbfHeaderV2ShortId>,
797874
}
798875

799876
/// Type that represents the fields of the Tock Binary Format header.
@@ -967,13 +1044,13 @@ impl TbfHeader {
9671044
}
9681045

9691046
/// Get the offset and size of a given flash region.
970-
pub fn get_writeable_flash_region(&self, index: usize) -> (u32, u32) {
1047+
pub fn get_writeable_flash_region(&self, index: usize) -> (usize, usize) {
9711048
match *self {
9721049
TbfHeader::TbfHeaderV2(hd) => hd.writeable_regions.map_or((0, 0), |wrs| {
9731050
wrs.get(index).unwrap_or(&None).map_or((0, 0), |wr| {
9741051
(
975-
wr.writeable_flash_region_offset,
976-
wr.writeable_flash_region_size,
1052+
wr.writeable_flash_region_offset as usize,
1053+
wr.writeable_flash_region_size as usize,
9771054
)
9781055
})
9791056
}),
@@ -1114,4 +1191,13 @@ impl TbfHeader {
11141191
_ => 0,
11151192
}
11161193
}
1117-
}
1194+
1195+
/// Return the fixed ShortId of the application if it was specified in the
1196+
/// TBF header.
1197+
pub fn get_fixed_short_id(&self) -> Option<core::num::NonZeroU32> {
1198+
match self {
1199+
TbfHeader::TbfHeaderV2(hd) => hd.short_id.and_then(|si| si.short_id),
1200+
_ => None,
1201+
}
1202+
}
1203+
}

tbf-parser/tests/parse.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use tbf_parser::parse::*;
1+
use tbf_parser::{parse::*};
22
use tbf_parser::types::{TbfFooterV2Credentials, TbfFooterV2CredentialsType};
33

44
#[test]

0 commit comments

Comments
 (0)