diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 71ac170e9ff..ab4b18137a3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -36,6 +36,10 @@ jobs: - name: Build run: cargo build --verbose --target ${{ matrix.target }} + - name: Check all targets without default features + run: cargo check --all-targets --no-default-features + if: matrix.target == 'x86_64-unknown-linux-gnu' + - name: Check all targets with default features run: cargo check --all-targets if: matrix.target == 'x86_64-unknown-linux-gnu' diff --git a/CHANGELOG.md b/CHANGELOG.md index de453af138e..724978871f0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,6 +32,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Upgrade the `interchange` dependency to version 0.3.0 ([#99][]) - As a consequence the type `pipe::TrussedInterchange` becomes a const`pipe::TRUSSED_INTERCHANGE` - Updated `littlefs2` to 0.4.0. +- Made `Request`, `Reply`, `Error`, `Context`, `CoreContext`, `Mechanism`, + `ui::Status` non-exhaustive. +- Made `postcard_deserialize`, `postcard_serialize` and + `postcard_serialize_bytes` private. ### Fixed diff --git a/Cargo.toml b/Cargo.toml index b64a140e9f3..9fcd0bc5cfc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,7 +18,7 @@ embedded-hal = { version = "0.2.3", features = ["unproven"] } flexiber = { version = "0.1.0", features = ["derive", "heapless"] } generic-array = "0.14.4" heapless = { version = "0.7", features = ["serde"] } -hex-literal = "0.3.1" +hex-literal = "0.4.1" nb = "1" postcard = "0.7.0" rand_core = "0.6" @@ -36,7 +36,6 @@ des = { version = "0.8", optional = true } hmac = "0.12" sha-1 = { version = "0.10", default-features = false, optional = true } sha2 = { version = "0.10", default-features = false } -num-bigint-dig = { version = "0.8.1", optional = true , default-features = false} # ours cosey = "0.3" @@ -51,7 +50,7 @@ serde-indexed = "0.1.0" [dev-dependencies] # Testing -serial_test = { version = "0.9" } +serial_test = { version = "2" } entropy = "0.4.0" once_cell = "1.13.0" # Somehow, this is causing a regression. @@ -122,7 +121,6 @@ test-attestation-cert-ids = [] [patch.crates-io] # interchange = { git = "https://github.com/trussed-dev/interchange", branch = "main" } -littlefs2 = { git = "https://github.com/Nitrokey/littlefs2", tag = "v0.3.2-nitrokey-1" } [package.metadata.docs.rs] features = ["serde-extensions", "virt"] diff --git a/src/api/macros.rs b/src/api/macros.rs index 0de36555b52..9a486a72e30 100644 --- a/src/api/macros.rs +++ b/src/api/macros.rs @@ -3,6 +3,7 @@ macro_rules! generate_enums { #[derive(Clone, Eq, PartialEq, Debug)] #[allow(clippy::large_enum_variant)] + #[non_exhaustive] pub enum Request { DummyRequest, // for testing $( @@ -13,6 +14,7 @@ macro_rules! generate_enums { #[derive(Clone, Eq, PartialEq, Debug)] #[allow(clippy::large_enum_variant)] + #[non_exhaustive] pub enum Reply { DummyReply, // for testing $( diff --git a/src/config.rs b/src/config.rs index 174293c2183..ed40e95579c 100644 --- a/src/config.rs +++ b/src/config.rs @@ -40,6 +40,8 @@ cfg_if::cfg_if! { pub const MAX_SERVICE_CLIENTS: usize = 2; } else if #[cfg(feature = "clients-1")] { pub const MAX_SERVICE_CLIENTS: usize = 1; + } else { + pub const MAX_SERVICE_CLIENTS: usize = 0; } } pub const MAX_SHORT_DATA_LENGTH: usize = 128; diff --git a/src/error.rs b/src/error.rs index 5d48d4b3394..1444789aa64 100644 --- a/src/error.rs +++ b/src/error.rs @@ -7,6 +7,7 @@ pub type Result = core::result::Result; #[derive(Copy, Clone, Eq, PartialEq, Debug)] #[repr(u32)] +#[non_exhaustive] pub enum Error { // cryptoki errors HostMemory = 0x0000_0002, diff --git a/src/lib.rs b/src/lib.rs index b45fc39a8f4..177dd376c01 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -48,11 +48,12 @@ pub use error::Error; pub use platform::Platform; pub use service::Service; -pub use cbor_smol::{cbor_deserialize, cbor_serialize, cbor_serialize_bytes}; +pub use cbor_smol::{cbor_deserialize, cbor_serialize_bytes}; pub use heapless_bytes::Bytes; -pub use postcard::{from_bytes as postcard_deserialize, to_slice as postcard_serialize}; -pub fn postcard_serialize_bytes( +pub(crate) use postcard::from_bytes as postcard_deserialize; + +pub(crate) fn postcard_serialize_bytes( object: &T, ) -> postcard::Result> { let vec = postcard::to_vec(object)?; diff --git a/src/mechanisms/aes256cbc.rs b/src/mechanisms/aes256cbc.rs index a49d4a7e230..6b0ca4c8fcb 100644 --- a/src/mechanisms/aes256cbc.rs +++ b/src/mechanisms/aes256cbc.rs @@ -167,9 +167,9 @@ impl UnsafeInjectKey for super::Aes256Cbc { #[cfg(not(feature = "aes256-cbc"))] impl UnsafeInjectKey for super::Aes256Cbc {} - #[cfg(not(feature = "aes256-cbc"))] impl Decrypt for super::Aes256Cbc {} - #[cfg(not(feature = "aes256-cbc"))] impl Encrypt for super::Aes256Cbc {} +#[cfg(not(feature = "aes256-cbc"))] +impl WrapKey for super::Aes256Cbc {} diff --git a/src/mechanisms/chacha8poly1305.rs b/src/mechanisms/chacha8poly1305.rs index 7e20dca4121..9fe96030bc1 100644 --- a/src/mechanisms/chacha8poly1305.rs +++ b/src/mechanisms/chacha8poly1305.rs @@ -245,8 +245,12 @@ impl UnwrapKey for super::Chacha8Poly1305 { } #[cfg(not(feature = "chacha8-poly1305"))] -impl Decrypt

for super::Chacha8Poly1305 {} +impl Decrypt for super::Chacha8Poly1305 {} #[cfg(not(feature = "chacha8-poly1305"))] -impl Encrypt

for super::Chacha8Poly1305 {} +impl Encrypt for super::Chacha8Poly1305 {} #[cfg(not(feature = "chacha8-poly1305"))] -impl GenerateKey

for super::Chacha8Poly1305 {} +impl WrapKey for super::Chacha8Poly1305 {} +#[cfg(not(feature = "chacha8-poly1305"))] +impl UnwrapKey for super::Chacha8Poly1305 {} +#[cfg(not(feature = "chacha8-poly1305"))] +impl GenerateKey for super::Chacha8Poly1305 {} diff --git a/src/mechanisms/ed255.rs b/src/mechanisms/ed255.rs index 6d3325d0873..808477969c8 100644 --- a/src/mechanisms/ed255.rs +++ b/src/mechanisms/ed255.rs @@ -265,13 +265,17 @@ impl UnsafeInjectKey for super::Ed255 { } } +#[cfg(not(feature = "ed255"))] +impl Exists for super::Ed255 {} #[cfg(not(feature = "ed255"))] impl DeriveKey for super::Ed255 {} #[cfg(not(feature = "ed255"))] impl GenerateKey for super::Ed255 {} #[cfg(not(feature = "ed255"))] +impl SerializeKey for super::Ed255 {} +#[cfg(not(feature = "ed255"))] +impl DeserializeKey for super::Ed255 {} +#[cfg(not(feature = "ed255"))] impl Sign for super::Ed255 {} #[cfg(not(feature = "ed255"))] impl Verify for super::Ed255 {} -#[cfg(not(feature = "ed255"))] -impl UnsafeInjectKey for super::ed255 {} diff --git a/src/mechanisms/hmacblake2s.rs b/src/mechanisms/hmacblake2s.rs index c90f9acf959..1f3320e1b54 100644 --- a/src/mechanisms/hmacblake2s.rs +++ b/src/mechanisms/hmacblake2s.rs @@ -10,8 +10,9 @@ impl DeriveKey for super::HmacBlake2s { keystore: &mut impl Keystore, request: &request::DeriveKey, ) -> Result { + use blake2::Blake2s256; use hmac::{Mac, SimpleHmac}; - type HmacBlake2s = SimpleHmac; + type HmacBlake2s = SimpleHmac; let key = keystore.load_key(key::Secrecy::Secret, None, &request.base_key)?; if !matches!(key.kind, key::Kind::Symmetric(..) | key::Kind::Shared(..)) { @@ -45,8 +46,9 @@ impl DeriveKey for super::HmacBlake2s { impl Sign for super::HmacBlake2s { #[inline(never)] fn sign(keystore: &mut impl Keystore, request: &request::Sign) -> Result { + use blake2::Blake2s256; use hmac::{Mac, SimpleHmac}; - type HmacBlake2s = SimpleHmac; + type HmacBlake2s = SimpleHmac; let key = keystore.load_key(key::Secrecy::Secret, None, &request.key)?; if !matches!(key.kind, key::Kind::Symmetric(..) | key::Kind::Shared(..)) { diff --git a/src/mechanisms/p256.rs b/src/mechanisms/p256.rs index 24b056698d4..d2b508c8dcd 100644 --- a/src/mechanisms/p256.rs +++ b/src/mechanisms/p256.rs @@ -373,12 +373,18 @@ impl UnsafeInjectKey for super::P256 { #[cfg(not(feature = "p256"))] impl Agree for super::P256 {} #[cfg(not(feature = "p256"))] +impl Exists for super::P256 {} +#[cfg(not(feature = "p256"))] impl DeriveKey for super::P256 {} #[cfg(not(feature = "p256"))] impl GenerateKey for super::P256 {} #[cfg(not(feature = "p256"))] +impl DeserializeKey for super::P256 {} +#[cfg(not(feature = "p256"))] +impl SerializeKey for super::P256 {} +#[cfg(not(feature = "p256"))] impl Sign for super::P256 {} #[cfg(not(feature = "p256"))] -impl Verify for super::P256 {} +impl Sign for super::P256Prehashed {} #[cfg(not(feature = "p256"))] -impl UnsafeInjectKey for super::P256 {} +impl Verify for super::P256 {} diff --git a/src/mechanisms/tdes.rs b/src/mechanisms/tdes.rs index 5734c1ba7af..7710f04252d 100644 --- a/src/mechanisms/tdes.rs +++ b/src/mechanisms/tdes.rs @@ -6,6 +6,7 @@ // use cortex_m_semihosting::{dbg, hprintln}; // needed to even get ::new() from des... +#[cfg(feature = "tdes")] use des::cipher::{BlockDecrypt, BlockEncrypt, KeyInit}; use crate::api::*; @@ -109,3 +110,9 @@ impl UnsafeInjectKey for super::Tdes { Ok(reply::UnsafeInjectKey { key: key_id }) } } + +#[cfg(not(feature = "tdes"))] +impl Encrypt for super::Tdes {} + +#[cfg(not(feature = "tdes"))] +impl Decrypt for super::Tdes {} diff --git a/src/mechanisms/totp.rs b/src/mechanisms/totp.rs index f47569eb3f0..dd356841f4b 100644 --- a/src/mechanisms/totp.rs +++ b/src/mechanisms/totp.rs @@ -9,11 +9,13 @@ const TOTP_KEY_SIZE: usize = 20; // https://tools.ietf.org/html/rfc4226#section-5.3 +#[cfg(feature = "totp")] #[inline(never)] fn hotp_raw(key: &[u8], counter: u64, digits: u32) -> u64 { hmac_and_truncate(key, &counter.to_be_bytes(), digits) } +#[cfg(feature = "totp")] #[inline(never)] fn hmac_and_truncate(key: &[u8], message: &[u8], digits: u32) -> u64 { use hmac::{Hmac, Mac}; @@ -91,7 +93,12 @@ impl Exists for super::Totp { } } -#[cfg(test)] +#[cfg(not(feature = "totp"))] +impl Sign for super::Totp {} +#[cfg(not(feature = "totp"))] +impl Exists for super::Totp {} + +#[cfg(all(test, feature = "totp"))] mod tests { use super::*; diff --git a/src/mechanisms/x255.rs b/src/mechanisms/x255.rs index c646c89f72d..8e747a7b0eb 100644 --- a/src/mechanisms/x255.rs +++ b/src/mechanisms/x255.rs @@ -235,10 +235,8 @@ impl GenerateKey for super::X255 {} #[cfg(not(feature = "x255"))] impl Exists for super::X255 {} #[cfg(not(feature = "x255"))] -impl Derive for super::X255 {} +impl DeriveKey for super::X255 {} #[cfg(not(feature = "x255"))] impl SerializeKey for super::X255 {} #[cfg(not(feature = "x255"))] impl DeserializeKey for super::X255 {} -#[cfg(not(feature = "x255"))] -impl UnsafeInjectKey for super::X255 {} diff --git a/src/tests.rs b/src/tests.rs index 379e748949f..af4b9320ce2 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -202,6 +202,7 @@ fn dummy() { setup!(_client); } +#[cfg(feature = "ed255")] #[test] #[serial] fn sign_ed255() { @@ -255,6 +256,7 @@ fn sign_ed255() { assert_eq!(Err(Error::WrongSignatureLength), reply); } +#[cfg(feature = "p255")] #[test] #[serial] fn sign_p256() { @@ -294,6 +296,7 @@ fn sign_p256() { assert!(valid); } +#[cfg(feature = "p255")] #[test] #[serial] fn agree_p256() { @@ -376,6 +379,7 @@ fn agree_p256() { .signature; } +#[cfg(feature = "chacha8-poly1305")] #[test] #[serial] fn aead_rng_nonce() { @@ -412,6 +416,7 @@ fn aead_rng_nonce() { assert_eq!(&message[..], plaintext.unwrap().as_ref()); } +#[cfg(feature = "chacha8-poly1305")] #[test] #[serial] fn aead_given_nonce() { @@ -450,6 +455,7 @@ fn aead_given_nonce() { } // Same as before but key generated with a nonce +#[cfg(feature = "chacha8-poly1305")] #[test] #[serial] fn aead_given_nonce_2() { @@ -487,6 +493,7 @@ fn aead_given_nonce_2() { assert_eq!(&message[..], plaintext.unwrap().as_ref()); } +#[cfg(feature = "chacha8-poly1305")] #[test] #[serial] fn aead() { diff --git a/src/types.rs b/src/types.rs index 3ce3a278cbe..b27252301c5 100644 --- a/src/types.rs +++ b/src/types.rs @@ -170,6 +170,7 @@ pub mod ui { // TODO: Consider whether a simple "language" to specify "patterns" // makes sense, vs. "semantic" indications with platform-specific implementation #[derive(Copy, Clone, Eq, PartialEq, Debug, Serialize, Deserialize)] + #[non_exhaustive] pub enum Status { Idle, WaitingForUserPresence, @@ -243,6 +244,7 @@ pub mod consent { /// The context stores the state used by the standard syscall implementations, see /// [`CoreContext`][]. Additionally, backends can define a custom context for their syscall /// implementations. +#[non_exhaustive] pub struct Context { pub core: CoreContext, pub backends: B, @@ -261,6 +263,7 @@ impl From for Context { // currently has. Trussed currently uses it to choose the client-specific // subtree in the filesystem (see docs in src/store.rs) and to maintain // the walker state of the directory traversal syscalls. +#[non_exhaustive] pub struct CoreContext { pub path: PathBuf, pub read_dir_state: Option, @@ -546,6 +549,7 @@ impl Default for StorageAttributes { } #[derive(Copy, Clone, Eq, PartialEq, Debug, Serialize, Deserialize)] +#[non_exhaustive] pub enum Mechanism { Aes256Cbc, Chacha8Poly1305,