From 8624e883be1e7d80938417f00208f789f9e59a5b Mon Sep 17 00:00:00 2001 From: Robin Krahl Date: Wed, 10 Apr 2024 17:04:37 +0200 Subject: [PATCH] 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. --- Cargo.toml | 1 + src/mechanisms.rs | 56 ++---- src/mechanisms/aes256cbc.rs | 29 +-- src/mechanisms/chacha8poly1305.rs | 82 ++++---- src/mechanisms/ed255.rs | 57 ++---- src/mechanisms/hmacblake2s.rs | 20 +- src/mechanisms/hmacsha1.rs | 20 +- src/mechanisms/hmacsha256.rs | 20 +- src/mechanisms/hmacsha512.rs | 20 +- src/mechanisms/p256.rs | 126 +++++------- src/mechanisms/sha256.rs | 20 +- src/mechanisms/shared_secret.rs | 10 +- src/mechanisms/tdes.rs | 19 +- src/mechanisms/totp.rs | 18 +- src/mechanisms/trng.rs | 7 +- src/mechanisms/x255.rs | 46 ++--- src/service.rs | 316 +++++++++++------------------- src/service/attest.rs | 130 ++++++------ src/store/keystore.rs | 5 +- 19 files changed, 400 insertions(+), 602 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index dba9705643a..c413223f57c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -57,6 +57,7 @@ littlefs2 = "0.4.0" p256-cortex-m4 = { version = "0.1.0-alpha.6", features = ["prehash", "sec1-signatures"] } salty = { version = "0.3.0", features = ["cose"] } serde-indexed = "0.1.0" +paste = "1.0.14" [dev-dependencies] # Testing diff --git a/src/mechanisms.rs b/src/mechanisms.rs index 67089a965e3..a472d6f64ca 100644 --- a/src/mechanisms.rs +++ b/src/mechanisms.rs @@ -10,73 +10,51 @@ // The question of breaking down `reply_to` into smaller, more globally understandable pieces, // should be revisited. -// TODO: rename to aes256-cbc-zero-iv -pub struct Aes256Cbc {} +pub struct Aes256Cbc; mod aes256cbc; -pub struct Chacha8Poly1305 {} +pub struct Chacha8Poly1305; mod chacha8poly1305; -pub struct SharedSecret {} +pub struct SharedSecret; mod shared_secret; -pub struct Ed255 {} +pub struct Ed255; mod ed255; -pub struct HmacBlake2s {} +pub struct HmacBlake2s; #[cfg(feature = "hmac-blake2s")] mod hmacblake2s; #[cfg(not(feature = "hmac-blake2s"))] -impl crate::service::DeriveKey for HmacBlake2s {} -#[cfg(not(feature = "hmac-blake2s"))] -impl crate::service::Sign for HmacBlake2s {} +impl crate::service::MechanismImpl for HmacBlake2s {} -pub struct HmacSha1 {} +pub struct HmacSha1; mod hmacsha1; -pub struct HmacSha256 {} +pub struct HmacSha256; mod hmacsha256; -pub struct HmacSha512 {} +pub struct HmacSha512; #[cfg(feature = "hmac-sha512")] mod hmacsha512; #[cfg(not(feature = "hmac-sha512"))] -impl crate::service::DeriveKey for HmacSha512 {} -#[cfg(not(feature = "hmac-sha512"))] -impl crate::service::Sign for HmacSha512 {} +impl crate::service::MechanismImpl for HmacSha512 {} -pub struct P256 {} -pub struct P256Prehashed {} +pub struct P256; +pub struct P256Prehashed; mod p256; -pub struct Sha256 {} +pub struct Sha256; mod sha256; -pub struct Tdes {} +pub struct Tdes; mod tdes; -pub struct Totp {} +pub struct Totp; mod totp; -pub struct Trng {} +pub struct Trng; mod trng; -pub struct X255 {} +pub struct 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 c70aba15591..9e09131d7bc 100644 --- a/src/mechanisms/aes256cbc.rs +++ b/src/mechanisms/aes256cbc.rs @@ -1,16 +1,17 @@ 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; #[cfg(feature = "aes256-cbc")] -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 { @@ -64,11 +65,9 @@ impl Encrypt for super::Aes256Cbc { tag: ShortData::new(), }) } -} -#[cfg(feature = "aes256-cbc")] -impl WrapKey for super::Aes256Cbc { fn wrap_key( + &self, keystore: &mut impl Keystore, request: &request::WrapKey, ) -> Result { @@ -93,17 +92,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 }) } -} -#[cfg(feature = "aes256-cbc")] -impl Decrypt for super::Aes256Cbc { fn decrypt( + &self, keystore: &mut impl Keystore, request: &request::Decrypt, ) -> Result { @@ -158,11 +155,9 @@ impl Decrypt for super::Aes256Cbc { plaintext: Some(plaintext), }) } -} -#[cfg(feature = "aes256-cbc")] -impl UnsafeInjectKey for super::Aes256Cbc { fn unsafe_inject_key( + &self, keystore: &mut impl Keystore, request: &request::UnsafeInjectKey, ) -> Result { @@ -173,7 +168,7 @@ impl UnsafeInjectKey for super::Aes256Cbc { let key_id = keystore.store_key( request.attributes.persistence, key::Secrecy::Secret, - key::Kind::Symmetric(request.raw_key.len()), + key::Kind::Symmetric(request.raw_key.len()).into(), &request.raw_key, )?; @@ -182,10 +177,4 @@ 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 {} +impl MechanismImpl for super::Aes256Cbc {} diff --git a/src/mechanisms/chacha8poly1305.rs b/src/mechanisms/chacha8poly1305.rs index c19460decf2..e474824ecc4 100644 --- a/src/mechanisms/chacha8poly1305.rs +++ b/src/mechanisms/chacha8poly1305.rs @@ -4,7 +4,7 @@ use rand_core::RngCore; 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}; @@ -19,10 +19,27 @@ const TAG_LEN: usize = 16; const KIND: key::Kind = key::Kind::Symmetric(KEY_LEN); const KIND_NONCE: key::Kind = key::Kind::Symmetric32Nonce(NONCE_LEN); +#[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) + } +} + #[cfg(feature = "chacha8-poly1305")] -impl GenerateKey for super::Chacha8Poly1305 { +impl MechanismImpl for super::Chacha8Poly1305 { #[inline(never)] fn generate_key( + &self, keystore: &mut impl Keystore, request: &request::GenerateKey, ) -> Result { @@ -39,34 +56,16 @@ impl GenerateKey for super::Chacha8Poly1305 { let key_id = keystore.store_key( request.attributes.persistence, key::Secrecy::Secret, - KIND_NONCE, + KIND_NONCE.into(), &serialized, )?; 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) - } -} -#[cfg(feature = "chacha8-poly1305")] -impl Decrypt for super::Chacha8Poly1305 { #[inline(never)] fn decrypt( + &self, keystore: &mut impl Keystore, request: &request::Decrypt, ) -> Result { @@ -104,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 { @@ -165,12 +162,10 @@ impl Encrypt for super::Chacha8Poly1305 { tag, }) } -} -#[cfg(feature = "chacha8-poly1305")] -impl WrapKey for super::Chacha8Poly1305 { #[inline(never)] fn wrap_key( + &self, keystore: &mut impl Keystore, request: &request::WrapKey, ) -> Result { @@ -188,19 +183,17 @@ 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 = crate::postcard_serialize_bytes(&encryption_reply).map_err(|_| Error::CborError)?; Ok(reply::WrapKey { wrapped_key }) } -} -#[cfg(feature = "chacha8-poly1305")] -impl UnwrapKey for super::Chacha8Poly1305 { #[inline(never)] fn unwrap_key( + &self, keystore: &mut impl Keystore, request: &request::UnwrapKey, ) -> Result { @@ -219,13 +212,12 @@ impl UnwrapKey for super::Chacha8Poly1305 { tag, }; - 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 { @@ -239,7 +231,7 @@ impl UnwrapKey for super::Chacha8Poly1305 { request.attributes.persistence, // using for signing keys... we need to know key::Secrecy::Secret, - kind, + kind.into(), &material, )?; @@ -248,12 +240,4 @@ impl UnwrapKey for super::Chacha8Poly1305 { } #[cfg(not(feature = "chacha8-poly1305"))] -impl Decrypt for super::Chacha8Poly1305 {} -#[cfg(not(feature = "chacha8-poly1305"))] -impl Encrypt for super::Chacha8Poly1305 {} -#[cfg(not(feature = "chacha8-poly1305"))] -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 {} +impl MechanismImpl for super::Chacha8Poly1305 {} diff --git a/src/mechanisms/ed255.rs b/src/mechanisms/ed255.rs index 9e8ce5084ce..f56af8944f6 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, @@ -44,9 +42,10 @@ fn load_keypair(keystore: &mut impl Keystore, key_id: &KeyId) -> Result Result { @@ -56,18 +55,16 @@ impl DeriveKey for super::Ed255 { let public_id = keystore.store_key( request.attributes.persistence, key::Secrecy::Public, - key::Kind::Ed255, + key::Kind::Ed255.into(), keypair.public.as_bytes(), )?; Ok(reply::DeriveKey { key: public_id }) } -} -#[cfg(feature = "ed255")] -impl DeserializeKey for super::Ed255 { #[inline(never)] fn deserialize_key( + &self, keystore: &mut impl Keystore, request: &request::DeserializeKey, ) -> Result { @@ -90,18 +87,16 @@ impl DeserializeKey for super::Ed255 { let public_id = keystore.store_key( request.attributes.persistence, key::Secrecy::Public, - key::Kind::Ed255, + key::Kind::Ed255.into(), public_key.as_bytes(), )?; Ok(reply::DeserializeKey { key: public_id }) } -} -#[cfg(feature = "ed255")] -impl GenerateKey for super::Ed255 { #[inline(never)] fn generate_key( + &self, keystore: &mut impl Keystore, request: &request::GenerateKey, ) -> Result { @@ -123,12 +118,10 @@ impl GenerateKey for super::Ed255 { // return handle Ok(reply::GenerateKey { key: key_id }) } -} -#[cfg(feature = "ed255")] -impl SerializeKey for super::Ed255 { #[inline(never)] fn serialize_key( + &self, keystore: &mut impl Keystore, request: &request::SerializeKey, ) -> Result { @@ -161,12 +154,10 @@ impl SerializeKey for super::Ed255 { Ok(reply::SerializeKey { serialized_key }) } -} -#[cfg(feature = "ed255")] -impl Exists for super::Ed255 { #[inline(never)] fn exists( + &self, keystore: &mut impl Keystore, request: &request::Exists, ) -> Result { @@ -175,12 +166,13 @@ impl Exists for super::Ed255 { let exists = keystore.exists_key(key::Secrecy::Secret, Some(key::Kind::Ed255), &key_id); Ok(reply::Exists { exists }) } -} -#[cfg(feature = "ed255")] -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 @@ -208,12 +200,10 @@ impl Sign for super::Ed255 { signature: our_signature, }) } -} -#[cfg(feature = "ed255")] -impl Verify for super::Ed255 { #[inline(never)] fn verify( + &self, keystore: &mut impl Keystore, request: &request::Verify, ) -> Result { @@ -239,10 +229,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 { @@ -270,16 +259,4 @@ 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 {} +impl MechanismImpl for super::Ed255 {} diff --git a/src/mechanisms/hmacblake2s.rs b/src/mechanisms/hmacblake2s.rs index 9ee4d834c54..d0e362b776e 100644 --- a/src/mechanisms/hmacblake2s.rs +++ b/src/mechanisms/hmacblake2s.rs @@ -1,14 +1,15 @@ 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; #[cfg(feature = "hmac-blake2s")] -impl DeriveKey for super::HmacBlake2s { +impl MechanismImpl for super::HmacBlake2s { #[inline(never)] fn derive_key( + &self, keystore: &mut impl Keystore, request: &request::DeriveKey, ) -> Result { @@ -32,18 +33,19 @@ impl DeriveKey for super::HmacBlake2s { let key = keystore.store_key( request.attributes.persistence, key::Secrecy::Secret, - key::Kind::Symmetric(32), + key::Kind::Symmetric(32).into(), &derived_key, )?; Ok(reply::DeriveKey { key }) } -} -#[cfg(feature = "hmac-blake2s")] -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; @@ -66,6 +68,4 @@ impl Sign for super::HmacBlake2s { } #[cfg(not(feature = "hmac-blake2s"))] -impl DeriveKey for super::HmacBlake2s {} -#[cfg(not(feature = "hmac-blake2s"))] -impl Sign for super::HmacBlake2s {} +impl MechanismImpl for super::HmacBlake2s {} diff --git a/src/mechanisms/hmacsha1.rs b/src/mechanisms/hmacsha1.rs index ff630329534..4e5cd28e605 100644 --- a/src/mechanisms/hmacsha1.rs +++ b/src/mechanisms/hmacsha1.rs @@ -1,14 +1,15 @@ 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; #[cfg(feature = "hmac-sha1")] -impl DeriveKey for super::HmacSha1 { +impl MechanismImpl for super::HmacSha1 { #[inline(never)] fn derive_key( + &self, keystore: &mut impl Keystore, request: &request::DeriveKey, ) -> Result { @@ -32,18 +33,19 @@ impl DeriveKey for super::HmacSha1 { let key_id = keystore.store_key( request.attributes.persistence, key::Secrecy::Secret, - key::Kind::Symmetric(20), + key::Kind::Symmetric(20).into(), &derived_key, )?; Ok(reply::DeriveKey { key: key_id }) } -} -#[cfg(feature = "hmac-sha1")] -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; @@ -67,6 +69,4 @@ impl Sign for super::HmacSha1 { } #[cfg(not(feature = "hmac-sha1"))] -impl DeriveKey for super::HmacSha1 {} -#[cfg(not(feature = "hmac-sha1"))] -impl Sign for super::HmacSha1 {} +impl MechanismImpl for super::HmacSha1 {} diff --git a/src/mechanisms/hmacsha256.rs b/src/mechanisms/hmacsha256.rs index 573bbf46b08..c2e5517b225 100644 --- a/src/mechanisms/hmacsha256.rs +++ b/src/mechanisms/hmacsha256.rs @@ -1,14 +1,15 @@ 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; #[cfg(feature = "hmac-sha256")] -impl DeriveKey for super::HmacSha256 { +impl MechanismImpl for super::HmacSha256 { #[inline(never)] fn derive_key( + &self, keystore: &mut impl Keystore, request: &request::DeriveKey, ) -> Result { @@ -37,18 +38,19 @@ impl DeriveKey for super::HmacSha256 { let key_id = keystore.store_key( request.attributes.persistence, key::Secrecy::Secret, - key::Kind::Symmetric(32), + key::Kind::Symmetric(32).into(), &derived_key, )?; Ok(reply::DeriveKey { key: key_id }) } -} -#[cfg(feature = "hmac-sha256")] -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; @@ -72,6 +74,4 @@ impl Sign for super::HmacSha256 { } #[cfg(not(feature = "hmac-sha256"))] -impl DeriveKey for super::HmacSha256 {} -#[cfg(not(feature = "hmac-sha256"))] -impl Sign for super::HmacSha256 {} +impl MechanismImpl for super::HmacSha256 {} diff --git a/src/mechanisms/hmacsha512.rs b/src/mechanisms/hmacsha512.rs index e4d1dc4d8be..b164370e253 100644 --- a/src/mechanisms/hmacsha512.rs +++ b/src/mechanisms/hmacsha512.rs @@ -1,14 +1,15 @@ 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; #[cfg(feature = "hmac-sha512")] -impl DeriveKey for super::HmacSha512 { +impl MechanismImpl for super::HmacSha512 { #[inline(never)] fn derive_key( + &self, keystore: &mut impl Keystore, request: &request::DeriveKey, ) -> Result { @@ -32,18 +33,19 @@ impl DeriveKey for super::HmacSha512 { let key = keystore.store_key( request.attributes.persistence, key::Secrecy::Secret, - key::Kind::Symmetric(64), + key::Kind::Symmetric(64).into(), &derived_key, )?; Ok(reply::DeriveKey { key }) } -} -#[cfg(feature = "hmac-sha512")] -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; @@ -66,6 +68,4 @@ impl Sign for super::HmacSha512 { } #[cfg(not(feature = "hmac-sha512"))] -impl DeriveKey for super::HmacSha512 {} -#[cfg(not(feature = "hmac-sha512"))] -impl Sign for super::HmacSha512 {} +impl MechanismImpl for super::HmacSha512 {} diff --git a/src/mechanisms/p256.rs b/src/mechanisms/p256.rs index e25df84ad3c..c5de57d6cca 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, @@ -45,9 +42,10 @@ fn load_public_key( } #[cfg(feature = "p256")] -impl Agree for super::P256 { +impl MechanismImpl for super::P256 { #[inline(never)] fn agree( + &self, keystore: &mut impl Keystore, request: &request::Agree, ) -> Result { @@ -81,12 +79,10 @@ impl Agree for super::P256 { shared_secret: key_id, }) } -} -#[cfg(feature = "p256")] -impl DeriveKey for super::P256 { #[inline(never)] fn derive_key( + &self, keystore: &mut impl Keystore, request: &request::DeriveKey, ) -> Result { @@ -98,18 +94,16 @@ impl DeriveKey for super::P256 { let public_id = keystore.store_key( request.attributes.persistence, key::Secrecy::Public, - key::Kind::P256, + key::Kind::P256.into(), &public_key.to_compressed_sec1_bytes(), )?; Ok(reply::DeriveKey { key: public_id }) } -} -#[cfg(feature = "p256")] -impl DeserializeKey for super::P256 { #[inline(never)] fn deserialize_key( + &self, keystore: &mut impl Keystore, request: &request::DeserializeKey, ) -> Result { @@ -172,18 +166,16 @@ impl DeserializeKey for super::P256 { let public_id = keystore.store_key( request.attributes.persistence, key::Secrecy::Public, - key::Kind::P256, + key::Kind::P256.into(), &public_key.to_compressed_sec1_bytes(), )?; Ok(reply::DeserializeKey { key: public_id }) } -} -#[cfg(feature = "p256")] -impl GenerateKey for super::P256 { #[inline(never)] fn generate_key( + &self, keystore: &mut impl Keystore, request: &request::GenerateKey, ) -> Result { @@ -200,12 +192,10 @@ impl GenerateKey for super::P256 { // return handle Ok(reply::GenerateKey { key: key_id }) } -} -#[cfg(feature = "p256")] -impl SerializeKey for super::P256 { #[inline(never)] fn serialize_key( + &self, keystore: &mut impl Keystore, request: &request::SerializeKey, ) -> Result { @@ -250,12 +240,10 @@ impl SerializeKey for super::P256 { Ok(reply::SerializeKey { serialized_key }) } -} -#[cfg(feature = "p256")] -impl Exists for super::P256 { #[inline(never)] fn exists( + &self, keystore: &mut impl Keystore, request: &request::Exists, ) -> Result { @@ -263,12 +251,13 @@ impl Exists for super::P256 { let exists = keystore.exists_key(key::Secrecy::Secret, Some(key::Kind::P256), &key_id); Ok(reply::Exists { exists }) } -} -#[cfg(feature = "p256")] -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)?; @@ -291,40 +280,10 @@ impl Sign for super::P256 { signature: serialized_signature, }) } -} -#[cfg(feature = "p256")] -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 signature - Ok(reply::Sign { - signature: serialized_signature, - }) - } -} - -#[cfg(feature = "p256")] -impl Verify for super::P256 { #[inline(never)] fn verify( + &self, keystore: &mut impl Keystore, request: &request::Verify, ) -> Result { @@ -345,10 +304,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 { @@ -375,21 +333,39 @@ impl UnsafeInjectKey for super::P256 { } } +#[cfg(feature = "p256")] +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 signature + Ok(reply::Sign { + signature: serialized_signature, + }) + } +} + #[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 Sign for super::P256Prehashed {} +impl MechanismImpl for super::P256 {} #[cfg(not(feature = "p256"))] -impl Verify for super::P256 {} +impl MechanismImpl for super::P256Prehashed {} diff --git a/src/mechanisms/sha256.rs b/src/mechanisms/sha256.rs index 073daa42d1c..0bc92c7bfef 100644 --- a/src/mechanisms/sha256.rs +++ b/src/mechanisms/sha256.rs @@ -1,14 +1,15 @@ 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; #[cfg(feature = "sha256")] -impl DeriveKey for super::Sha256 { +impl MechanismImpl for super::Sha256 { #[inline(never)] fn derive_key( + &self, keystore: &mut impl Keystore, request: &request::DeriveKey, ) -> Result { @@ -27,18 +28,19 @@ impl DeriveKey for super::Sha256 { let key_id = keystore.store_key( request.attributes.persistence, key::Secrecy::Secret, - key::Kind::Symmetric(32), + key::Kind::Symmetric(32).into(), &symmetric_key, )?; Ok(reply::DeriveKey { key: key_id }) } -} -#[cfg(feature = "sha256")] -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); @@ -51,6 +53,4 @@ impl Hash for super::Sha256 { } #[cfg(not(feature = "sha256"))] -impl DeriveKey for super::Sha256 {} -#[cfg(not(feature = "sha256"))] -impl Hash for super::Sha256 {} +impl MechanismImpl for super::Sha256 {} diff --git a/src/mechanisms/shared_secret.rs b/src/mechanisms/shared_secret.rs index 904654604bc..c2ce4b51783 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,17 +29,16 @@ 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 { let key_id = keystore.store_key( request.attributes.persistence, key::Secrecy::Secret, - key::Kind::Shared(request.raw_key.len()), + key::Kind::Shared(request.raw_key.len()).into(), &request.raw_key, )?; diff --git a/src/mechanisms/tdes.rs b/src/mechanisms/tdes.rs index c4bb2db05f6..b1c4f4f9690 100644 --- a/src/mechanisms/tdes.rs +++ b/src/mechanisms/tdes.rs @@ -13,16 +13,17 @@ 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; #[cfg(feature = "tdes")] -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 { @@ -59,13 +60,11 @@ impl Encrypt for super::Tdes { tag: Default::default(), }) } -} -#[cfg(feature = "tdes")] -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 { @@ -91,10 +90,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 { @@ -105,7 +103,7 @@ impl UnsafeInjectKey for super::Tdes { let key_id = keystore.store_key( request.attributes.persistence, key::Secrecy::Secret, - key::Kind::Symmetric(request.raw_key.len()), + key::Kind::Symmetric(request.raw_key.len()).into(), &request.raw_key, )?; @@ -114,7 +112,4 @@ impl UnsafeInjectKey for super::Tdes { } #[cfg(not(feature = "tdes"))] -impl Encrypt for super::Tdes {} - -#[cfg(not(feature = "tdes"))] -impl Decrypt for super::Tdes {} +impl MechanismImpl for super::Tdes {} diff --git a/src/mechanisms/totp.rs b/src/mechanisms/totp.rs index affe67ac72e..c1e4bb2d0fa 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 @@ -47,9 +47,13 @@ fn dynamic_truncation(hs: &[u8]) -> u64 { } #[cfg(feature = "totp")] -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)?; @@ -75,12 +79,10 @@ impl Sign for super::Totp { signature: crate::Bytes::from_slice(totp_material.to_le_bytes().as_ref()).unwrap(), }) } -} -#[cfg(feature = "totp")] -impl Exists for super::Totp { #[inline(never)] fn exists( + &self, keystore: &mut impl Keystore, request: &request::Exists, ) -> Result { @@ -96,9 +98,7 @@ impl Exists for super::Totp { } #[cfg(not(feature = "totp"))] -impl Sign for super::Totp {} -#[cfg(not(feature = "totp"))] -impl Exists for super::Totp {} +impl MechanismImpl for super::Totp {} #[cfg(all(test, feature = "totp"))] mod tests { diff --git a/src/mechanisms/trng.rs b/src/mechanisms/trng.rs index 6ef8e475767..f4fcf0ebdf0 100644 --- a/src/mechanisms/trng.rs +++ b/src/mechanisms/trng.rs @@ -3,12 +3,13 @@ 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; #[cfg(feature = "trng")] -impl GenerateKey for super::Trng { +impl MechanismImpl for super::Trng { fn generate_key( + &self, keystore: &mut impl Keystore, request: &request::GenerateKey, ) -> Result { @@ -20,7 +21,7 @@ impl GenerateKey for super::Trng { let key_id = keystore.store_key( request.attributes.persistence, key::Secrecy::Secret, - key::Kind::Symmetric(32), + key::Kind::Symmetric(32).into(), &entropy, )?; diff --git a/src/mechanisms/x255.rs b/src/mechanisms/x255.rs index 69ad0ce5441..e98adf084e2 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}; @@ -42,9 +40,10 @@ fn load_secret_key( } #[cfg(feature = "x255")] -impl Agree for super::X255 { +impl MechanismImpl for super::X255 { // #[inline(never)] fn agree( + &self, keystore: &mut impl Keystore, request: &request::Agree, ) -> Result { @@ -76,12 +75,10 @@ impl Agree for super::X255 { shared_secret: key_id, }) } -} -#[cfg(feature = "x255")] -impl GenerateKey for super::X255 { // #[inline(never)] fn generate_key( + &self, keystore: &mut impl Keystore, request: &request::GenerateKey, ) -> Result { @@ -100,12 +97,10 @@ impl GenerateKey for super::X255 { // return handle Ok(reply::GenerateKey { key: key_id }) } -} -#[cfg(feature = "x255")] -impl Exists for super::X255 { // #[inline(never)] fn exists( + &self, keystore: &mut impl Keystore, request: &request::Exists, ) -> Result { @@ -113,12 +108,10 @@ impl Exists for super::X255 { let exists = keystore.exists_key(key::Secrecy::Secret, Some(key::Kind::X255), &key_id); Ok(reply::Exists { exists }) } -} -#[cfg(feature = "x255")] -impl DeriveKey for super::X255 { // #[inline(never)] fn derive_key( + &self, keystore: &mut impl Keystore, request: &request::DeriveKey, ) -> Result { @@ -131,18 +124,16 @@ impl DeriveKey for super::X255 { let public_id = keystore.store_key( request.attributes.persistence, key::Secrecy::Public, - key::Kind::X255, + key::Kind::X255.into(), &public_key_bytes, )?; Ok(reply::DeriveKey { key: public_id }) } -} -#[cfg(feature = "x255")] -impl SerializeKey for super::X255 { // #[inline(never)] fn serialize_key( + &self, keystore: &mut impl Keystore, request: &request::SerializeKey, ) -> Result { @@ -164,12 +155,10 @@ impl SerializeKey for super::X255 { Ok(reply::SerializeKey { serialized_key }) } -} -#[cfg(feature = "x255")] -impl DeserializeKey for super::X255 { // #[inline(never)] fn deserialize_key( + &self, keystore: &mut impl Keystore, request: &request::DeserializeKey, ) -> Result { @@ -192,16 +181,15 @@ impl DeserializeKey for super::X255 { let public_id = keystore.store_key( request.attributes.persistence, key::Secrecy::Public, - key::Kind::X255, + key::Kind::X255.into(), &public_key.to_bytes(), )?; Ok(reply::DeserializeKey { key: public_id }) } -} -impl UnsafeInjectKey for super::X255 { fn unsafe_inject_key( + &self, keystore: &mut impl Keystore, request: &request::UnsafeInjectKey, ) -> Result { @@ -229,14 +217,4 @@ impl UnsafeInjectKey for super::X255 { } #[cfg(not(feature = "x255"))] -impl Agree for super::X255 {} -#[cfg(not(feature = "x255"))] -impl GenerateKey for super::X255 {} -#[cfg(not(feature = "x255"))] -impl Exists for super::X255 {} -#[cfg(not(feature = "x255"))] -impl DeriveKey for super::X255 {} -#[cfg(not(feature = "x255"))] -impl SerializeKey for super::X255 {} -#[cfg(not(feature = "x255"))] -impl DeserializeKey for super::X255 {} +impl MechanismImpl for super::X255 {} diff --git a/src/service.rs b/src/service.rs index 11b0f110e3b..44b6b8f498b 100644 --- a/src/service.rs +++ b/src/service.rs @@ -32,33 +32,68 @@ use crate::{ pub mod attest; -// #[macro_use] -// mod macros; - -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]> { + match self { + Self::Aes256Cbc => mechanisms::Aes256Cbc.$name(keystore, request), + Self::Chacha8Poly1305 => mechanisms::Chacha8Poly1305.$name(keystore, request), + Self::SharedSecret => mechanisms::SharedSecret.$name(keystore, request), + Self::Ed255 => mechanisms::Ed255.$name(keystore, request), + Self::HmacBlake2s => mechanisms::HmacBlake2s.$name(keystore, request), + Self::HmacSha1 => mechanisms::HmacSha1.$name(keystore, request), + Self::HmacSha256 => mechanisms::HmacSha256.$name(keystore, request), + Self::HmacSha512 => mechanisms::HmacSha512.$name(keystore, request), + Self::P256 => mechanisms::P256.$name(keystore, request), + Self::P256Prehashed => mechanisms::P256Prehashed.$name(keystore, request), + Self::Sha256 => mechanisms::Sha256.$name(keystore, request), + Self::Tdes => mechanisms::Tdes.$name(keystore, request), + Self::Totp => mechanisms::Totp.$name(keystore, request), + Self::Trng => mechanisms::Trng.$name(keystore, request), + Self::X255 => mechanisms::X255.$name(keystore, request), + Self::Rsa2048Raw | + Self::Rsa3072Raw | + Self::Rsa4096Raw | + Self::Rsa2048Pkcs1v15 | + Self::Rsa3072Pkcs1v15 | + Self::Rsa4096Pkcs1v15 => Err(Error::MechanismNotAvailable), + } + } + } + )* } -)* } } +} } 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

@@ -170,12 +205,10 @@ impl ServiceResources

{ match request { Request::DummyRequest => Ok(Reply::DummyReply), - Request::Agree(request) => match request.mechanism { - Mechanism::P256 => mechanisms::P256::agree(&mut keystore(self, ctx)?, request), - 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 = "crypto-client-attest")] Request::Attest(request) => { @@ -196,68 +229,25 @@ impl ServiceResources

{ #[cfg(not(feature = "crypto-client-attest"))] Request::Attest(_) => Err(Error::RequestNotAvailable), - Request::Decrypt(request) => match request.mechanism { - Mechanism::Aes256Cbc => { - mechanisms::Aes256Cbc::decrypt(&mut keystore(self, ctx)?, request) - } - Mechanism::Chacha8Poly1305 => { - mechanisms::Chacha8Poly1305::decrypt(&mut keystore(self, ctx)?, request) - } - 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), - Request::DeriveKey(request) => match request.mechanism { - Mechanism::HmacBlake2s => { - mechanisms::HmacBlake2s::derive_key(&mut keystore(self, ctx)?, request) - } - Mechanism::HmacSha1 => { - mechanisms::HmacSha1::derive_key(&mut keystore(self, ctx)?, request) - } - Mechanism::HmacSha256 => { - mechanisms::HmacSha256::derive_key(&mut keystore(self, ctx)?, request) - } - Mechanism::HmacSha512 => { - mechanisms::HmacSha512::derive_key(&mut keystore(self, ctx)?, request) - } - Mechanism::Ed255 => { - mechanisms::Ed255::derive_key(&mut keystore(self, ctx)?, request) - } - Mechanism::P256 => mechanisms::P256::derive_key(&mut keystore(self, ctx)?, request), - Mechanism::Sha256 => { - mechanisms::Sha256::derive_key(&mut keystore(self, ctx)?, request) - } - 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), - Request::DeserializeKey(request) => match request.mechanism { - Mechanism::Ed255 => { - mechanisms::Ed255::deserialize_key(&mut keystore(self, ctx)?, request) - } - Mechanism::P256 => { - mechanisms::P256::deserialize_key(&mut keystore(self, ctx)?, request) - } - 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), - Request::Encrypt(request) => match request.mechanism { - Mechanism::Aes256Cbc => { - mechanisms::Aes256Cbc::encrypt(&mut keystore(self, ctx)?, request) - } - Mechanism::Chacha8Poly1305 => { - mechanisms::Chacha8Poly1305::encrypt(&mut keystore(self, ctx)?, request) - } - 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), Request::Delete(request) => { let success = keystore(self, ctx)?.delete_key(&request.key); @@ -274,31 +264,15 @@ impl ServiceResources

{ Ok(Reply::DeleteAllKeys(reply::DeleteAllKeys { count })) } - Request::Exists(request) => match request.mechanism { - Mechanism::Ed255 => mechanisms::Ed255::exists(&mut keystore(self, ctx)?, request), - Mechanism::P256 => mechanisms::P256::exists(&mut keystore(self, ctx)?, request), - Mechanism::Totp => mechanisms::Totp::exists(&mut keystore(self, ctx)?, request), - 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), - Request::GenerateKey(request) => match request.mechanism { - Mechanism::Chacha8Poly1305 => { - mechanisms::Chacha8Poly1305::generate_key(&mut keystore(self, ctx)?, request) - } - Mechanism::Ed255 => { - mechanisms::Ed255::generate_key(&mut keystore(self, ctx)?, request) - } - Mechanism::P256 => { - mechanisms::P256::generate_key(&mut keystore(self, ctx)?, request) - } - 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), Request::GenerateSecretKey(request) => { let mut secret_key = MediumData::new(); @@ -311,7 +285,7 @@ impl ServiceResources

{ let key_id = keystore.store_key( request.attributes.persistence, key::Secrecy::Secret, - key::Kind::Symmetric(size), + key::Kind::Symmetric(size).into(), &secret_key[..size], )?; Ok(Reply::GenerateSecretKey(reply::GenerateSecretKey { @@ -320,34 +294,16 @@ impl ServiceResources

{ } // deprecated - Request::UnsafeInjectKey(request) => match request.mechanism { - Mechanism::P256 => { - mechanisms::P256::unsafe_inject_key(&mut keystore(self, ctx)?, request) - } - Mechanism::X255 => { - mechanisms::X255::unsafe_inject_key(&mut keystore(self, ctx)?, request) - } - Mechanism::Ed255 => { - mechanisms::Ed255::unsafe_inject_key(&mut keystore(self, ctx)?, request) - } - Mechanism::SharedSecret => { - mechanisms::SharedSecret::unsafe_inject_key(&mut keystore(self, ctx)?, request) - } - Mechanism::Aes256Cbc => { - mechanisms::Aes256Cbc::unsafe_inject_key(&mut keystore(self, ctx)?, request) - } - 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), Request::UnsafeInjectSharedKey(request) => { let key_id = keystore(self, ctx)?.store_key( request.location, key::Secrecy::Secret, - key::Kind::Shared(request.raw_key.len()), + key::Kind::Shared(request.raw_key.len()).into(), &request.raw_key, )?; @@ -356,11 +312,10 @@ impl ServiceResources

{ })) } - Request::Hash(request) => match request.mechanism { - 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), Request::LocateFile(request) => { let path = filestore.locate_file( @@ -531,76 +486,35 @@ impl ServiceResources

{ } } - Request::SerializeKey(request) => match request.mechanism { - Mechanism::Ed255 => { - mechanisms::Ed255::serialize_key(&mut keystore(self, ctx)?, request) - } - Mechanism::P256 => { - mechanisms::P256::serialize_key(&mut keystore(self, ctx)?, request) - } - Mechanism::X255 => { - mechanisms::X255::serialize_key(&mut keystore(self, ctx)?, request) - } - 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), - Request::Sign(request) => match request.mechanism { - Mechanism::Ed255 => mechanisms::Ed255::sign(&mut keystore(self, ctx)?, request), - Mechanism::HmacBlake2s => { - mechanisms::HmacBlake2s::sign(&mut keystore(self, ctx)?, request) - } - Mechanism::HmacSha1 => { - mechanisms::HmacSha1::sign(&mut keystore(self, ctx)?, request) - } - Mechanism::HmacSha256 => { - mechanisms::HmacSha256::sign(&mut keystore(self, ctx)?, request) - } - Mechanism::HmacSha512 => { - mechanisms::HmacSha512::sign(&mut keystore(self, ctx)?, request) - } - Mechanism::P256 => mechanisms::P256::sign(&mut keystore(self, ctx)?, request), - Mechanism::P256Prehashed => { - mechanisms::P256Prehashed::sign(&mut keystore(self, ctx)?, request) - } - 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), Request::WriteFile(request) => { filestore.write(&request.path, request.location, &request.data)?; Ok(Reply::WriteFile(reply::WriteFile {})) } - Request::UnwrapKey(request) => match request.mechanism { - 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), - Request::Verify(request) => match request.mechanism { - Mechanism::Ed255 => mechanisms::Ed255::verify(&mut keystore(self, ctx)?, request), - 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), - Request::WrapKey(request) => match request.mechanism { - Mechanism::Aes256Cbc => { - mechanisms::Aes256Cbc::wrap_key(&mut keystore(self, ctx)?, request) - } - 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), Request::RequestUserConsent(request) => { // assert_eq!(request.level, consent::Level::Normal); diff --git a/src/service/attest.rs b/src/service/attest.rs index b345390c6d4..dfe87e7ade9 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/store/keystore.rs b/src/store/keystore.rs index 01f12e22686..7fe5bfa8b26 100644 --- a/src/store/keystore.rs +++ b/src/store/keystore.rs @@ -42,7 +42,7 @@ pub trait Keystore { &mut self, location: Location, secrecy: key::Secrecy, - info: impl Into, + info: key::Info, material: &[u8], ) -> Result; fn exists_key(&self, secrecy: key::Secrecy, kind: Option, id: &KeyId) -> bool; @@ -101,12 +101,11 @@ impl Keystore for ClientKeystore { &mut self, location: Location, secrecy: key::Secrecy, - info: impl Into, + mut info: key::Info, material: &[u8], ) -> Result { // info_now!("storing {:?} -> {:?}", &key_kind, location); - let mut info: key::Info = info.into(); if secrecy == key::Secrecy::Secret { info.flags |= key::Flags::SENSITIVE; }