From 2284ef84a1beb1a67f27934ab13f438c469c2fc0 Mon Sep 17 00:00:00 2001 From: Brad Campbell Date: Mon, 22 May 2023 17:40:49 -0400 Subject: [PATCH] trying to verify rsa signed apps --- Cargo.toml | 1 + boards/Makefile.common | 1 - boards/hail/Cargo.toml | 2 + boards/hail/chip_layout.ld | 4 +- boards/hail/src/main.rs | 44 +++- capsules/rsa_sw/Cargo.toml | 14 ++ capsules/rsa_sw/README.md | 78 ++++++ capsules/rsa_sw/src/lib.rs | 4 + capsules/rsa_sw/src/verifier.rs | 106 ++++++++ kernel/src/hil/public_key_crypto/mod.rs | 1 + kernel/src/hil/public_key_crypto/signature.rs | 35 +++ kernel/src/process_checker.rs | 1 + kernel/src/process_checker/rsa.rs | 226 ++++++++++++++++++ libraries/tock-tbf/src/types.rs | 3 + 14 files changed, 507 insertions(+), 13 deletions(-) create mode 100644 capsules/rsa_sw/Cargo.toml create mode 100644 capsules/rsa_sw/README.md create mode 100644 capsules/rsa_sw/src/lib.rs create mode 100644 capsules/rsa_sw/src/verifier.rs create mode 100644 kernel/src/hil/public_key_crypto/signature.rs create mode 100644 kernel/src/process_checker/rsa.rs diff --git a/Cargo.toml b/Cargo.toml index 01825f0a87..8f95a86bce 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -49,6 +49,7 @@ members = [ "boards/weact_f401ccu6/", "capsules/core", "capsules/extra", + "capsules/rsa_sw", "chips/apollo3", "chips/arty_e21_chip", "chips/e310_g002", diff --git a/boards/Makefile.common b/boards/Makefile.common index 6e9cc9adac..6be1879904 100644 --- a/boards/Makefile.common +++ b/boards/Makefile.common @@ -231,7 +231,6 @@ CARGO_FLAGS ?= # https://github.com/tock/tock/pull/2847 for more details. CARGO_FLAGS_TOCK ?= \ $(VERBOSE_FLAGS) \ - -Z build-std=core,compiler_builtins \ --target=$(TARGET) \ --package $(PLATFORM) \ --target-dir=$(TARGET_DIRECTORY) $(CARGO_FLAGS) diff --git a/boards/hail/Cargo.toml b/boards/hail/Cargo.toml index ed1adadbbb..72ee47dae0 100644 --- a/boards/hail/Cargo.toml +++ b/boards/hail/Cargo.toml @@ -17,3 +17,5 @@ sam4l = { path = "../../chips/sam4l" } capsules-core = { path = "../../capsules/core" } capsules-extra = { path = "../../capsules/extra" } +rsa-sw = { path = "../../capsules/rsa_sw" } +emballoc = "0.1.2" diff --git a/boards/hail/chip_layout.ld b/boards/hail/chip_layout.ld index 4979b83422..6f1b7f8b39 100644 --- a/boards/hail/chip_layout.ld +++ b/boards/hail/chip_layout.ld @@ -2,7 +2,7 @@ /* Bootloader is at address 0x00000000 */ MEMORY { - rom (rx) : ORIGIN = 0x00010000, LENGTH = 0x00020000 - prog (rx) : ORIGIN = 0x00030000, LENGTH = 0x00040000 + rom (rx) : ORIGIN = 0x00010000, LENGTH = 0x00030000 + prog (rx) : ORIGIN = 0x00040000, LENGTH = 0x00030000 ram (rwx) : ORIGIN = 0x20000000, LENGTH = 64K } diff --git a/boards/hail/src/main.rs b/boards/hail/src/main.rs index a016e87cfa..6b2d06ceec 100644 --- a/boards/hail/src/main.rs +++ b/boards/hail/src/main.rs @@ -17,12 +17,13 @@ mod custom_fault_policy; use kernel::capabilities; use kernel::component::Component; +use kernel::deferred_call::DeferredCallClient; use kernel::hil; use kernel::hil::digest::Digest; use kernel::hil::led::LedLow; +use kernel::hil::public_key_crypto::signature::SignatureVerify; use kernel::hil::Controller; use kernel::platform::{KernelResources, SyscallDriverLookup}; -use kernel::process_checker::basic::AppCheckerSha256; use kernel::scheduler::round_robin::RoundRobinSched; #[allow(unused_imports)] use kernel::{create_capability, debug, debug_gpio, static_init}; @@ -50,7 +51,12 @@ static mut PROCESS_PRINTER: Option<&'static kernel::process::ProcessPrinterText> /// Dummy buffer that causes the linker to reserve enough space for the stack. #[no_mangle] #[link_section = ".stack_buffer"] -pub static mut STACK_MEMORY: [u8; 0x1200] = [0; 0x1200]; +pub static mut STACK_MEMORY: [u8; 0x1400] = [0; 0x1400]; + +#[global_allocator] +static ALLOCATOR: emballoc::Allocator<16000> = emballoc::Allocator::new(); + +extern crate alloc; // Function for the process console to use to reboot the board fn reset() -> ! { @@ -100,7 +106,7 @@ struct Hail { scheduler: &'static RoundRobinSched<'static>, systick: cortexm4::systick::SysTick, fault_policy: &'static custom_fault_policy::CredentialedFaultPolicy, - credentials_checking_policy: &'static AppCheckerSha256, + credentials_checking_policy: &'static kernel::process_checker::rsa::AppCheckerRsa2048, } /// Mapping of integer syscalls to objects that implement syscalls. @@ -141,7 +147,7 @@ impl KernelResources> for Hail { type SyscallFilter = (); type ProcessFault = (); type ProcessFaultPolicy = custom_fault_policy::CredentialedFaultPolicy; - type CredentialsCheckingPolicy = AppCheckerSha256; + type CredentialsCheckingPolicy = kernel::process_checker::rsa::AppCheckerRsa2048; type Scheduler = RoundRobinSched<'static>; type SchedulerTimer = cortexm4::systick::SysTick; type WatchDog = (); @@ -508,18 +514,36 @@ pub unsafe fn main() { custom_fault_policy::CredentialedFaultPolicy::new() ); - let sha256_checker_buf = static_init!([u8; 32], [0; 32]); - let sha = static_init!( + /////// + // App Credential Checker + /////// + + let sha256_hash_buf = static_init!([u8; 32], [0; 32]); + let rsa2048_signature_buf = static_init!([u8; 256], [0; 256]); + + let sha256 = static_init!( capsules_extra::sha256::Sha256Software<'static>, capsules_extra::sha256::Sha256Software::new() ); - kernel::deferred_call::DeferredCallClient::register(sha); + sha256.register(); + + let rsa2048verifier = static_init!( + rsa_sw::verifier::RsaSignatureVerifier<'static, 32, 256>, + rsa_sw::verifier::RsaSignatureVerifier::new() + ); + rsa2048verifier.register(); let checker = static_init!( - AppCheckerSha256, - AppCheckerSha256::new(sha, sha256_checker_buf, false) + kernel::process_checker::rsa::AppCheckerRsa2048, + kernel::process_checker::rsa::AppCheckerRsa2048::new( + sha256, + rsa2048verifier, + sha256_hash_buf, + rsa2048_signature_buf + ) ); - sha.set_client(checker); + sha256.set_client(checker); + rsa2048verifier.set_verify_client(checker); let scheduler = components::sched::round_robin::RoundRobinComponent::new(&PROCESSES) .finalize(components::round_robin_component_static!(NUM_PROCS)); diff --git a/capsules/rsa_sw/Cargo.toml b/capsules/rsa_sw/Cargo.toml new file mode 100644 index 0000000000..d1397b4e8e --- /dev/null +++ b/capsules/rsa_sw/Cargo.toml @@ -0,0 +1,14 @@ +# Licensed under the Apache License, Version 2.0 or the MIT License. +# SPDX-License-Identifier: Apache-2.0 OR MIT +# Copyright Tock Contributors 2023. + +[package] +name = "rsa-sw" +version.workspace = true +authors.workspace = true +edition.workspace = true + +[dependencies] +kernel = { path = "../../kernel" } +rsa = { version = "0.9.2", default-features = false, features = ["sha2"] } + diff --git a/capsules/rsa_sw/README.md b/capsules/rsa_sw/README.md new file mode 100644 index 0000000000..53a8e45593 --- /dev/null +++ b/capsules/rsa_sw/README.md @@ -0,0 +1,78 @@ +RSA Software Implementation +=========================== + +This crate provides a software-based implementation of RSA algorithms using +the RustCrypto RSA crate. + +Dependency Tree +--------------- + +``` +rsa-sw v0.1.0 (/Users/bradjc/git/tock/capsules/rsa_sw) +├── kernel v0.1.0 (/Users/bradjc/git/tock/kernel) +│ ├── tock-cells v0.1.0 (/Users/bradjc/git/tock/libraries/tock-cells) +│ ├── tock-registers v0.8.1 (/Users/bradjc/git/tock/libraries/tock-register-interface) +│ └── tock-tbf v0.1.0 (/Users/bradjc/git/tock/libraries/tock-tbf) +└── rsa v0.9.2 + ├── byteorder v1.4.3 + ├── const-oid v0.9.2 + ├── digest v0.10.7 + │ ├── block-buffer v0.10.4 + │ │ └── generic-array v0.14.7 + │ │ └── typenum v1.16.0 + │ │ [build-dependencies] + │ │ └── version_check v0.9.4 + │ ├── const-oid v0.9.2 + │ └── crypto-common v0.1.6 + │ ├── generic-array v0.14.7 (*) + │ └── typenum v1.16.0 + ├── num-bigint-dig v0.8.2 + │ ├── byteorder v1.4.3 + │ ├── lazy_static v1.4.0 + │ │ └── spin v0.5.2 + │ ├── libm v0.2.7 + │ ├── num-integer v0.1.45 + │ │ └── num-traits v0.2.15 + │ │ └── libm v0.2.7 + │ │ [build-dependencies] + │ │ └── autocfg v1.1.0 + │ │ [build-dependencies] + │ │ └── autocfg v1.1.0 + │ ├── num-iter v0.1.43 + │ │ ├── num-integer v0.1.45 (*) + │ │ └── num-traits v0.2.15 (*) + │ │ [build-dependencies] + │ │ └── autocfg v1.1.0 + │ ├── num-traits v0.2.15 (*) + │ ├── rand v0.8.5 + │ │ ├── rand_chacha v0.3.1 + │ │ │ ├── ppv-lite86 v0.2.17 + │ │ │ └── rand_core v0.6.4 + │ │ └── rand_core v0.6.4 + │ ├── smallvec v1.10.0 + │ └── zeroize v1.6.0 + ├── num-integer v0.1.45 (*) + ├── num-iter v0.1.43 (*) + ├── num-traits v0.2.15 (*) + ├── pkcs1 v0.7.5 + │ ├── der v0.7.6 + │ │ ├── const-oid v0.9.2 + │ │ └── zeroize v1.6.0 + │ ├── pkcs8 v0.10.2 + │ │ ├── der v0.7.6 (*) + │ │ └── spki v0.7.2 + │ │ └── der v0.7.6 (*) + │ └── spki v0.7.2 (*) + ├── pkcs8 v0.10.2 (*) + ├── rand_core v0.6.4 + ├── sha2 v0.10.6 + │ ├── cfg-if v1.0.0 + │ ├── cpufeatures v0.2.7 + │ └── digest v0.10.7 (*) + ├── signature v2.1.0 + │ ├── digest v0.10.7 (*) + │ └── rand_core v0.6.4 + ├── spki v0.7.2 (*) + ├── subtle v2.5.0 + └── zeroize v1.6.0 +``` diff --git a/capsules/rsa_sw/src/lib.rs b/capsules/rsa_sw/src/lib.rs new file mode 100644 index 0000000000..21b4d4c896 --- /dev/null +++ b/capsules/rsa_sw/src/lib.rs @@ -0,0 +1,4 @@ +#![forbid(unsafe_code)] +#![no_std] + +pub mod verifier; diff --git a/capsules/rsa_sw/src/verifier.rs b/capsules/rsa_sw/src/verifier.rs new file mode 100644 index 0000000000..2b9d5bb3db --- /dev/null +++ b/capsules/rsa_sw/src/verifier.rs @@ -0,0 +1,106 @@ +// Licensed under the Apache License, Version 2.0 or the MIT License. +// SPDX-License-Identifier: Apache-2.0 OR MIT +// Copyright Tock Contributors 2023. + +//! RSA Signature Verifier for SHA256 hashes and RSA2048 keys. + +use core::cell::Cell; +use kernel::hil; +use kernel::utilities::cells::{MapCell, OptionalCell, TakeCell}; + +pub struct RsaSignatureVerifier<'a, const H: usize, const S: usize> { + verified: Cell, + client: OptionalCell<&'a dyn hil::public_key_crypto::signature::ClientVerify>, + rsa_public_key: MapCell, + hash_storage: TakeCell<'static, [u8; 32]>, + signature_storage: TakeCell<'static, [u8; 256]>, + + deferred_call: kernel::deferred_call::DeferredCall, +} + +impl<'a, const H: usize, const S: usize> RsaSignatureVerifier<'a, H, S> { + pub fn new() -> Self { + // my ACTUAL public key + let n = rsa::BigUint::parse_bytes(b"24207257266404723702480416527933364039116773666417951609465570931679686940076207109293072612569267113256147168695608811123741758650429326896362330556657608406060222154960934834802893052320574456334624928389491520892685313371199210386475223296696579831840058897720325126562243770933238678183073031561719244791265232863605896837907058881808599654200582034457810596804897754743492491685117186551986141408292570229581725243489406524879436825146596246620952685529114397828868686804212048259156058108264250596765840612650253797791010731257875056647324896013942698591287080293236802963873491363585251097167389150803020633481", 10).unwrap(); + let e = rsa::BigUint::parse_bytes(b"65537", 10).unwrap(); + + // Incorrect public key for testing + // let n = rsa::BigUint::parse_bytes(b"34207257266404723702480416527933364039116773666417951609465570931679686940076207109293072612569267113256147168695608811123741758650429326896362330556657608406060222154960934834802893052320574456334624928389491520892685313371199210386475223296696579831840058897720325126562243770933238678183073031561719244791265232863605896837907058881808599654200582034457810596804897754743492491685117186551986141408292570229581725243489406524879436825146596246620952685529114397828868686804212048259156058108264250596765840612650253797791010731257875056647324896013942698591287080293236802963873491363585251097167389150803020633481", 10).unwrap(); + // let e = rsa::BigUint::parse_bytes(b"65537", 10).unwrap(); + + let pub_key = + rsa::RsaPublicKey::new(n, e).map_or_else(|_e| MapCell::empty(), |v| MapCell::new(v)); + + Self { + verified: Cell::new(false), + client: OptionalCell::empty(), + rsa_public_key: pub_key, + hash_storage: TakeCell::empty(), + signature_storage: TakeCell::empty(), + + deferred_call: kernel::deferred_call::DeferredCall::new(), + } + } +} + +impl<'a> hil::public_key_crypto::signature::SignatureVerify<'a, 32, 256> + for RsaSignatureVerifier<'a, 32, 256> +{ + fn set_verify_client( + &'a self, + client: &'a dyn hil::public_key_crypto::signature::ClientVerify<32, 256>, + ) { + self.client.replace(client); + } + + fn verify( + &'a self, + hash: &'static mut [u8; 32], + signature: &'static mut [u8; 256], + ) -> Result< + (), + ( + kernel::ErrorCode, + &'static mut [u8; 32], + &'static mut [u8; 256], + ), + > { + if self.rsa_public_key.is_some() { + self.rsa_public_key + .map(|pub_key| { + self.verified.set( + pub_key + .verify( + rsa::Pkcs1v15Sign::new::(), + hash, + signature, + ) + .is_ok(), + ); + self.hash_storage.replace(hash); + self.signature_storage.replace(signature); + self.deferred_call.set(); + Ok(()) + }) + .unwrap() + } else { + Err((kernel::ErrorCode::FAIL, hash, signature)) + } + } +} + +impl<'a> kernel::deferred_call::DeferredCallClient for RsaSignatureVerifier<'a, 32, 256> { + fn handle_deferred_call(&self) { + self.client.map(|client| { + self.hash_storage.take().map(|h| { + self.signature_storage.take().map(|s| { + client.verification_done(Ok(self.verified.get()), h, s); + }); + }); + }); + } + + fn register(&'static self) { + self.deferred_call.register(self); + } +} diff --git a/kernel/src/hil/public_key_crypto/mod.rs b/kernel/src/hil/public_key_crypto/mod.rs index 66b074ffc9..f9c86d537a 100644 --- a/kernel/src/hil/public_key_crypto/mod.rs +++ b/kernel/src/hil/public_key_crypto/mod.rs @@ -6,3 +6,4 @@ pub mod keys; pub mod rsa_math; +pub mod signature; diff --git a/kernel/src/hil/public_key_crypto/signature.rs b/kernel/src/hil/public_key_crypto/signature.rs new file mode 100644 index 0000000000..18b645c22f --- /dev/null +++ b/kernel/src/hil/public_key_crypto/signature.rs @@ -0,0 +1,35 @@ +// Licensed under the Apache License, Version 2.0 or the MIT License. +// SPDX-License-Identifier: Apache-2.0 OR MIT +// Copyright Tock Contributors 2022. + +//! Interface for verifying signatures. + +use crate::ErrorCode; + +/// This trait provides callbacks for when the verification has completed. +pub trait ClientVerify { + fn verification_done( + &self, + result: Result, + hash: &'static mut [u8; H], + signature: &'static mut [u8; S], + ); +} + +/// Verify a signature. +/// +/// - `H`: The length in bytes of the hash. +/// - `S`: The length in bytes of the signature. +pub trait SignatureVerify<'a, const H: usize, const S: usize> { + /// Set the client instance which will receive the `verification_done()` + /// callback. + #[allow(unused_variables)] + fn set_verify_client(&'a self, client: &'a dyn ClientVerify) {} + + // Verify the signature. Returns `Ok(())` if the signature matches. + fn verify( + &'a self, + hash: &'static mut [u8; H], + signature: &'static mut [u8; S], + ) -> Result<(), (ErrorCode, &'static mut [u8; H], &'static mut [u8; S])>; +} diff --git a/kernel/src/process_checker.rs b/kernel/src/process_checker.rs index a314725358..71766fb4f7 100644 --- a/kernel/src/process_checker.rs +++ b/kernel/src/process_checker.rs @@ -7,6 +7,7 @@ //| the [AppID TRD](../../doc/reference/trd-appid.md). pub mod basic; +pub mod rsa; use crate::config; use crate::debug; diff --git a/kernel/src/process_checker/rsa.rs b/kernel/src/process_checker/rsa.rs new file mode 100644 index 0000000000..d8d154864e --- /dev/null +++ b/kernel/src/process_checker/rsa.rs @@ -0,0 +1,226 @@ +// Licensed under the Apache License, Version 2.0 or the MIT License. +// SPDX-License-Identifier: Apache-2.0 OR MIT +// Copyright Tock Contributors 2022. + +//! RSA credential checkers for checking process credentials. + +use crate::hil; +use crate::process::{Process, ShortID}; +use crate::process_checker::{AppCredentialsChecker, AppUniqueness}; +use crate::process_checker::{CheckResult, Client, Compress}; +use crate::utilities::cells::OptionalCell; +use crate::utilities::cells::TakeCell; +use crate::utilities::leasable_buffer::{LeasableBuffer, LeasableMutableBuffer}; +use crate::ErrorCode; +use tock_tbf::types::TbfFooterV2Credentials; +use tock_tbf::types::TbfFooterV2CredentialsType; + +pub trait Sha256Hasher<'a>: + hil::digest::DigestDataHash<'a, 32_usize> + hil::digest::Sha256 +{ +} +impl<'a, T: hil::digest::DigestDataHash<'a, 32_usize> + hil::digest::Sha256> Sha256Hasher<'a> + for T +{ +} + +pub trait Rsa2048Verifier<'a, const H: usize, const S: usize>: + hil::public_key_crypto::signature::SignatureVerify<'static, 32, 256> +{ +} +impl<'a, T: hil::public_key_crypto::signature::SignatureVerify<'static, 32, 256>> + Rsa2048Verifier<'a, 32, 256> for T +{ +} + +/// Checker that validates correct RSA2048 credentials using a SHA256 hash. +pub struct AppCheckerRsa2048 { + hasher: &'static dyn Sha256Hasher<'static>, + verifier: &'static dyn Rsa2048Verifier<'static, 32, 256>, + hash: TakeCell<'static, [u8; 32]>, + signature: TakeCell<'static, [u8; 256]>, + client: OptionalCell<&'static dyn Client<'static>>, + credentials: OptionalCell, + binary: OptionalCell<&'static [u8]>, +} + +impl AppCheckerRsa2048 { + pub fn new( + hasher: &'static dyn Sha256Hasher<'static>, + verifier: &'static dyn Rsa2048Verifier<'static, 32, 256>, + hash_buffer: &'static mut [u8; 32], + signature_buffer: &'static mut [u8; 256], + ) -> AppCheckerRsa2048 { + Self { + hasher, + verifier, + hash: TakeCell::new(hash_buffer), + signature: TakeCell::new(signature_buffer), + client: OptionalCell::empty(), + credentials: OptionalCell::empty(), + binary: OptionalCell::empty(), + } + } +} + +impl hil::digest::ClientData<32_usize> for AppCheckerRsa2048 { + fn add_mut_data_done( + &self, + _result: Result<(), ErrorCode>, + _data: LeasableMutableBuffer<'static, u8>, + ) { + } + + fn add_data_done(&self, result: Result<(), ErrorCode>, data: LeasableBuffer<'static, u8>) { + // We added the binary data to the hasher, now we can compute the hash. + match result { + Err(_e) => {} + Ok(()) => { + self.binary.set(data.take()); + + self.hash.take().map(|h| match self.hasher.run(h) { + Err((_e, _)) => {} + Ok(()) => {} + }); + } + } + } +} + +impl hil::digest::ClientHash<32_usize> for AppCheckerRsa2048 { + fn hash_done(&self, result: Result<(), ErrorCode>, digest: &'static mut [u8; 32]) { + match result { + Err(_e) => {} + Ok(()) => { + self.signature + .take() + .map(|s| match self.verifier.verify(digest, s) { + Err((_e, _, _)) => {} + Ok(()) => {} + }); + } + } + } +} + +impl<'a> hil::digest::ClientVerify<32_usize> for AppCheckerRsa2048 { + fn verification_done( + &self, + _result: Result, + _compare: &'static mut [u8; 32_usize], + ) { + // Unused for this checker. + // Needed to make the sha256 client work. + } +} + +impl hil::public_key_crypto::signature::ClientVerify<32_usize, 256_usize> for AppCheckerRsa2048 { + fn verification_done( + &self, + result: Result, + hash: &'static mut [u8; 32], + signature: &'static mut [u8; 256], + ) { + self.hash.replace(hash); + self.signature.replace(signature); + + self.client.map(|c| { + let binary = self.binary.take().unwrap(); + let cred = self.credentials.take().unwrap(); + let check_result = if result.unwrap_or(false) { + Ok(CheckResult::Accept) + } else { + Ok(CheckResult::Pass) + }; + + c.check_done(check_result, cred, binary) + }); + } +} + +impl AppCredentialsChecker<'static> for AppCheckerRsa2048 { + fn require_credentials(&self) -> bool { + true + } + + fn check_credentials( + &self, + credentials: TbfFooterV2Credentials, + binary: &'static [u8], + ) -> Result<(), (ErrorCode, TbfFooterV2Credentials, &'static [u8])> { + self.credentials.set(credentials); + + match credentials.format() { + TbfFooterV2CredentialsType::Rsa2048 => { + // Save the signature we are trying to compare with. + self.signature.map(|b| { + for i in 0..256 { + b[i] = credentials.data()[i]; + } + }); + + // Add the process binary to compute the hash. + self.hasher.clear_data(); + match self.hasher.add_data(LeasableBuffer::new(binary)) { + Ok(()) => Ok(()), + Err((e, b)) => Err((e, credentials, b.take())), + } + } + _ => Err((ErrorCode::NOSUPPORT, credentials, binary)), + } + } + + fn set_client(&self, client: &'static dyn Client<'static>) { + self.client.replace(client); + } +} + +impl AppUniqueness for AppCheckerRsa2048 { + fn different_identifier(&self, process_a: &dyn Process, process_b: &dyn Process) -> bool { + let cred_a = process_a.get_credentials(); + let cred_b = process_b.get_credentials(); + + // If it doesn't have credentials, it is by definition + // different. It should not be runnable (this checker requires + // credentials), but if this returned false it could block + // runnable processes from running. + cred_a.map_or(true, |a| { + cred_b.map_or(true, |b| { + // Two IDs are different if they have a different format, + // different length (should not happen, but worth checking for + // the next test), or any byte of them differs. + if a.format() != b.format() { + true + } else if a.data().len() != b.data().len() { + true + } else { + for (aval, bval) in a.data().iter().zip(b.data().iter()) { + if aval != bval { + return true; + } + } + false + } + }) + }) + } +} + +impl Compress for AppCheckerRsa2048 { + fn to_short_id(&self, credentials: &TbfFooterV2Credentials) -> ShortID { + // Should never trigger, as we only approve RSA3072 and RSA4096 credentials. + let data = credentials.data(); + if data.len() < 4 { + return ShortID::LocallyUnique; + } + let id: u32 = 0x8000000 as u32 + | (data[0] as u32) << 24 + | (data[1] as u32) << 16 + | (data[2] as u32) << 8 + | (data[3] as u32); + match core::num::NonZeroU32::new(id) { + Some(nzid) => ShortID::Fixed(nzid), + None => ShortID::LocallyUnique, // Should never be generated + } + } +} diff --git a/libraries/tock-tbf/src/types.rs b/libraries/tock-tbf/src/types.rs index 66db3c3272..b36b03ac46 100644 --- a/libraries/tock-tbf/src/types.rs +++ b/libraries/tock-tbf/src/types.rs @@ -248,6 +248,7 @@ pub enum TbfFooterV2CredentialsType { SHA256 = 3, SHA384 = 4, SHA512 = 5, + Rsa2048 = 10, } #[derive(Clone, Copy, Debug)] @@ -615,6 +616,7 @@ impl core::convert::TryFrom<&'static [u8]> for TbfFooterV2Credentials { 3 => TbfFooterV2CredentialsType::SHA256, 4 => TbfFooterV2CredentialsType::SHA384, 5 => TbfFooterV2CredentialsType::SHA512, + 10 => TbfFooterV2CredentialsType::Rsa2048, _ => { return Err(TbfParseError::InternalError); } @@ -626,6 +628,7 @@ impl core::convert::TryFrom<&'static [u8]> for TbfFooterV2Credentials { TbfFooterV2CredentialsType::SHA256 => 32, TbfFooterV2CredentialsType::SHA384 => 48, TbfFooterV2CredentialsType::SHA512 => 64, + TbfFooterV2CredentialsType::Rsa2048 => 256, }; let data = &b .get(4..(length + 4))