From f14ac90c07d0d5ac5b4946463a451eedccdd03c4 Mon Sep 17 00:00:00 2001 From: Robin Krahl Date: Mon, 3 Mar 2025 16:53:09 +0100 Subject: [PATCH 1/4] Unify mechanism traits This patch combines the operation traits that were previously used to call mechanism implementations into a single MechanismImpl trait. This has several advantages: - We can use a macro to implement the dispatch from the Mechanism enum, removing boilerplate code from the reply_to implementation. - To implement an operation for a mechanism, it is now sufficient to override the respective trait method. It is no longer necessary to also update reply_to. - The need to annotate all mechanism methods with #[inline(never)] to avoid producing a huge reply_to function (see the comment in mechanisms.rs) is reduced as we can just mark the methods generated by the macro as #[inline(never)]. - This reduces the binary size required in the stable nitrokey-3-firmware by some kB. --- CHANGELOG.md | 1 + Cargo.toml | 1 + src/mechanisms.rs | 55 ++-- src/mechanisms/aes256cbc.rs | 16 +- src/mechanisms/chacha8poly1305.rs | 65 ++--- src/mechanisms/ed255.rs | 33 +-- src/mechanisms/hmacblake2s.rs | 13 +- src/mechanisms/hmacsha1.rs | 13 +- src/mechanisms/hmacsha256.rs | 13 +- src/mechanisms/hmacsha512.rs | 13 +- src/mechanisms/p256.rs | 101 ++++--- src/mechanisms/p384.rs | 105 +++---- src/mechanisms/p521.rs | 104 +++---- src/mechanisms/sha256.rs | 13 +- src/mechanisms/shared_secret.rs | 8 +- src/mechanisms/tdes.rs | 11 +- src/mechanisms/totp.rs | 13 +- src/mechanisms/trng.rs | 5 +- src/mechanisms/x255.rs | 25 +- src/service.rs | 447 ++++++++++-------------------- src/service/attest.rs | 130 ++++----- src/types.rs | 2 + 22 files changed, 507 insertions(+), 680 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8da3c2f13fe..b29383bf46e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -64,6 +64,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Removed the `Copy` requirement. - Removed the `unsafe` keyword for the `Store` trait. - Removed the `unsafe` keyword for the `Platform` trait. +- Replaced the mechanism RPC traits in `service` with a single `MechanismImpl` trait. ### Fixed diff --git a/Cargo.toml b/Cargo.toml index 57dc5f996cd..e7a73ff93ca 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -44,6 +44,7 @@ rand_core.workspace = true serde.workspace = true zeroize = { version = "1.2", default-features = false, features = ["zeroize_derive"] } rand_chacha = { version = "0.3.1", default-features = false } +paste = "1" # RustCrypto aes = { version = "0.8", default-features = false } diff --git a/src/mechanisms.rs b/src/mechanisms.rs index fd7e6f5e2b6..4ca2baae4f2 100644 --- a/src/mechanisms.rs +++ b/src/mechanisms.rs @@ -12,104 +12,87 @@ // TODO: rename to aes256-cbc-zero-iv #[cfg(feature = "aes256-cbc")] -pub struct Aes256Cbc {} +pub struct Aes256Cbc; #[cfg(feature = "aes256-cbc")] mod aes256cbc; #[cfg(feature = "chacha8-poly1305")] -pub struct Chacha8Poly1305 {} +pub struct Chacha8Poly1305; #[cfg(feature = "chacha8-poly1305")] mod chacha8poly1305; #[cfg(feature = "shared-secret")] -pub struct SharedSecret {} +pub struct SharedSecret; #[cfg(feature = "shared-secret")] mod shared_secret; #[cfg(feature = "ed255")] -pub struct Ed255 {} +pub struct Ed255; #[cfg(feature = "ed255")] mod ed255; #[cfg(feature = "hmac-blake2s")] -pub struct HmacBlake2s {} +pub struct HmacBlake2s; #[cfg(feature = "hmac-blake2s")] mod hmacblake2s; #[cfg(feature = "hmac-sha1")] -pub struct HmacSha1 {} +pub struct HmacSha1; #[cfg(feature = "hmac-sha1")] mod hmacsha1; #[cfg(feature = "hmac-sha256")] -pub struct HmacSha256 {} +pub struct HmacSha256; #[cfg(feature = "hmac-sha256")] mod hmacsha256; #[cfg(feature = "hmac-sha512")] -pub struct HmacSha512 {} +pub struct HmacSha512; #[cfg(feature = "hmac-sha512")] mod hmacsha512; #[cfg(feature = "p256")] -pub struct P256 {} +pub struct P256; #[cfg(feature = "p256")] -pub struct P256Prehashed {} +pub struct P256Prehashed; #[cfg(feature = "p256")] mod p256; #[cfg(feature = "p384")] -pub struct P384 {} +pub struct P384; #[cfg(feature = "p384")] -pub struct P384Prehashed {} +pub struct P384Prehashed; #[cfg(feature = "p384")] mod p384; #[cfg(feature = "p521")] -pub struct P521 {} +pub struct P521; #[cfg(feature = "p521")] -pub struct P521Prehashed {} +pub struct P521Prehashed; #[cfg(feature = "p521")] mod p521; #[cfg(feature = "sha256")] -pub struct Sha256 {} +pub struct Sha256; #[cfg(feature = "sha256")] mod sha256; #[cfg(feature = "tdes")] -pub struct Tdes {} +pub struct Tdes; #[cfg(feature = "tdes")] mod tdes; #[cfg(feature = "totp")] -pub struct Totp {} +pub struct Totp; #[cfg(feature = "totp")] mod totp; #[cfg(feature = "trng")] -pub struct Trng {} +pub struct Trng; #[cfg(feature = "trng")] mod trng; #[cfg(feature = "x255")] -pub struct X255 {} +pub struct X255; #[cfg(feature = "x255")] mod x255; - -// pub enum MechanismEnum { -// NotImplemented, -// Ed255(ed255::Ed255), -// P256(p256::P256), -// } - -// use crate::types::Mechanism; -// pub fn enum_to_type(mechanism: Mechanism) -> MechanismEnum { -// match mechanism { -// #[cfg(feature = "ed255")] -// Mechanism::Ed255 => MechanismEnum::Ed255(ed255::Ed255 {} ), -// #[cfg(feature = "p256")] -// Mechanism::P256 => MechanismEnum::P256(p256::P256 {} ), -// _ => MechanismEnum::NotImplemented, -// } -// } diff --git a/src/mechanisms/aes256cbc.rs b/src/mechanisms/aes256cbc.rs index 01f83ea3d78..81993a0d9c4 100644 --- a/src/mechanisms/aes256cbc.rs +++ b/src/mechanisms/aes256cbc.rs @@ -1,15 +1,16 @@ use crate::api::{reply, request}; use crate::error::Error; use crate::key; -use crate::service::{Decrypt, Encrypt, UnsafeInjectKey, WrapKey}; +use crate::service::MechanismImpl; use crate::store::keystore::Keystore; use crate::types::{Mechanism, Message, ShortData}; const AES256_KEY_SIZE: usize = 32; -impl Encrypt for super::Aes256Cbc { +impl MechanismImpl for super::Aes256Cbc { /// Encrypts the input *with zero IV* fn encrypt( + &self, keystore: &mut impl Keystore, request: &request::Encrypt, ) -> Result { @@ -63,10 +64,9 @@ impl Encrypt for super::Aes256Cbc { tag: ShortData::new(), }) } -} -impl WrapKey for super::Aes256Cbc { fn wrap_key( + &self, keystore: &mut impl Keystore, request: &request::WrapKey, ) -> Result { @@ -91,16 +91,15 @@ impl WrapKey for super::Aes256Cbc { associated_data: request.associated_data.clone(), nonce: request.nonce.clone(), }; - let encryption_reply = ::encrypt(keystore, &encryption_request)?; + let encryption_reply = self.encrypt(keystore, &encryption_request)?; let wrapped_key = encryption_reply.ciphertext; Ok(reply::WrapKey { wrapped_key }) } -} -impl Decrypt for super::Aes256Cbc { fn decrypt( + &self, keystore: &mut impl Keystore, request: &request::Decrypt, ) -> Result { @@ -155,10 +154,9 @@ impl Decrypt for super::Aes256Cbc { plaintext: Some(plaintext), }) } -} -impl UnsafeInjectKey for super::Aes256Cbc { fn unsafe_inject_key( + &self, keystore: &mut impl Keystore, request: &request::UnsafeInjectKey, ) -> Result { diff --git a/src/mechanisms/chacha8poly1305.rs b/src/mechanisms/chacha8poly1305.rs index 2b072887216..422a3dd4c71 100644 --- a/src/mechanisms/chacha8poly1305.rs +++ b/src/mechanisms/chacha8poly1305.rs @@ -5,7 +5,7 @@ use trussed_core::types::EncryptedData; use crate::api::{reply, request}; use crate::error::Error; use crate::key; -use crate::service::{Decrypt, Encrypt, GenerateKey, UnwrapKey, WrapKey}; +use crate::service::MechanismImpl; use crate::store::keystore::Keystore; use crate::types::{Mechanism, Message, ShortData}; @@ -20,9 +20,26 @@ const TAG_LEN: usize = 16; const KIND: key::Kind = key::Kind::Symmetric(KEY_LEN); const KIND_NONCE: key::Kind = key::Kind::Symmetric32Nonce(NONCE_LEN); -impl GenerateKey for super::Chacha8Poly1305 { +#[inline(never)] +fn increment_nonce(nonce: &mut [u8]) -> Result<(), Error> { + assert_eq!(nonce.len(), NONCE_LEN); + let mut carry: u16 = 1; + for digit in nonce.iter_mut() { + let x = (*digit as u16) + carry; + *digit = x as u8; + carry = x >> 8; + } + if carry == 0 { + Ok(()) + } else { + Err(Error::NonceOverflow) + } +} + +impl MechanismImpl for super::Chacha8Poly1305 { #[inline(never)] fn generate_key( + &self, keystore: &mut impl Keystore, request: &request::GenerateKey, ) -> Result { @@ -45,27 +62,10 @@ impl GenerateKey for super::Chacha8Poly1305 { Ok(reply::GenerateKey { key: key_id }) } -} -#[inline(never)] -fn increment_nonce(nonce: &mut [u8]) -> Result<(), Error> { - assert_eq!(nonce.len(), NONCE_LEN); - let mut carry: u16 = 1; - for digit in nonce.iter_mut() { - let x = (*digit as u16) + carry; - *digit = x as u8; - carry = x >> 8; - } - if carry == 0 { - Ok(()) - } else { - Err(Error::NonceOverflow) - } -} - -impl Decrypt for super::Chacha8Poly1305 { #[inline(never)] fn decrypt( + &self, keystore: &mut impl Keystore, request: &request::Decrypt, ) -> Result { @@ -103,12 +103,10 @@ impl Decrypt for super::Chacha8Poly1305 { }, }) } -} -#[cfg(feature = "chacha8-poly1305")] -impl Encrypt for super::Chacha8Poly1305 { #[inline(never)] fn encrypt( + &self, keystore: &mut impl Keystore, request: &request::Encrypt, ) -> Result { @@ -164,11 +162,10 @@ impl Encrypt for super::Chacha8Poly1305 { tag, }) } -} -impl WrapKey for super::Chacha8Poly1305 { #[inline(never)] fn wrap_key( + &self, keystore: &mut impl Keystore, request: &request::WrapKey, ) -> Result { @@ -186,7 +183,7 @@ impl WrapKey for super::Chacha8Poly1305 { associated_data: request.associated_data.clone(), nonce: request.nonce.clone(), }; - let encryption_reply = ::encrypt(keystore, &encryption_request)?; + let encryption_reply = self.encrypt(keystore, &encryption_request)?; let wrapped_key = EncryptedData::from(encryption_reply); let wrapped_key = @@ -194,11 +191,10 @@ impl WrapKey for super::Chacha8Poly1305 { Ok(reply::WrapKey { wrapped_key }) } -} -impl UnwrapKey for super::Chacha8Poly1305 { #[inline(never)] fn unwrap_key( + &self, keystore: &mut impl Keystore, request: &request::UnwrapKey, ) -> Result { @@ -211,13 +207,12 @@ impl UnwrapKey for super::Chacha8Poly1305 { request.associated_data.clone(), ); - let serialized_key = if let Some(serialized_key) = - ::decrypt(keystore, &decryption_request)?.plaintext - { - serialized_key - } else { - return Ok(reply::UnwrapKey { key: None }); - }; + let serialized_key = + if let Some(serialized_key) = self.decrypt(keystore, &decryption_request)?.plaintext { + serialized_key + } else { + return Ok(reply::UnwrapKey { key: None }); + }; // TODO: probably change this to returning Option too let key::Key { diff --git a/src/mechanisms/ed255.rs b/src/mechanisms/ed255.rs index d3f9cd8a88e..13136ced79b 100644 --- a/src/mechanisms/ed255.rs +++ b/src/mechanisms/ed255.rs @@ -3,9 +3,7 @@ use rand_core::RngCore; use crate::api::{reply, request}; use crate::error::Error; use crate::key; -use crate::service::{ - DeriveKey, DeserializeKey, Exists, GenerateKey, SerializeKey, Sign, UnsafeInjectKey, Verify, -}; +use crate::service::MechanismImpl; use crate::store::keystore::Keystore; use crate::types::{ Bytes, KeyId, KeySerialization, SerializedKey, Signature, SignatureSerialization, @@ -43,9 +41,10 @@ fn load_keypair(keystore: &mut impl Keystore, key_id: &KeyId) -> Result Result { @@ -61,11 +60,10 @@ impl DeriveKey for super::Ed255 { Ok(reply::DeriveKey { key: public_id }) } -} -impl DeserializeKey for super::Ed255 { #[inline(never)] fn deserialize_key( + &self, keystore: &mut impl Keystore, request: &request::DeserializeKey, ) -> Result { @@ -94,11 +92,10 @@ impl DeserializeKey for super::Ed255 { Ok(reply::DeserializeKey { key: public_id }) } -} -impl GenerateKey for super::Ed255 { #[inline(never)] fn generate_key( + &self, keystore: &mut impl Keystore, request: &request::GenerateKey, ) -> Result { @@ -120,11 +117,10 @@ impl GenerateKey for super::Ed255 { // return handle Ok(reply::GenerateKey { key: key_id }) } -} -impl SerializeKey for super::Ed255 { #[inline(never)] fn serialize_key( + &self, keystore: &mut impl Keystore, request: &request::SerializeKey, ) -> Result { @@ -157,11 +153,10 @@ impl SerializeKey for super::Ed255 { Ok(reply::SerializeKey { serialized_key }) } -} -impl Exists for super::Ed255 { #[inline(never)] fn exists( + &self, keystore: &mut impl Keystore, request: &request::Exists, ) -> Result { @@ -170,11 +165,13 @@ impl Exists for super::Ed255 { let exists = keystore.exists_key(key::Secrecy::Secret, Some(key::Kind::Ed255), &key_id); Ok(reply::Exists { exists }) } -} -impl Sign for super::Ed255 { #[inline(never)] - fn sign(keystore: &mut impl Keystore, request: &request::Sign) -> Result { + fn sign( + &self, + keystore: &mut impl Keystore, + request: &request::Sign, + ) -> Result { // Not so nice, expands to // `trussed::/home/nicolas/projects/solo-bee/components/trussed/src/mechanisms/ed255.rs:151 // Ed255::Sign`, i.e. VEERY long @@ -202,11 +199,10 @@ impl Sign for super::Ed255 { signature: our_signature, }) } -} -impl Verify for super::Ed255 { #[inline(never)] fn verify( + &self, keystore: &mut impl Keystore, request: &request::Verify, ) -> Result { @@ -232,10 +228,9 @@ impl Verify for super::Ed255 { .is_ok(), }) } -} -impl UnsafeInjectKey for super::Ed255 { fn unsafe_inject_key( + &self, keystore: &mut impl Keystore, request: &request::UnsafeInjectKey, ) -> Result { diff --git a/src/mechanisms/hmacblake2s.rs b/src/mechanisms/hmacblake2s.rs index b1f8a3c98da..930568fe5dd 100644 --- a/src/mechanisms/hmacblake2s.rs +++ b/src/mechanisms/hmacblake2s.rs @@ -1,13 +1,14 @@ use crate::api::{reply, request}; use crate::error::Error; use crate::key; -use crate::service::{DeriveKey, Sign}; +use crate::service::MechanismImpl; use crate::store::keystore::Keystore; use crate::types::Signature; -impl DeriveKey for super::HmacBlake2s { +impl MechanismImpl for super::HmacBlake2s { #[inline(never)] fn derive_key( + &self, keystore: &mut impl Keystore, request: &request::DeriveKey, ) -> Result { @@ -37,11 +38,13 @@ impl DeriveKey for super::HmacBlake2s { Ok(reply::DeriveKey { key }) } -} -impl Sign for super::HmacBlake2s { #[inline(never)] - fn sign(keystore: &mut impl Keystore, request: &request::Sign) -> Result { + fn sign( + &self, + keystore: &mut impl Keystore, + request: &request::Sign, + ) -> Result { use blake2::Blake2s256; use hmac::{Mac, SimpleHmac}; type HmacBlake2s = SimpleHmac; diff --git a/src/mechanisms/hmacsha1.rs b/src/mechanisms/hmacsha1.rs index b73d7e158c6..4d5259329db 100644 --- a/src/mechanisms/hmacsha1.rs +++ b/src/mechanisms/hmacsha1.rs @@ -1,13 +1,14 @@ use crate::api::{reply, request}; use crate::error::Error; use crate::key; -use crate::service::{DeriveKey, Sign}; +use crate::service::MechanismImpl; use crate::store::keystore::Keystore; use crate::types::Signature; -impl DeriveKey for super::HmacSha1 { +impl MechanismImpl for super::HmacSha1 { #[inline(never)] fn derive_key( + &self, keystore: &mut impl Keystore, request: &request::DeriveKey, ) -> Result { @@ -37,11 +38,13 @@ impl DeriveKey for super::HmacSha1 { Ok(reply::DeriveKey { key: key_id }) } -} -impl Sign for super::HmacSha1 { #[inline(never)] - fn sign(keystore: &mut impl Keystore, request: &request::Sign) -> Result { + fn sign( + &self, + keystore: &mut impl Keystore, + request: &request::Sign, + ) -> Result { use hmac::{Hmac, Mac}; use sha1::Sha1; type HmacSha1 = Hmac; diff --git a/src/mechanisms/hmacsha256.rs b/src/mechanisms/hmacsha256.rs index 8e120956bb4..034aca3a89a 100644 --- a/src/mechanisms/hmacsha256.rs +++ b/src/mechanisms/hmacsha256.rs @@ -1,13 +1,14 @@ use crate::api::{reply, request}; use crate::error::Error; use crate::key; -use crate::service::{DeriveKey, Sign}; +use crate::service::MechanismImpl; use crate::store::keystore::Keystore; use crate::types::Signature; -impl DeriveKey for super::HmacSha256 { +impl MechanismImpl for super::HmacSha256 { #[inline(never)] fn derive_key( + &self, keystore: &mut impl Keystore, request: &request::DeriveKey, ) -> Result { @@ -42,11 +43,13 @@ impl DeriveKey for super::HmacSha256 { Ok(reply::DeriveKey { key: key_id }) } -} -impl Sign for super::HmacSha256 { #[inline(never)] - fn sign(keystore: &mut impl Keystore, request: &request::Sign) -> Result { + fn sign( + &self, + keystore: &mut impl Keystore, + request: &request::Sign, + ) -> Result { use hmac::{Hmac, Mac}; use sha2::Sha256; type HmacSha256 = Hmac; diff --git a/src/mechanisms/hmacsha512.rs b/src/mechanisms/hmacsha512.rs index be037eea3c7..95a247e5f61 100644 --- a/src/mechanisms/hmacsha512.rs +++ b/src/mechanisms/hmacsha512.rs @@ -1,13 +1,14 @@ use crate::api::{reply, request}; use crate::error::Error; use crate::key; -use crate::service::{DeriveKey, Sign}; +use crate::service::MechanismImpl; use crate::store::keystore::Keystore; use crate::types::Signature; -impl DeriveKey for super::HmacSha512 { +impl MechanismImpl for super::HmacSha512 { #[inline(never)] fn derive_key( + &self, keystore: &mut impl Keystore, request: &request::DeriveKey, ) -> Result { @@ -37,11 +38,13 @@ impl DeriveKey for super::HmacSha512 { Ok(reply::DeriveKey { key }) } -} -impl Sign for super::HmacSha512 { #[inline(never)] - fn sign(keystore: &mut impl Keystore, request: &request::Sign) -> Result { + fn sign( + &self, + keystore: &mut impl Keystore, + request: &request::Sign, + ) -> Result { use hmac::{Hmac, Mac}; use sha2::Sha512; type HmacSha512 = Hmac; diff --git a/src/mechanisms/p256.rs b/src/mechanisms/p256.rs index b2ea0813fb7..e0e6a2d0c91 100644 --- a/src/mechanisms/p256.rs +++ b/src/mechanisms/p256.rs @@ -1,10 +1,7 @@ use crate::api::{reply, request}; use crate::error::Error; use crate::key; -use crate::service::{ - Agree, DeriveKey, DeserializeKey, Exists, GenerateKey, SerializeKey, Sign, UnsafeInjectKey, - Verify, -}; +use crate::service::MechanismImpl; use crate::store::keystore::Keystore; use crate::types::{ Bytes, KeyId, KeySerialization, SerializedKey, Signature, SignatureSerialization, @@ -44,9 +41,10 @@ fn load_public_key( .map_err(|_| Error::InternalError) } -impl Agree for super::P256 { +impl MechanismImpl for super::P256 { #[inline(never)] fn agree( + &self, keystore: &mut impl Keystore, request: &request::Agree, ) -> Result { @@ -80,11 +78,10 @@ impl Agree for super::P256 { shared_secret: key_id, }) } -} -impl DeriveKey for super::P256 { #[inline(never)] fn derive_key( + &self, keystore: &mut impl Keystore, request: &request::DeriveKey, ) -> Result { @@ -102,11 +99,10 @@ impl DeriveKey for super::P256 { Ok(reply::DeriveKey { key: public_id }) } -} -impl DeserializeKey for super::P256 { #[inline(never)] fn deserialize_key( + &self, keystore: &mut impl Keystore, request: &request::DeserializeKey, ) -> Result { @@ -175,11 +171,10 @@ impl DeserializeKey for super::P256 { Ok(reply::DeserializeKey { key: public_id }) } -} -impl GenerateKey for super::P256 { #[inline(never)] fn generate_key( + &self, keystore: &mut impl Keystore, request: &request::GenerateKey, ) -> Result { @@ -196,11 +191,10 @@ impl GenerateKey for super::P256 { // return handle Ok(reply::GenerateKey { key: key_id }) } -} -impl SerializeKey for super::P256 { #[inline(never)] fn serialize_key( + &self, keystore: &mut impl Keystore, request: &request::SerializeKey, ) -> Result { @@ -245,11 +239,10 @@ impl SerializeKey for super::P256 { Ok(reply::SerializeKey { serialized_key }) } -} -impl Exists for super::P256 { #[inline(never)] fn exists( + &self, keystore: &mut impl Keystore, request: &request::Exists, ) -> Result { @@ -257,11 +250,13 @@ impl Exists for super::P256 { let exists = keystore.exists_key(key::Secrecy::Secret, Some(key::Kind::P256), &key_id); Ok(reply::Exists { exists }) } -} -impl Sign for super::P256 { #[inline(never)] - fn sign(keystore: &mut impl Keystore, request: &request::Sign) -> Result { + fn sign( + &self, + keystore: &mut impl Keystore, + request: &request::Sign, + ) -> Result { let key_id = request.key; let secret_key = load_secret_key(keystore, &key_id)?; @@ -287,41 +282,10 @@ impl Sign for super::P256 { signature: serialized_signature, }) } -} -impl Sign for super::P256Prehashed { - #[inline(never)] - fn sign(keystore: &mut impl Keystore, request: &request::Sign) -> Result { - let key_id = request.key; - - let secret_key = load_secret_key(keystore, &key_id)?; - let signature = secret_key.sign_prehashed(&request.message, keystore.rng()); - - // debug_now!("making signature"); - let serialized_signature = match request.format { - SignatureSerialization::Asn1Der => { - let mut buffer = [0u8; 72]; - let l = signature.to_sec1_bytes(&mut buffer); - Signature::from_slice(&buffer[..l]).unwrap() - } - SignatureSerialization::Raw => { - Signature::from_slice(&signature.to_untagged_bytes()).unwrap() - } - _ => { - return Err(Error::InvalidSerializationFormat); - } - }; - - // return signature - Ok(reply::Sign { - signature: serialized_signature, - }) - } -} - -impl Verify for super::P256 { #[inline(never)] fn verify( + &self, keystore: &mut impl Keystore, request: &request::Verify, ) -> Result { @@ -342,10 +306,9 @@ impl Verify for super::P256 { let valid = public_key.verify(&request.message, &signature); Ok(reply::Verify { valid }) } -} -impl UnsafeInjectKey for super::P256 { fn unsafe_inject_key( + &self, keystore: &mut impl Keystore, request: &request::UnsafeInjectKey, ) -> Result { @@ -371,3 +334,37 @@ impl UnsafeInjectKey for super::P256 { .map(|key| reply::UnsafeInjectKey { key }) } } + +impl MechanismImpl for super::P256Prehashed { + #[inline(never)] + fn sign( + &self, + keystore: &mut impl Keystore, + request: &request::Sign, + ) -> Result { + let key_id = request.key; + + let secret_key = load_secret_key(keystore, &key_id)?; + let signature = secret_key.sign_prehashed(&request.message, keystore.rng()); + + // debug_now!("making signature"); + let serialized_signature = match request.format { + SignatureSerialization::Asn1Der => { + let mut buffer = [0u8; 72]; + let l = signature.to_sec1_bytes(&mut buffer); + Signature::from_slice(&buffer[..l]).unwrap() + } + SignatureSerialization::Raw => { + Signature::from_slice(&signature.to_untagged_bytes()).unwrap() + } + _ => { + return Err(Error::InvalidSerializationFormat); + } + }; + + // return signature + Ok(reply::Sign { + signature: serialized_signature, + }) + } +} diff --git a/src/mechanisms/p384.rs b/src/mechanisms/p384.rs index 775cb3cf35e..91eaf6b488e 100644 --- a/src/mechanisms/p384.rs +++ b/src/mechanisms/p384.rs @@ -12,10 +12,7 @@ use super::{P384Prehashed, P384}; use crate::{ api::{reply, request}, key, - service::{ - Agree, DeriveKey, DeserializeKey, Exists, GenerateKey, SerializeKey, Sign, UnsafeInjectKey, - Verify, - }, + service::MechanismImpl, store::keystore::Keystore, types::{KeyId, KeySerialization, SerializedKey, Signature, SignatureSerialization}, Error, @@ -52,8 +49,9 @@ fn to_sec1_bytes(public_key: &p384::PublicKey) -> heapless::Vec Result { @@ -85,10 +83,10 @@ impl Agree for P384 { shared_secret: key_id, }) } -} -impl DeriveKey for P384 { + #[inline(never)] fn derive_key( + &self, keystore: &mut impl Keystore, request: &request::DeriveKey, ) -> Result { @@ -106,10 +104,10 @@ impl DeriveKey for P384 { Ok(reply::DeriveKey { key: public_id }) } -} -impl DeserializeKey for P384 { + #[inline(never)] fn deserialize_key( + &self, keystore: &mut impl Keystore, request: &request::DeserializeKey, ) -> Result { @@ -144,10 +142,10 @@ impl DeserializeKey for P384 { Ok(reply::DeserializeKey { key: public_id }) } -} -impl SerializeKey for P384 { + #[inline(never)] fn serialize_key( + &self, keystore: &mut impl Keystore, request: &request::SerializeKey, ) -> Result { @@ -179,10 +177,10 @@ impl SerializeKey for P384 { Ok(reply::SerializeKey { serialized_key }) } -} -impl Exists for P384 { + #[inline(never)] fn exists( + &self, keystore: &mut impl Keystore, request: &request::Exists, ) -> Result { @@ -190,11 +188,13 @@ impl Exists for P384 { let exists = keystore.exists_key(key::Secrecy::Secret, Some(key::Kind::P384), &key_id); Ok(reply::Exists { exists }) } -} -impl Sign for P384 { #[inline(never)] - fn sign(keystore: &mut impl Keystore, request: &request::Sign) -> Result { + fn sign( + &self, + keystore: &mut impl Keystore, + request: &request::Sign, + ) -> Result { let key_id = request.key; let secret_key = load_secret_key(keystore, &key_id)?; @@ -219,39 +219,9 @@ impl Sign for P384 { signature: serialized_signature, }) } -} -impl Sign for P384Prehashed { - #[inline(never)] - fn sign(keystore: &mut impl Keystore, request: &request::Sign) -> Result { - let key_id = request.key; - - let secret_key = load_secret_key(keystore, &key_id)?; - let signing_key = SigningKey::from(secret_key); - let signature: p384::ecdsa::Signature = signing_key - .sign_prehash_with_rng(keystore.rng(), &request.message) - .map_err(|_| Error::InvalidSerializedRequest)?; - - // debug_now!("making signature"); - let serialized_signature = match request.format { - SignatureSerialization::Asn1Der => { - let der = signature.to_der(); - Signature::from_slice(der.as_bytes()).unwrap() - } - SignatureSerialization::Raw => Signature::from_slice(&signature.to_bytes()).unwrap(), - _ => { - return Err(Error::InvalidSerializationFormat); - } - }; - // return signature - Ok(reply::Sign { - signature: serialized_signature, - }) - } -} - -impl UnsafeInjectKey for P384 { fn unsafe_inject_key( + &self, keystore: &mut impl Keystore, request: &request::UnsafeInjectKey, ) -> Result { @@ -276,11 +246,10 @@ impl UnsafeInjectKey for P384 { ) .map(|key| reply::UnsafeInjectKey { key }) } -} -impl Verify for P384 { #[inline(never)] fn verify( + &self, keystore: &mut impl Keystore, request: &request::Verify, ) -> Result { @@ -303,9 +272,9 @@ impl Verify for P384 { let valid = verifying_key.verify(&request.message, &signature).is_ok(); Ok(reply::Verify { valid }) } -} -impl GenerateKey for P384 { + fn generate_key( + &self, keystore: &mut impl Keystore, request: &request::GenerateKey, ) -> Result { @@ -322,3 +291,37 @@ impl GenerateKey for P384 { Ok(reply::GenerateKey { key: key_id }) } } + +impl MechanismImpl for P384Prehashed { + #[inline(never)] + fn sign( + &self, + keystore: &mut impl Keystore, + request: &request::Sign, + ) -> Result { + let key_id = request.key; + + let secret_key = load_secret_key(keystore, &key_id)?; + let signing_key = SigningKey::from(secret_key); + let signature: p384::ecdsa::Signature = signing_key + .sign_prehash_with_rng(keystore.rng(), &request.message) + .map_err(|_| Error::InvalidSerializedRequest)?; + + // debug_now!("making signature"); + let serialized_signature = match request.format { + SignatureSerialization::Asn1Der => { + let der = signature.to_der(); + Signature::from_slice(der.as_bytes()).unwrap() + } + SignatureSerialization::Raw => Signature::from_slice(&signature.to_bytes()).unwrap(), + _ => { + return Err(Error::InvalidSerializationFormat); + } + }; + + // return signature + Ok(reply::Sign { + signature: serialized_signature, + }) + } +} diff --git a/src/mechanisms/p521.rs b/src/mechanisms/p521.rs index 9f45fd84bae..227eab2947b 100644 --- a/src/mechanisms/p521.rs +++ b/src/mechanisms/p521.rs @@ -12,10 +12,7 @@ use super::{P521Prehashed, P521}; use crate::{ api::{reply, request}, key, - service::{ - Agree, DeriveKey, DeserializeKey, Exists, GenerateKey, SerializeKey, Sign, UnsafeInjectKey, - Verify, - }, + service::MechanismImpl, store::keystore::Keystore, types::{KeyId, KeySerialization, SerializedKey, Signature, SignatureSerialization}, Error, @@ -52,8 +49,9 @@ fn to_sec1_bytes(public_key: &p521::PublicKey) -> heapless::Vec Result { @@ -87,10 +85,10 @@ impl Agree for P521 { shared_secret: key_id, }) } -} -impl DeriveKey for P521 { + #[inline(never)] fn derive_key( + &self, keystore: &mut impl Keystore, request: &request::DeriveKey, ) -> Result { @@ -108,10 +106,10 @@ impl DeriveKey for P521 { Ok(reply::DeriveKey { key: public_id }) } -} -impl DeserializeKey for P521 { + #[inline(never)] fn deserialize_key( + &self, keystore: &mut impl Keystore, request: &request::DeserializeKey, ) -> Result { @@ -146,10 +144,10 @@ impl DeserializeKey for P521 { Ok(reply::DeserializeKey { key: public_id }) } -} -impl SerializeKey for P521 { + #[inline(never)] fn serialize_key( + &self, keystore: &mut impl Keystore, request: &request::SerializeKey, ) -> Result { @@ -181,10 +179,10 @@ impl SerializeKey for P521 { Ok(reply::SerializeKey { serialized_key }) } -} -impl Exists for P521 { + #[inline(never)] fn exists( + &self, keystore: &mut impl Keystore, request: &request::Exists, ) -> Result { @@ -192,11 +190,13 @@ impl Exists for P521 { let exists = keystore.exists_key(key::Secrecy::Secret, Some(key::Kind::P521), &key_id); Ok(reply::Exists { exists }) } -} -impl Sign for P521 { #[inline(never)] - fn sign(keystore: &mut impl Keystore, request: &request::Sign) -> Result { + fn sign( + &self, + keystore: &mut impl Keystore, + request: &request::Sign, + ) -> Result { let key_id = request.key; let secret_key = load_secret_key(keystore, &key_id)?; @@ -222,39 +222,9 @@ impl Sign for P521 { signature: serialized_signature, }) } -} -impl Sign for P521Prehashed { - #[inline(never)] - fn sign(keystore: &mut impl Keystore, request: &request::Sign) -> Result { - let key_id = request.key; - - let secret_key = load_secret_key(keystore, &key_id)?; - let signing_key = SigningKey::from(ecdsa::SigningKey::from(secret_key)); - let signature: p521::ecdsa::Signature = signing_key - .sign_prehash_with_rng(keystore.rng(), &request.message) - .map_err(|_| Error::InvalidSerializedRequest)?; - - // debug_now!("making signature"); - let serialized_signature = match request.format { - SignatureSerialization::Asn1Der => { - let der = signature.to_der(); - Signature::from_slice(der.as_bytes()).unwrap() - } - SignatureSerialization::Raw => Signature::from_slice(&signature.to_bytes()).unwrap(), - _ => { - return Err(Error::InvalidSerializationFormat); - } - }; - - // return signature - Ok(reply::Sign { - signature: serialized_signature, - }) - } -} -impl UnsafeInjectKey for P521 { fn unsafe_inject_key( + &self, keystore: &mut impl Keystore, request: &request::UnsafeInjectKey, ) -> Result { @@ -279,11 +249,10 @@ impl UnsafeInjectKey for P521 { ) .map(|key| reply::UnsafeInjectKey { key }) } -} -impl Verify for P521 { #[inline(never)] fn verify( + &self, keystore: &mut impl Keystore, request: &request::Verify, ) -> Result { @@ -306,10 +275,9 @@ impl Verify for P521 { let valid = verifying_key.verify(&request.message, &signature).is_ok(); Ok(reply::Verify { valid }) } -} -impl GenerateKey for P521 { fn generate_key( + &self, keystore: &mut impl Keystore, request: &request::GenerateKey, ) -> Result { @@ -326,3 +294,37 @@ impl GenerateKey for P521 { Ok(reply::GenerateKey { key: key_id }) } } + +impl MechanismImpl for P521Prehashed { + #[inline(never)] + fn sign( + &self, + keystore: &mut impl Keystore, + request: &request::Sign, + ) -> Result { + let key_id = request.key; + + let secret_key = load_secret_key(keystore, &key_id)?; + let signing_key = SigningKey::from(ecdsa::SigningKey::from(secret_key)); + let signature: p521::ecdsa::Signature = signing_key + .sign_prehash_with_rng(keystore.rng(), &request.message) + .map_err(|_| Error::InvalidSerializedRequest)?; + + // debug_now!("making signature"); + let serialized_signature = match request.format { + SignatureSerialization::Asn1Der => { + let der = signature.to_der(); + Signature::from_slice(der.as_bytes()).unwrap() + } + SignatureSerialization::Raw => Signature::from_slice(&signature.to_bytes()).unwrap(), + _ => { + return Err(Error::InvalidSerializationFormat); + } + }; + + // return signature + Ok(reply::Sign { + signature: serialized_signature, + }) + } +} diff --git a/src/mechanisms/sha256.rs b/src/mechanisms/sha256.rs index 92460277fe2..a2e2213a3cf 100644 --- a/src/mechanisms/sha256.rs +++ b/src/mechanisms/sha256.rs @@ -1,13 +1,14 @@ use crate::api::{reply, request}; use crate::error::Error; use crate::key; -use crate::service::{DeriveKey, Hash}; +use crate::service::MechanismImpl; use crate::store::keystore::Keystore; use crate::types::ShortData; -impl DeriveKey for super::Sha256 { +impl MechanismImpl for super::Sha256 { #[inline(never)] fn derive_key( + &self, keystore: &mut impl Keystore, request: &request::DeriveKey, ) -> Result { @@ -32,11 +33,13 @@ impl DeriveKey for super::Sha256 { Ok(reply::DeriveKey { key: key_id }) } -} -impl Hash for super::Sha256 { #[inline(never)] - fn hash(_keystore: &mut impl Keystore, request: &request::Hash) -> Result { + fn hash( + &self, + _keystore: &mut impl Keystore, + request: &request::Hash, + ) -> Result { use sha2::digest::Digest; let mut hash = sha2::Sha256::new(); hash.update(&request.message); diff --git a/src/mechanisms/shared_secret.rs b/src/mechanisms/shared_secret.rs index 904654604bc..76097bc52d8 100644 --- a/src/mechanisms/shared_secret.rs +++ b/src/mechanisms/shared_secret.rs @@ -1,13 +1,14 @@ use crate::api::{reply, request}; use crate::error::Error; use crate::key; -use crate::service::{SerializeKey, UnsafeInjectKey}; +use crate::service::MechanismImpl; use crate::store::keystore::Keystore; use crate::types::{KeySerialization, SerializedKey}; -impl SerializeKey for super::SharedSecret { +impl MechanismImpl for super::SharedSecret { #[inline(never)] fn serialize_key( + &self, keystore: &mut impl Keystore, request: &request::SerializeKey, ) -> Result { @@ -28,10 +29,9 @@ impl SerializeKey for super::SharedSecret { Ok(reply::SerializeKey { serialized_key }) } -} -impl UnsafeInjectKey for super::SharedSecret { fn unsafe_inject_key( + &self, keystore: &mut impl Keystore, request: &request::UnsafeInjectKey, ) -> Result { diff --git a/src/mechanisms/tdes.rs b/src/mechanisms/tdes.rs index 51a63efc6d1..829de59549d 100644 --- a/src/mechanisms/tdes.rs +++ b/src/mechanisms/tdes.rs @@ -12,15 +12,16 @@ use generic_array::GenericArray; use crate::api::{reply, request}; use crate::error::Error; use crate::key; -use crate::service::{Decrypt, Encrypt, UnsafeInjectKey}; +use crate::service::MechanismImpl; use crate::store::keystore::Keystore; const TDES_KEY_SIZE: usize = 24; -impl Encrypt for super::Tdes { +impl MechanismImpl for super::Tdes { /// Encrypts a single block. Let's hope we don't have to support ECB!! #[inline(never)] fn encrypt( + &self, keystore: &mut impl Keystore, request: &request::Encrypt, ) -> Result { @@ -57,12 +58,11 @@ impl Encrypt for super::Tdes { tag: Default::default(), }) } -} -impl Decrypt for super::Tdes { /// Decrypts a single block. Let's hope we don't have to support ECB!! #[inline(never)] fn decrypt( + &self, keystore: &mut impl Keystore, request: &request::Decrypt, ) -> Result { @@ -88,10 +88,9 @@ impl Decrypt for super::Tdes { plaintext: Some(message), }) } -} -impl UnsafeInjectKey for super::Tdes { fn unsafe_inject_key( + &self, keystore: &mut impl Keystore, request: &request::UnsafeInjectKey, ) -> Result { diff --git a/src/mechanisms/totp.rs b/src/mechanisms/totp.rs index c38c3662ef9..e7015af5cc8 100644 --- a/src/mechanisms/totp.rs +++ b/src/mechanisms/totp.rs @@ -1,7 +1,7 @@ use crate::api::{reply, request}; use crate::error::Error; use crate::key; -use crate::service::{Exists, Sign}; +use crate::service::MechanismImpl; use crate::store::keystore::Keystore; // code copied from https://github.com/avacariu/rust-oath @@ -44,9 +44,13 @@ fn dynamic_truncation(hs: &[u8]) -> u64 { p & 0x7fff_ffff } -impl Sign for super::Totp { +impl MechanismImpl for super::Totp { #[inline(never)] - fn sign(keystore: &mut impl Keystore, request: &request::Sign) -> Result { + fn sign( + &self, + keystore: &mut impl Keystore, + request: &request::Sign, + ) -> Result { let key_id = request.key; let key = keystore.load_key(key::Secrecy::Secret, None, &key_id)?; @@ -72,11 +76,10 @@ impl Sign for super::Totp { signature: crate::Bytes::from_slice(totp_material.to_le_bytes().as_ref()).unwrap(), }) } -} -impl Exists for super::Totp { #[inline(never)] fn exists( + &self, keystore: &mut impl Keystore, request: &request::Exists, ) -> Result { diff --git a/src/mechanisms/trng.rs b/src/mechanisms/trng.rs index 2550d52c7d8..a2ba95cdd77 100644 --- a/src/mechanisms/trng.rs +++ b/src/mechanisms/trng.rs @@ -3,11 +3,12 @@ use rand_core::RngCore; use crate::api::{reply, request}; use crate::error::Error; use crate::key; -use crate::service::GenerateKey; +use crate::service::MechanismImpl; use crate::store::keystore::Keystore; -impl GenerateKey for super::Trng { +impl MechanismImpl for super::Trng { fn generate_key( + &self, keystore: &mut impl Keystore, request: &request::GenerateKey, ) -> Result { diff --git a/src/mechanisms/x255.rs b/src/mechanisms/x255.rs index 0cf53ea6a6e..cf9fe86f13a 100644 --- a/src/mechanisms/x255.rs +++ b/src/mechanisms/x255.rs @@ -4,9 +4,7 @@ use salty::agreement; use crate::api::{reply, request}; use crate::error::Error; use crate::key; -use crate::service::{ - Agree, DeriveKey, DeserializeKey, Exists, GenerateKey, SerializeKey, UnsafeInjectKey, -}; +use crate::service::MechanismImpl; use crate::store::keystore::Keystore; use crate::types::{KeyId, KeySerialization, SerializedKey}; @@ -41,9 +39,10 @@ fn load_secret_key( Ok(keypair) } -impl Agree for super::X255 { +impl MechanismImpl for super::X255 { // #[inline(never)] fn agree( + &self, keystore: &mut impl Keystore, request: &request::Agree, ) -> Result { @@ -75,11 +74,10 @@ impl Agree for super::X255 { shared_secret: key_id, }) } -} -impl GenerateKey for super::X255 { // #[inline(never)] fn generate_key( + &self, keystore: &mut impl Keystore, request: &request::GenerateKey, ) -> Result { @@ -98,11 +96,10 @@ impl GenerateKey for super::X255 { // return handle Ok(reply::GenerateKey { key: key_id }) } -} -impl Exists for super::X255 { // #[inline(never)] fn exists( + &self, keystore: &mut impl Keystore, request: &request::Exists, ) -> Result { @@ -110,11 +107,10 @@ impl Exists for super::X255 { let exists = keystore.exists_key(key::Secrecy::Secret, Some(key::Kind::X255), &key_id); Ok(reply::Exists { exists }) } -} -impl DeriveKey for super::X255 { // #[inline(never)] fn derive_key( + &self, keystore: &mut impl Keystore, request: &request::DeriveKey, ) -> Result { @@ -133,11 +129,10 @@ impl DeriveKey for super::X255 { Ok(reply::DeriveKey { key: public_id }) } -} -impl SerializeKey for super::X255 { // #[inline(never)] fn serialize_key( + &self, keystore: &mut impl Keystore, request: &request::SerializeKey, ) -> Result { @@ -159,11 +154,10 @@ impl SerializeKey for super::X255 { Ok(reply::SerializeKey { serialized_key }) } -} -impl DeserializeKey for super::X255 { // #[inline(never)] fn deserialize_key( + &self, keystore: &mut impl Keystore, request: &request::DeserializeKey, ) -> Result { @@ -192,10 +186,9 @@ impl DeserializeKey for super::X255 { Ok(reply::DeserializeKey { key: public_id }) } -} -impl UnsafeInjectKey for super::X255 { fn unsafe_inject_key( + &self, keystore: &mut impl Keystore, request: &request::UnsafeInjectKey, ) -> Result { diff --git a/src/service.rs b/src/service.rs index 950c7af203d..da257583e53 100644 --- a/src/service.rs +++ b/src/service.rs @@ -29,31 +29,96 @@ pub mod attest; // mod macros; #[cfg(feature = "crypto-client")] -macro_rules! rpc_trait { ($($Name:ident, $name:ident,)*) => { $( +macro_rules! rpc_trait { { $($name:ident,)* } => { + pub trait MechanismImpl { + $( + paste::paste! { + fn $name( + &self, + keystore: &mut impl Keystore, + request: &request::[<$name:camel>], + ) -> Result]> { + let _ = (keystore, request); + Err(Error::MechanismNotAvailable) + } + } + )* + } - pub trait $Name { - fn $name(_keystore: &mut impl Keystore, _request: &request::$Name) - -> Result { Err(Error::MechanismNotAvailable) } + impl MechanismImpl for Mechanism { + $( + paste::paste! { + #[inline(never)] + fn $name( + &self, + keystore: &mut impl Keystore, + request: &request::[<$name:camel>], + ) -> Result]> { + // TODO: sync with IMPLEMENTED_MECHANISMS + match self { + #[cfg(feature = "aes256-cbc")] + Self::Aes256Cbc => mechanisms::Aes256Cbc.$name(keystore, request), + #[cfg(feature = "chacha8-poly1305")] + Self::Chacha8Poly1305 => mechanisms::Chacha8Poly1305.$name(keystore, request), + #[cfg(feature = "ed255")] + Self::Ed255 => mechanisms::Ed255.$name(keystore, request), + #[cfg(feature = "hmac-blake2s")] + Self::HmacBlake2s => mechanisms::HmacBlake2s.$name(keystore, request), + #[cfg(feature = "hmac-sha1")] + Self::HmacSha1 => mechanisms::HmacSha1.$name(keystore, request), + #[cfg(feature = "hmac-sha256")] + Self::HmacSha256 => mechanisms::HmacSha256.$name(keystore, request), + #[cfg(feature = "hmac-sha512")] + Self::HmacSha512 => mechanisms::HmacSha512.$name(keystore, request), + #[cfg(feature = "p256")] + Self::P256 => mechanisms::P256.$name(keystore, request), + #[cfg(feature = "p256")] + Self::P256Prehashed => mechanisms::P256Prehashed.$name(keystore, request), + #[cfg(feature = "p384")] + Self::P384 => mechanisms::P384.$name(keystore, request), + #[cfg(feature = "p384")] + Self::P384Prehashed => mechanisms::P384Prehashed.$name(keystore, request), + #[cfg(feature = "p521")] + Self::P521 => mechanisms::P521.$name(keystore, request), + #[cfg(feature = "p521")] + Self::P521Prehashed => mechanisms::P521Prehashed.$name(keystore, request), + #[cfg(feature = "sha256")] + Self::Sha256 => mechanisms::Sha256.$name(keystore, request), + #[cfg(feature = "shared-secret")] + Self::SharedSecret => mechanisms::SharedSecret.$name(keystore, request), + #[cfg(feature = "tdes")] + Self::Tdes => mechanisms::Tdes.$name(keystore, request), + #[cfg(feature = "totp")] + Self::Totp => mechanisms::Totp.$name(keystore, request), + #[cfg(feature = "trng")] + Self::Trng => mechanisms::Trng.$name(keystore, request), + #[cfg(feature = "x255")] + Self::X255 => mechanisms::X255.$name(keystore, request), + _ => Err(Error::MechanismNotAvailable), + } + } + } + )* } -)* } } +} } #[cfg(feature = "crypto-client")] rpc_trait! { - Agree, agree, - Decrypt, decrypt, - DeriveKey, derive_key, - DeserializeKey, deserialize_key, - Encrypt, encrypt, - Exists, exists, - GenerateKey, generate_key, - Hash, hash, - SerializeKey, serialize_key, - Sign, sign, - UnsafeInjectKey, unsafe_inject_key, - UnwrapKey, unwrap_key, - Verify, verify, + agree, + decrypt, + derive_key, + deserialize_key, + encrypt, + exists, + generate_key, + hash, + serialize_key, + sign, + unsafe_inject_key, + unwrap_key, + verify, // TODO: can the default implementation be implemented in terms of Encrypt? - WrapKey, wrap_key, + wrap_key, } pub struct ServiceResources

@@ -169,18 +234,10 @@ impl ServiceResources

{ Request::DummyRequest => Ok(Reply::DummyReply), #[cfg(feature = "crypto-client")] - Request::Agree(request) => match request.mechanism { - #[cfg(feature = "p521")] - Mechanism::P521 => mechanisms::P521::agree(&mut keystore(self, ctx)?, request), - #[cfg(feature = "p384")] - Mechanism::P384 => mechanisms::P384::agree(&mut keystore(self, ctx)?, request), - #[cfg(feature = "p256")] - Mechanism::P256 => mechanisms::P256::agree(&mut keystore(self, ctx)?, request), - #[cfg(feature = "x255")] - Mechanism::X255 => mechanisms::X255::agree(&mut keystore(self, ctx)?, request), - _ => Err(Error::MechanismNotAvailable), - } - .map(Reply::Agree), + Request::Agree(request) => request + .mechanism + .agree(&mut keystore(self, ctx)?, request) + .map(Reply::Agree), #[cfg(feature = "attestation-client")] Request::Attest(request) => { @@ -199,100 +256,28 @@ impl ServiceResources

{ } #[cfg(feature = "crypto-client")] - Request::Decrypt(request) => match request.mechanism { - #[cfg(feature = "aes256-cbc")] - Mechanism::Aes256Cbc => { - mechanisms::Aes256Cbc::decrypt(&mut keystore(self, ctx)?, request) - } - #[cfg(feature = "chacha8-poly1305")] - Mechanism::Chacha8Poly1305 => { - mechanisms::Chacha8Poly1305::decrypt(&mut keystore(self, ctx)?, request) - } - #[cfg(feature = "tdes")] - Mechanism::Tdes => mechanisms::Tdes::decrypt(&mut keystore(self, ctx)?, request), - _ => Err(Error::MechanismNotAvailable), - } - .map(Reply::Decrypt), + Request::Decrypt(request) => request + .mechanism + .decrypt(&mut keystore(self, ctx)?, request) + .map(Reply::Decrypt), #[cfg(feature = "crypto-client")] - Request::DeriveKey(request) => match request.mechanism { - #[cfg(feature = "hmac-blake2s")] - Mechanism::HmacBlake2s => { - mechanisms::HmacBlake2s::derive_key(&mut keystore(self, ctx)?, request) - } - #[cfg(feature = "hmac-sha1")] - Mechanism::HmacSha1 => { - mechanisms::HmacSha1::derive_key(&mut keystore(self, ctx)?, request) - } - #[cfg(feature = "hmac-sha256")] - Mechanism::HmacSha256 => { - mechanisms::HmacSha256::derive_key(&mut keystore(self, ctx)?, request) - } - #[cfg(feature = "hmac-sha512")] - Mechanism::HmacSha512 => { - mechanisms::HmacSha512::derive_key(&mut keystore(self, ctx)?, request) - } - #[cfg(feature = "ed255")] - Mechanism::Ed255 => { - mechanisms::Ed255::derive_key(&mut keystore(self, ctx)?, request) - } - #[cfg(feature = "p521")] - Mechanism::P521 => mechanisms::P521::derive_key(&mut keystore(self, ctx)?, request), - #[cfg(feature = "p384")] - Mechanism::P384 => mechanisms::P384::derive_key(&mut keystore(self, ctx)?, request), - #[cfg(feature = "p256")] - Mechanism::P256 => mechanisms::P256::derive_key(&mut keystore(self, ctx)?, request), - #[cfg(feature = "sha256")] - Mechanism::Sha256 => { - mechanisms::Sha256::derive_key(&mut keystore(self, ctx)?, request) - } - #[cfg(feature = "x255")] - Mechanism::X255 => mechanisms::X255::derive_key(&mut keystore(self, ctx)?, request), - _ => Err(Error::MechanismNotAvailable), - } - .map(Reply::DeriveKey), + Request::DeriveKey(request) => request + .mechanism + .derive_key(&mut keystore(self, ctx)?, request) + .map(Reply::DeriveKey), #[cfg(feature = "crypto-client")] - Request::DeserializeKey(request) => match request.mechanism { - #[cfg(feature = "ed255")] - Mechanism::Ed255 => { - mechanisms::Ed255::deserialize_key(&mut keystore(self, ctx)?, request) - } - #[cfg(feature = "p521")] - Mechanism::P521 => { - mechanisms::P521::deserialize_key(&mut keystore(self, ctx)?, request) - } - #[cfg(feature = "p384")] - Mechanism::P384 => { - mechanisms::P384::deserialize_key(&mut keystore(self, ctx)?, request) - } - #[cfg(feature = "p256")] - Mechanism::P256 => { - mechanisms::P256::deserialize_key(&mut keystore(self, ctx)?, request) - } - #[cfg(feature = "x255")] - Mechanism::X255 => { - mechanisms::X255::deserialize_key(&mut keystore(self, ctx)?, request) - } - _ => Err(Error::MechanismNotAvailable), - } - .map(Reply::DeserializeKey), + Request::DeserializeKey(request) => request + .mechanism + .deserialize_key(&mut keystore(self, ctx)?, request) + .map(Reply::DeserializeKey), #[cfg(feature = "crypto-client")] - Request::Encrypt(request) => match request.mechanism { - #[cfg(feature = "aes256-cbc")] - Mechanism::Aes256Cbc => { - mechanisms::Aes256Cbc::encrypt(&mut keystore(self, ctx)?, request) - } - #[cfg(feature = "chacha8-poly1305")] - Mechanism::Chacha8Poly1305 => { - mechanisms::Chacha8Poly1305::encrypt(&mut keystore(self, ctx)?, request) - } - #[cfg(feature = "tdes")] - Mechanism::Tdes => mechanisms::Tdes::encrypt(&mut keystore(self, ctx)?, request), - _ => Err(Error::MechanismNotAvailable), - } - .map(Reply::Encrypt), + Request::Encrypt(request) => request + .mechanism + .encrypt(&mut keystore(self, ctx)?, request) + .map(Reply::Encrypt), #[cfg(feature = "crypto-client")] Request::Delete(request) => { @@ -313,52 +298,16 @@ impl ServiceResources

{ } #[cfg(feature = "crypto-client")] - Request::Exists(request) => match request.mechanism { - #[cfg(feature = "ed255")] - Mechanism::Ed255 => mechanisms::Ed255::exists(&mut keystore(self, ctx)?, request), - #[cfg(feature = "p521")] - Mechanism::P521 => mechanisms::P521::exists(&mut keystore(self, ctx)?, request), - #[cfg(feature = "p384")] - Mechanism::P384 => mechanisms::P384::exists(&mut keystore(self, ctx)?, request), - #[cfg(feature = "p256")] - Mechanism::P256 => mechanisms::P256::exists(&mut keystore(self, ctx)?, request), - #[cfg(feature = "totp")] - Mechanism::Totp => mechanisms::Totp::exists(&mut keystore(self, ctx)?, request), - #[cfg(feature = "x255")] - Mechanism::X255 => mechanisms::X255::exists(&mut keystore(self, ctx)?, request), - _ => Err(Error::MechanismNotAvailable), - } - .map(Reply::Exists), + Request::Exists(request) => request + .mechanism + .exists(&mut keystore(self, ctx)?, request) + .map(Reply::Exists), #[cfg(feature = "crypto-client")] - Request::GenerateKey(request) => match request.mechanism { - #[cfg(feature = "chacha8-poly1305")] - Mechanism::Chacha8Poly1305 => { - mechanisms::Chacha8Poly1305::generate_key(&mut keystore(self, ctx)?, request) - } - #[cfg(feature = "ed255")] - Mechanism::Ed255 => { - mechanisms::Ed255::generate_key(&mut keystore(self, ctx)?, request) - } - #[cfg(feature = "p521")] - Mechanism::P521 => { - mechanisms::P521::generate_key(&mut keystore(self, ctx)?, request) - } - #[cfg(feature = "p384")] - Mechanism::P384 => { - mechanisms::P384::generate_key(&mut keystore(self, ctx)?, request) - } - #[cfg(feature = "p256")] - Mechanism::P256 => { - mechanisms::P256::generate_key(&mut keystore(self, ctx)?, request) - } - #[cfg(feature = "x255")] - Mechanism::X255 => { - mechanisms::X255::generate_key(&mut keystore(self, ctx)?, request) - } - _ => Err(Error::MechanismNotAvailable), - } - .map(Reply::GenerateKey), + Request::GenerateKey(request) => request + .mechanism + .generate_key(&mut keystore(self, ctx)?, request) + .map(Reply::GenerateKey), #[cfg(feature = "crypto-client")] Request::GenerateSecretKey(request) => { @@ -382,42 +331,10 @@ impl ServiceResources

{ // deprecated #[cfg(feature = "crypto-client")] - Request::UnsafeInjectKey(request) => match request.mechanism { - #[cfg(feature = "p521")] - Mechanism::P521 => { - mechanisms::P521::unsafe_inject_key(&mut keystore(self, ctx)?, request) - } - #[cfg(feature = "p384")] - Mechanism::P384 => { - mechanisms::P384::unsafe_inject_key(&mut keystore(self, ctx)?, request) - } - #[cfg(feature = "p256")] - Mechanism::P256 => { - mechanisms::P256::unsafe_inject_key(&mut keystore(self, ctx)?, request) - } - #[cfg(feature = "x255")] - Mechanism::X255 => { - mechanisms::X255::unsafe_inject_key(&mut keystore(self, ctx)?, request) - } - #[cfg(feature = "ed255")] - Mechanism::Ed255 => { - mechanisms::Ed255::unsafe_inject_key(&mut keystore(self, ctx)?, request) - } - #[cfg(feature = "shared-secret")] - Mechanism::SharedSecret => { - mechanisms::SharedSecret::unsafe_inject_key(&mut keystore(self, ctx)?, request) - } - #[cfg(feature = "aes256-cbc")] - Mechanism::Aes256Cbc => { - mechanisms::Aes256Cbc::unsafe_inject_key(&mut keystore(self, ctx)?, request) - } - #[cfg(feature = "tdes")] - Mechanism::Tdes => { - mechanisms::Tdes::unsafe_inject_key(&mut keystore(self, ctx)?, request) - } - _ => Err(Error::MechanismNotAvailable), - } - .map(Reply::UnsafeInjectKey), + Request::UnsafeInjectKey(request) => request + .mechanism + .unsafe_inject_key(&mut keystore(self, ctx)?, request) + .map(Reply::UnsafeInjectKey), #[cfg(feature = "crypto-client")] Request::UnsafeInjectSharedKey(request) => { @@ -434,12 +351,10 @@ impl ServiceResources

{ } #[cfg(feature = "crypto-client")] - Request::Hash(request) => match request.mechanism { - #[cfg(feature = "sha256")] - Mechanism::Sha256 => mechanisms::Sha256::hash(&mut keystore(self, ctx)?, request), - _ => Err(Error::MechanismNotAvailable), - } - .map(Reply::Hash), + Request::Hash(request) => request + .mechanism + .hash(&mut keystore(self, ctx)?, request) + .map(Reply::Hash), #[cfg(feature = "filesystem-client")] Request::LocateFile(request) => { @@ -593,78 +508,16 @@ impl ServiceResources

{ } #[cfg(feature = "crypto-client")] - Request::SerializeKey(request) => match request.mechanism { - #[cfg(feature = "ed255")] - Mechanism::Ed255 => { - mechanisms::Ed255::serialize_key(&mut keystore(self, ctx)?, request) - } - #[cfg(feature = "p521")] - Mechanism::P521 => { - mechanisms::P521::serialize_key(&mut keystore(self, ctx)?, request) - } - #[cfg(feature = "p384")] - Mechanism::P384 => { - mechanisms::P384::serialize_key(&mut keystore(self, ctx)?, request) - } - #[cfg(feature = "p256")] - Mechanism::P256 => { - mechanisms::P256::serialize_key(&mut keystore(self, ctx)?, request) - } - #[cfg(feature = "x255")] - Mechanism::X255 => { - mechanisms::X255::serialize_key(&mut keystore(self, ctx)?, request) - } - #[cfg(feature = "shared-secret")] - Mechanism::SharedSecret => { - mechanisms::SharedSecret::serialize_key(&mut keystore(self, ctx)?, request) - } - _ => Err(Error::MechanismNotAvailable), - } - .map(Reply::SerializeKey), + Request::SerializeKey(request) => request + .mechanism + .serialize_key(&mut keystore(self, ctx)?, request) + .map(Reply::SerializeKey), #[cfg(feature = "crypto-client")] - Request::Sign(request) => match request.mechanism { - #[cfg(feature = "ed255")] - Mechanism::Ed255 => mechanisms::Ed255::sign(&mut keystore(self, ctx)?, request), - #[cfg(feature = "hmac-blake2s")] - Mechanism::HmacBlake2s => { - mechanisms::HmacBlake2s::sign(&mut keystore(self, ctx)?, request) - } - #[cfg(feature = "hmac-sha1")] - Mechanism::HmacSha1 => { - mechanisms::HmacSha1::sign(&mut keystore(self, ctx)?, request) - } - #[cfg(feature = "hmac-sha256")] - Mechanism::HmacSha256 => { - mechanisms::HmacSha256::sign(&mut keystore(self, ctx)?, request) - } - #[cfg(feature = "hmac-sha512")] - Mechanism::HmacSha512 => { - mechanisms::HmacSha512::sign(&mut keystore(self, ctx)?, request) - } - #[cfg(feature = "p521")] - Mechanism::P521 => mechanisms::P521::sign(&mut keystore(self, ctx)?, request), - #[cfg(feature = "p521")] - Mechanism::P521Prehashed => { - mechanisms::P521Prehashed::sign(&mut keystore(self, ctx)?, request) - } - #[cfg(feature = "p384")] - Mechanism::P384 => mechanisms::P384::sign(&mut keystore(self, ctx)?, request), - #[cfg(feature = "p384")] - Mechanism::P384Prehashed => { - mechanisms::P384Prehashed::sign(&mut keystore(self, ctx)?, request) - } - #[cfg(feature = "p256")] - Mechanism::P256 => mechanisms::P256::sign(&mut keystore(self, ctx)?, request), - #[cfg(feature = "p256")] - Mechanism::P256Prehashed => { - mechanisms::P256Prehashed::sign(&mut keystore(self, ctx)?, request) - } - #[cfg(feature = "totp")] - Mechanism::Totp => mechanisms::Totp::sign(&mut keystore(self, ctx)?, request), - _ => Err(Error::MechanismNotAvailable), - } - .map(Reply::Sign), + Request::Sign(request) => request + .mechanism + .sign(&mut keystore(self, ctx)?, request) + .map(Reply::Sign), #[cfg(feature = "filesystem-client")] Request::WriteFile(request) => { @@ -673,42 +526,22 @@ impl ServiceResources

{ } #[cfg(feature = "crypto-client")] - Request::UnwrapKey(request) => match request.mechanism { - #[cfg(feature = "chacha8-poly1305")] - Mechanism::Chacha8Poly1305 => { - mechanisms::Chacha8Poly1305::unwrap_key(&mut keystore(self, ctx)?, request) - } - _ => Err(Error::MechanismNotAvailable), - } - .map(Reply::UnwrapKey), + Request::UnwrapKey(request) => request + .mechanism + .unwrap_key(&mut keystore(self, ctx)?, request) + .map(Reply::UnwrapKey), #[cfg(feature = "crypto-client")] - Request::Verify(request) => match request.mechanism { - #[cfg(feature = "ed255")] - Mechanism::Ed255 => mechanisms::Ed255::verify(&mut keystore(self, ctx)?, request), - #[cfg(feature = "p521")] - Mechanism::P521 => mechanisms::P521::verify(&mut keystore(self, ctx)?, request), - #[cfg(feature = "p384")] - Mechanism::P384 => mechanisms::P384::verify(&mut keystore(self, ctx)?, request), - #[cfg(feature = "p256")] - Mechanism::P256 => mechanisms::P256::verify(&mut keystore(self, ctx)?, request), - _ => Err(Error::MechanismNotAvailable), - } - .map(Reply::Verify), + Request::Verify(request) => request + .mechanism + .verify(&mut keystore(self, ctx)?, request) + .map(Reply::Verify), #[cfg(feature = "crypto-client")] - Request::WrapKey(request) => match request.mechanism { - #[cfg(feature = "aes256-cbc")] - Mechanism::Aes256Cbc => { - mechanisms::Aes256Cbc::wrap_key(&mut keystore(self, ctx)?, request) - } - #[cfg(feature = "chacha8-poly1305")] - Mechanism::Chacha8Poly1305 => { - mechanisms::Chacha8Poly1305::wrap_key(&mut keystore(self, ctx)?, request) - } - _ => Err(Error::MechanismNotAvailable), - } - .map(Reply::WrapKey), + Request::WrapKey(request) => request + .mechanism + .wrap_key(&mut keystore(self, ctx)?, request) + .map(Reply::WrapKey), #[cfg(feature = "ui-client")] Request::RequestUserConsent(request) => { diff --git a/src/service/attest.rs b/src/service/attest.rs index 08e36d40598..b7feb073573 100644 --- a/src/service/attest.rs +++ b/src/service/attest.rs @@ -9,7 +9,7 @@ use crate::{ api::{reply::Attest as AttestReply, request, request::Attest as AttestRequest}, error::Error, key, mechanisms, - service::{DeriveKey, SerializeKey, Sign}, + service::MechanismImpl, store::certstore::Certstore, store::keystore::Keystore, types::{ @@ -67,26 +67,28 @@ pub fn try_attest( let spki = match key_algorithm { KeyAlgorithm::Ed255 => { - let public_key = mechanisms::Ed255::derive_key( - keystore, - &request::DeriveKey { - mechanism: Mechanism::Ed255, - base_key: request.private_key, - additional_data: None, - attributes: StorageAttributes::new().set_persistence(Location::Volatile), - }, - )? - .key; - let serialized_key = mechanisms::Ed255::serialize_key( - keystore, - &request::SerializeKey { - mechanism: Mechanism::Ed255, - key: public_key, - format: KeySerialization::Raw, - }, - ) - .unwrap() - .serialized_key; + let public_key = mechanisms::Ed255 + .derive_key( + keystore, + &request::DeriveKey { + mechanism: Mechanism::Ed255, + base_key: request.private_key, + additional_data: None, + attributes: StorageAttributes::new().set_persistence(Location::Volatile), + }, + )? + .key; + let serialized_key = mechanisms::Ed255 + .serialize_key( + keystore, + &request::SerializeKey { + mechanism: Mechanism::Ed255, + key: public_key, + format: KeySerialization::Raw, + }, + ) + .unwrap() + .serialized_key; keystore.delete_key(&public_key); SerializedSubjectPublicKey::Ed255( @@ -98,26 +100,28 @@ pub fn try_attest( } KeyAlgorithm::P256 => { - let public_key = mechanisms::P256::derive_key( - keystore, - &request::DeriveKey { - mechanism: Mechanism::P256, - base_key: request.private_key, - additional_data: None, - attributes: StorageAttributes::new().set_persistence(Location::Volatile), - }, - )? - .key; - let serialized_key = mechanisms::P256::serialize_key( - keystore, - &request::SerializeKey { - mechanism: Mechanism::P256, - key: public_key, - format: KeySerialization::Sec1, - }, - ) - .unwrap() - .serialized_key; + let public_key = mechanisms::P256 + .derive_key( + keystore, + &request::DeriveKey { + mechanism: Mechanism::P256, + base_key: request.private_key, + additional_data: None, + attributes: StorageAttributes::new().set_persistence(Location::Volatile), + }, + )? + .key; + let serialized_key = mechanisms::P256 + .serialize_key( + keystore, + &request::SerializeKey { + mechanism: Mechanism::P256, + key: public_key, + format: KeySerialization::Sec1, + }, + ) + .unwrap() + .serialized_key; keystore.delete_key(&public_key); SerializedSubjectPublicKey::P256( @@ -156,33 +160,35 @@ pub fn try_attest( // 2. sign the TBS Cert let signature = match signature_algorithm { SignatureAlgorithm::Ed255 => { - let signature = mechanisms::Ed255::sign( - attn_keystore, - &request::Sign { - mechanism: Mechanism::Ed255, - key: ED255_ATTN_KEY, - message, - format: SignatureSerialization::Raw, - }, - ) - .unwrap() - .signature; - SerializedSignature::Ed255(signature.as_ref().try_into().unwrap()) - } - SignatureAlgorithm::P256 => SerializedSignature::P256( - heapless_bytes::Bytes::from_slice( - mechanisms::P256::sign( + let signature = mechanisms::Ed255 + .sign( attn_keystore, &request::Sign { - mechanism: Mechanism::P256, - key: P256_ATTN_KEY, + mechanism: Mechanism::Ed255, + key: ED255_ATTN_KEY, message, - format: SignatureSerialization::Asn1Der, + format: SignatureSerialization::Raw, }, ) .unwrap() - .signature - .as_ref(), + .signature; + SerializedSignature::Ed255(signature.as_ref().try_into().unwrap()) + } + SignatureAlgorithm::P256 => SerializedSignature::P256( + heapless_bytes::Bytes::from_slice( + mechanisms::P256 + .sign( + attn_keystore, + &request::Sign { + mechanism: Mechanism::P256, + key: P256_ATTN_KEY, + message, + format: SignatureSerialization::Asn1Der, + }, + ) + .unwrap() + .signature + .as_ref(), ) .unwrap(), ), diff --git a/src/types.rs b/src/types.rs index 46f7adbf034..32f41aae232 100644 --- a/src/types.rs +++ b/src/types.rs @@ -77,6 +77,8 @@ pub const IMPLEMENTED_MECHANISMS: &[Mechanism] = &[ Mechanism::Tdes, #[cfg(feature = "totp")] Mechanism::Totp, + #[cfg(feature = "trng")] + Mechanism::Trng, #[cfg(feature = "x255")] Mechanism::X255, ]; From 7f3d0000a328425092e990e9ad8ac2e6bcf67264 Mon Sep 17 00:00:00 2001 From: Robin Krahl Date: Tue, 4 Mar 2025 12:17:13 +0100 Subject: [PATCH 2/4] Use single source of truth for implemented mechanisms This patch removes the manual mechanism enumeration in IMPLEMENTED_MECHANISMS and changes the rpc_trait! macro to also generate this constant so that it acts as a single source of truth. As a side effect, the IMPLEMENTED_MECHANISMS constant is moved from types to service and only available if the crypto-client feature is enabled. --- src/service.rs | 211 ++++++++++++++++++++++++++++++------------------- src/types.rs | 41 ---------- 2 files changed, 131 insertions(+), 121 deletions(-) diff --git a/src/service.rs b/src/service.rs index da257583e53..d058363169a 100644 --- a/src/service.rs +++ b/src/service.rs @@ -29,96 +29,147 @@ pub mod attest; // mod macros; #[cfg(feature = "crypto-client")] -macro_rules! rpc_trait { { $($name:ident,)* } => { - pub trait MechanismImpl { - $( - paste::paste! { - fn $name( - &self, - keystore: &mut impl Keystore, - request: &request::[<$name:camel>], - ) -> Result]> { - let _ = (keystore, request); - Err(Error::MechanismNotAvailable) +macro_rules! impl_mechanisms { + { + [ + $( + #[cfg($($cfg_cond:tt)*)] + $mechanism:ident, + )* + ] + } => { + pub const IMPLEMENTED_MECHANISMS: &[Mechanism] = &[ + $( + #[cfg($($cfg_cond)*)] + Mechanism::$mechanism, + )* + ]; + } +} + +#[cfg(feature = "crypto-client")] +macro_rules! impl_rpc_method { + { + $name:ident, + mechanisms = [$( + #[cfg($($cfg_cond:tt)*)] + $mechanism:ident, + )*], + } => { + paste::paste! { + #[inline(never)] + fn $name( + &self, + keystore: &mut impl Keystore, + request: &request::[<$name:camel>], + ) -> Result]> { + match self { + $( + #[cfg($($cfg_cond)*)] + Self::$mechanism => mechanisms::$mechanism.$name(keystore, request), + )* + _ => Err(Error::MechanismNotAvailable), } } - )* + } } +} - impl MechanismImpl for Mechanism { - $( - paste::paste! { - #[inline(never)] - fn $name( - &self, - keystore: &mut impl Keystore, - request: &request::[<$name:camel>], - ) -> Result]> { - // TODO: sync with IMPLEMENTED_MECHANISMS - match self { - #[cfg(feature = "aes256-cbc")] - Self::Aes256Cbc => mechanisms::Aes256Cbc.$name(keystore, request), - #[cfg(feature = "chacha8-poly1305")] - Self::Chacha8Poly1305 => mechanisms::Chacha8Poly1305.$name(keystore, request), - #[cfg(feature = "ed255")] - Self::Ed255 => mechanisms::Ed255.$name(keystore, request), - #[cfg(feature = "hmac-blake2s")] - Self::HmacBlake2s => mechanisms::HmacBlake2s.$name(keystore, request), - #[cfg(feature = "hmac-sha1")] - Self::HmacSha1 => mechanisms::HmacSha1.$name(keystore, request), - #[cfg(feature = "hmac-sha256")] - Self::HmacSha256 => mechanisms::HmacSha256.$name(keystore, request), - #[cfg(feature = "hmac-sha512")] - Self::HmacSha512 => mechanisms::HmacSha512.$name(keystore, request), - #[cfg(feature = "p256")] - Self::P256 => mechanisms::P256.$name(keystore, request), - #[cfg(feature = "p256")] - Self::P256Prehashed => mechanisms::P256Prehashed.$name(keystore, request), - #[cfg(feature = "p384")] - Self::P384 => mechanisms::P384.$name(keystore, request), - #[cfg(feature = "p384")] - Self::P384Prehashed => mechanisms::P384Prehashed.$name(keystore, request), - #[cfg(feature = "p521")] - Self::P521 => mechanisms::P521.$name(keystore, request), - #[cfg(feature = "p521")] - Self::P521Prehashed => mechanisms::P521Prehashed.$name(keystore, request), - #[cfg(feature = "sha256")] - Self::Sha256 => mechanisms::Sha256.$name(keystore, request), - #[cfg(feature = "shared-secret")] - Self::SharedSecret => mechanisms::SharedSecret.$name(keystore, request), - #[cfg(feature = "tdes")] - Self::Tdes => mechanisms::Tdes.$name(keystore, request), - #[cfg(feature = "totp")] - Self::Totp => mechanisms::Totp.$name(keystore, request), - #[cfg(feature = "trng")] - Self::Trng => mechanisms::Trng.$name(keystore, request), - #[cfg(feature = "x255")] - Self::X255 => mechanisms::X255.$name(keystore, request), - _ => Err(Error::MechanismNotAvailable), +#[cfg(feature = "crypto-client")] +macro_rules! rpc_trait { + { + methods = [$($name:ident,)*], + mechanisms = $mechanisms:tt, + } => { + pub trait MechanismImpl { + $( + paste::paste! { + fn $name( + &self, + keystore: &mut impl Keystore, + request: &request::[<$name:camel>], + ) -> Result]> { + let _ = (keystore, request); + Err(Error::MechanismNotAvailable) } } - } - )* + )* + } + + impl MechanismImpl for Mechanism { + $( + impl_rpc_method! { + $name, + mechanisms = $mechanisms, + } + )* + } + + impl_mechanisms! { + $mechanisms + } } -} } +} #[cfg(feature = "crypto-client")] rpc_trait! { - agree, - decrypt, - derive_key, - deserialize_key, - encrypt, - exists, - generate_key, - hash, - serialize_key, - sign, - unsafe_inject_key, - unwrap_key, - verify, - // TODO: can the default implementation be implemented in terms of Encrypt? - wrap_key, + methods = [ + agree, + decrypt, + derive_key, + deserialize_key, + encrypt, + exists, + generate_key, + hash, + serialize_key, + sign, + unsafe_inject_key, + unwrap_key, + verify, + // TODO: can the default implementation be implemented in terms of Encrypt? + wrap_key, + ], + mechanisms = [ + #[cfg(feature = "aes256-cbc")] + Aes256Cbc, + #[cfg(feature = "chacha8-poly1305")] + Chacha8Poly1305, + #[cfg(feature = "ed255")] + Ed255, + #[cfg(feature = "hmac-blake2s")] + HmacBlake2s, + #[cfg(feature = "hmac-sha1")] + HmacSha1, + #[cfg(feature = "hmac-sha256")] + HmacSha256, + #[cfg(feature = "hmac-sha512")] + HmacSha512, + #[cfg(feature = "p256")] + P256, + #[cfg(feature = "p256")] + P256Prehashed, + #[cfg(feature = "p384")] + P384, + #[cfg(feature = "p384")] + P384Prehashed, + #[cfg(feature = "p521")] + P521, + #[cfg(feature = "p521")] + P521Prehashed, + #[cfg(feature = "sha256")] + Sha256, + #[cfg(feature = "shared-secret")] + SharedSecret, + #[cfg(feature = "tdes")] + Tdes, + #[cfg(feature = "totp")] + Totp, + #[cfg(feature = "trng")] + Trng, + #[cfg(feature = "x255")] + X255, + ], } pub struct ServiceResources

diff --git a/src/types.rs b/src/types.rs index 32f41aae232..2a419889781 100644 --- a/src/types.rs +++ b/src/types.rs @@ -42,47 +42,6 @@ pub mod consent { pub use trussed_core::types::consent::{Error, Level, Result}; } -pub const IMPLEMENTED_MECHANISMS: &[Mechanism] = &[ - #[cfg(feature = "aes256-cbc")] - Mechanism::Aes256Cbc, - #[cfg(feature = "chacha8-poly1305")] - Mechanism::Chacha8Poly1305, - #[cfg(feature = "ed255")] - Mechanism::Ed255, - #[cfg(feature = "hmac-blake2s")] - Mechanism::HmacBlake2s, - #[cfg(feature = "hmac-sha1")] - Mechanism::HmacSha1, - #[cfg(feature = "hmac-sha256")] - Mechanism::HmacSha256, - #[cfg(feature = "hmac-sha512")] - Mechanism::HmacSha512, - #[cfg(feature = "p256")] - Mechanism::P256, - #[cfg(feature = "p256")] - Mechanism::P256Prehashed, - #[cfg(feature = "p384")] - Mechanism::P384, - #[cfg(feature = "p384")] - Mechanism::P384Prehashed, - #[cfg(feature = "p521")] - Mechanism::P521, - #[cfg(feature = "p521")] - Mechanism::P521Prehashed, - #[cfg(feature = "sha256")] - Mechanism::Sha256, - #[cfg(feature = "shared-secret")] - Mechanism::SharedSecret, - #[cfg(feature = "tdes")] - Mechanism::Tdes, - #[cfg(feature = "totp")] - Mechanism::Totp, - #[cfg(feature = "trng")] - Mechanism::Trng, - #[cfg(feature = "x255")] - Mechanism::X255, -]; - /// The context for a syscall (per client). /// /// The context stores the state used by the standard syscall implementations, see From 1408449bc4477b71ba4d88b7a5509ecb1afc6556 Mon Sep 17 00:00:00 2001 From: Robin Krahl Date: Tue, 4 Mar 2025 12:25:42 +0100 Subject: [PATCH 3/4] Make mechanisms module private This patch makes the mechanisms module private. The mechanism implementation can still be accessed using the Mechanism enum. This leads to a clenaer public API and triggers a compiler warning if the mapping between the Mechanism enum and the mechanism implementations is wrong (as the implementation would then be unused). --- CHANGELOG.md | 1 + src/lib.rs | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b29383bf46e..cebc013ba2c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -65,6 +65,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Removed the `unsafe` keyword for the `Store` trait. - Removed the `unsafe` keyword for the `Platform` trait. - Replaced the mechanism RPC traits in `service` with a single `MechanismImpl` trait. +- Made the `mechanisms` module private. Mechanism implementation can still be accessed via the `Mechanism` enum. ### Fixed diff --git a/src/lib.rs b/src/lib.rs index 772648cc91e..12132dc0232 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -32,7 +32,7 @@ pub mod error; pub mod interrupt; pub mod key; #[cfg(feature = "crypto-client")] -pub mod mechanisms; +mod mechanisms; pub mod pipe; pub mod platform; #[cfg(feature = "serde-extensions")] From 7aea23b7e1897ca85e1f7598b0ada161c1423ca2 Mon Sep 17 00:00:00 2001 From: Robin Krahl Date: Mon, 10 Mar 2025 14:43:10 +0100 Subject: [PATCH 4/4] Remove paste dependency The paste dependency is unmaintained and not really necessary for our use case. --- Cargo.toml | 1 - src/service.rs | 78 ++++++++++++++++++++++++-------------------------- 2 files changed, 38 insertions(+), 41 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index e7a73ff93ca..57dc5f996cd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -44,7 +44,6 @@ rand_core.workspace = true serde.workspace = true zeroize = { version = "1.2", default-features = false, features = ["zeroize_derive"] } rand_chacha = { version = "0.3.1", default-features = false } -paste = "1" # RustCrypto aes = { version = "0.8", default-features = false } diff --git a/src/service.rs b/src/service.rs index d058363169a..f959e8817d6 100644 --- a/src/service.rs +++ b/src/service.rs @@ -50,26 +50,25 @@ macro_rules! impl_mechanisms { #[cfg(feature = "crypto-client")] macro_rules! impl_rpc_method { { - $name:ident, + $struct:ident, + $method:ident, mechanisms = [$( #[cfg($($cfg_cond:tt)*)] $mechanism:ident, )*], } => { - paste::paste! { - #[inline(never)] - fn $name( - &self, - keystore: &mut impl Keystore, - request: &request::[<$name:camel>], - ) -> Result]> { - match self { - $( - #[cfg($($cfg_cond)*)] - Self::$mechanism => mechanisms::$mechanism.$name(keystore, request), - )* - _ => Err(Error::MechanismNotAvailable), - } + #[inline(never)] + fn $method( + &self, + keystore: &mut impl Keystore, + request: &request::$struct, + ) -> Result { + match self { + $( + #[cfg($($cfg_cond)*)] + Self::$mechanism => mechanisms::$mechanism.$method(keystore, request), + )* + _ => Err(Error::MechanismNotAvailable), } } } @@ -78,20 +77,18 @@ macro_rules! impl_rpc_method { #[cfg(feature = "crypto-client")] macro_rules! rpc_trait { { - methods = [$($name:ident,)*], + methods = [$($method:ident: $struct:ident,)*], mechanisms = $mechanisms:tt, } => { pub trait MechanismImpl { $( - paste::paste! { - fn $name( - &self, - keystore: &mut impl Keystore, - request: &request::[<$name:camel>], - ) -> Result]> { - let _ = (keystore, request); - Err(Error::MechanismNotAvailable) - } + fn $method( + &self, + keystore: &mut impl Keystore, + request: &request::$struct, + ) -> Result { + let _ = (keystore, request); + Err(Error::MechanismNotAvailable) } )* } @@ -99,7 +96,8 @@ macro_rules! rpc_trait { impl MechanismImpl for Mechanism { $( impl_rpc_method! { - $name, + $struct, + $method, mechanisms = $mechanisms, } )* @@ -114,21 +112,21 @@ macro_rules! rpc_trait { #[cfg(feature = "crypto-client")] rpc_trait! { methods = [ - agree, - decrypt, - derive_key, - deserialize_key, - encrypt, - exists, - generate_key, - hash, - serialize_key, - sign, - unsafe_inject_key, - unwrap_key, - verify, + agree: Agree, + decrypt: Decrypt, + derive_key: DeriveKey, + deserialize_key: DeserializeKey, + encrypt: Encrypt, + exists: Exists, + generate_key: GenerateKey, + hash: Hash, + serialize_key: SerializeKey, + sign: Sign, + unsafe_inject_key: UnsafeInjectKey, + unwrap_key: UnwrapKey, + verify: Verify, // TODO: can the default implementation be implemented in terms of Encrypt? - wrap_key, + wrap_key: WrapKey, ], mechanisms = [ #[cfg(feature = "aes256-cbc")]