diff --git a/Cargo.toml b/Cargo.toml index 0ee0af5..869fa0b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,6 +15,7 @@ keywords = ["trussed", "rsa", "no-std"] delog = "0.1.6" heapless-bytes = "0.3.0" num-bigint-dig = { version = "0.8.2", default-features = false } +postcard = { version = "0.7", default-features = false, features = ["heapless"] } rsa = { version = "0.8.1", default-features = false, features = ["sha2"]} serde = { version = "1.0.152", default-features = false, features = ["derive"] } @@ -30,7 +31,7 @@ rand = "0.8.5" [features] -virt = ["std","trussed/virt"] +virt = ["std", "trussed/virt"] std = [] # Add support for raw RSA keys diff --git a/src/crypto_traits.rs b/src/crypto_traits.rs index 42c173f..dcf844e 100644 --- a/src/crypto_traits.rs +++ b/src/crypto_traits.rs @@ -7,7 +7,6 @@ use trussed::{ request::{DeserializeKey, UnsafeInjectKey}, }, client::{ClientError, ClientResult, CryptoClient}, - postcard_serialize_bytes, types::{ KeyId, KeySerialization, Location, Mechanism, SignatureSerialization, StorageAttributes, }, @@ -47,17 +46,17 @@ pub trait Rsa2048Pkcs1v15: CryptoClient { /// Serializes an RSA 2048 bit key. /// /// The resulting [`serialized_key`](trussed::api::reply::SerializeKey::serialized_key) contains a buffer of the parts of the key - /// as a postcard-serialized [`RsaPublicParts`](crate::RsaPublicParts): + /// as a serialized [`RsaPublicParts`](crate::RsaPublicParts): /// ``` ///# #[cfg(feature = "virt")] ///# { ///# use trussed_rsa_alloc::*; - ///# use trussed::{postcard_deserialize,syscall,types::Location::{Volatile,Internal}}; + ///# use trussed::{syscall,types::Location::{Volatile,Internal}}; ///# virt::with_ram_client("rsa tests", |mut client| { ///# let sk = syscall!(client.generate_rsa2048pkcs_private_key(Internal)).key; ///# let pk = syscall!(client.derive_rsa2048pkcs_public_key(sk, Volatile)).key; /// let serialized_key = syscall!(client.serialize_rsa2048_key(pk)).serialized_key; - /// let public_key: RsaPublicParts = postcard_deserialize(&serialized_key).unwrap(); + /// let public_key = RsaPublicParts::deserialize(&serialized_key).unwrap(); ///# }) ///# } ///``` @@ -72,7 +71,7 @@ pub trait Rsa2048Pkcs1v15: CryptoClient { ) -> ClientResult<'c, reply::DeserializeKey, Self> { self.request(DeserializeKey { mechanism: Mechanism::Rsa2048Pkcs1v15, - serialized_key: postcard_serialize_bytes(&key_parts).map_err(|_err| { + serialized_key: key_parts.serialize().map_err(|_err| { error!("Failed to serialize key parts: {:?}", _err); ClientError::DataTooLarge })?, @@ -116,7 +115,7 @@ pub trait Rsa2048Pkcs1v15: CryptoClient { ) -> ClientResult<'c, reply::UnsafeInjectKey, Self> { self.request(UnsafeInjectKey { mechanism: Mechanism::Rsa2048Pkcs1v15, - raw_key: postcard_serialize_bytes(&key_parts).map_err(|_err| { + raw_key: key_parts.serialize().map_err(|_err| { error!("Failed to serialize key parts: {:?}", _err); ClientError::DataTooLarge })?, @@ -166,17 +165,17 @@ pub trait Rsa3072Pkcs1v15: CryptoClient { /// Serializes an RSA 3072 bit key. /// /// The resulting [`serialized_key`](trussed::api::reply::SerializeKey::serialized_key) contains a buffer of the parts of the key - /// as a postcard-serialized [`RsaPublicParts`](crate::RsaPublicParts): + /// as a serialized [`RsaPublicParts`](crate::RsaPublicParts): /// ``` ///# #[cfg(feature = "virt")] ///# { ///# use trussed_rsa_alloc::*; - ///# use trussed::{postcard_deserialize,syscall,types::Location::{Volatile,Internal}}; + ///# use trussed::{syscall,types::Location::{Volatile,Internal}}; ///# virt::with_ram_client("rsa tests", |mut client| { ///# let sk = syscall!(client.generate_rsa3072pkcs_private_key(Internal)).key; ///# let pk = syscall!(client.derive_rsa3072pkcs_public_key(sk, Volatile)).key; /// let serialized_key = syscall!(client.serialize_rsa3072_key(pk)).serialized_key; - /// let public_key: RsaPublicParts = postcard_deserialize(&serialized_key).unwrap(); + /// let public_key = RsaPublicParts::deserialize(&serialized_key).unwrap(); ///# }) ///# } ///``` @@ -191,7 +190,7 @@ pub trait Rsa3072Pkcs1v15: CryptoClient { ) -> ClientResult<'c, reply::DeserializeKey, Self> { self.request(DeserializeKey { mechanism: Mechanism::Rsa3072Pkcs1v15, - serialized_key: postcard_serialize_bytes(&key_parts).map_err(|_err| { + serialized_key: key_parts.serialize().map_err(|_err| { error!("Failed to serialize key parts: {:?}", _err); ClientError::DataTooLarge })?, @@ -235,7 +234,7 @@ pub trait Rsa3072Pkcs1v15: CryptoClient { ) -> ClientResult<'c, reply::UnsafeInjectKey, Self> { self.request(UnsafeInjectKey { mechanism: Mechanism::Rsa3072Pkcs1v15, - raw_key: postcard_serialize_bytes(&key_parts).map_err(|_err| { + raw_key: key_parts.serialize().map_err(|_err| { error!("Failed to serialize key parts: {:?}", _err); ClientError::DataTooLarge })?, @@ -285,17 +284,17 @@ pub trait Rsa4096Pkcs1v15: CryptoClient { /// Serializes an RSA 4096 bit key. /// /// The resulting [`serialized_key`](trussed::api::reply::SerializeKey::serialized_key) contains a buffer of the parts of the key - /// as a postcard-serialized [`RsaPublicParts`](crate::RsaPublicParts): + /// as a serialized [`RsaPublicParts`](crate::RsaPublicParts): /// ``` ///# #[cfg(feature = "virt")] ///# { ///# use trussed_rsa_alloc::*; - ///# use trussed::{postcard_deserialize,syscall,types::Location::{Volatile,Internal}}; + ///# use trussed::{syscall,types::Location::{Volatile,Internal}}; ///# virt::with_ram_client("rsa tests", |mut client| { ///# let sk = syscall!(client.generate_rsa4096pkcs_private_key(Internal)).key; ///# let pk = syscall!(client.derive_rsa4096pkcs_public_key(sk, Volatile)).key; /// let serialized_key = syscall!(client.serialize_rsa4096_key(pk)).serialized_key; - /// let public_key: RsaPublicParts = postcard_deserialize(&serialized_key).unwrap(); + /// let public_key = RsaPublicParts::deserialize(&serialized_key).unwrap(); ///# }) ///# } ///``` @@ -310,7 +309,7 @@ pub trait Rsa4096Pkcs1v15: CryptoClient { ) -> ClientResult<'c, reply::DeserializeKey, Self> { self.request(DeserializeKey { mechanism: Mechanism::Rsa4096Pkcs1v15, - serialized_key: postcard_serialize_bytes(&key_parts).map_err(|_err| { + serialized_key: key_parts.serialize().map_err(|_err| { error!("Failed to serialize key parts: {:?}", _err); ClientError::DataTooLarge })?, @@ -354,7 +353,7 @@ pub trait Rsa4096Pkcs1v15: CryptoClient { ) -> ClientResult<'c, reply::UnsafeInjectKey, Self> { self.request(UnsafeInjectKey { mechanism: Mechanism::Rsa4096Pkcs1v15, - raw_key: postcard_serialize_bytes(&key_parts).map_err(|_err| { + raw_key: key_parts.serialize().map_err(|_err| { error!("Failed to serialize key parts: {:?}", _err); ClientError::DataTooLarge })?, diff --git a/src/lib.rs b/src/lib.rs index c52559a..c2d04b6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -19,7 +19,6 @@ use trussed::{ backend::Backend, key, platform::Platform, - postcard_deserialize, postcard_serialize_bytes, service::{Keystore, ServiceResources}, types::{ CoreContext, KeyId, KeySerialization, Mechanism, Message, Signature, SignatureSerialization, @@ -124,7 +123,7 @@ fn deserialize_parts_key( bits: usize, kind: key::Kind, ) -> Result { - let parsed: RsaPublicParts = postcard_deserialize(&request.serialized_key).map_err(|_err| { + let parsed = RsaPublicParts::deserialize(&request.serialized_key).map_err(|_err| { error!("Failed to deserialize key parts"); Error::InvalidSerializedKey })?; @@ -187,7 +186,7 @@ fn serialize_key( DecodePublicKey::from_public_key_der(&pub_key_der).expect("Failed to parse key"); let e = &key.e().to_bytes_be(); let n = &key.n().to_bytes_be(); - postcard_serialize_bytes(&RsaPublicParts { e, n }).map_err(|_err| { + RsaPublicParts { e, n }.serialize().map_err(|_err| { error!("Failed to serialize public key {_err:?}"); Error::InternalError })? diff --git a/src/types.rs b/src/types.rs index 82b3d83..4e252fa 100644 --- a/src/types.rs +++ b/src/types.rs @@ -1,9 +1,36 @@ // Copyright (C) Nitrokey GmbH // SPDX-License-Identifier: Apache-2.0 or MIT +use heapless_bytes::Bytes; use serde::{Deserialize, Serialize}; +use trussed::config::MAX_KEY_MATERIAL_LENGTH; + +/// Error type +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] +#[non_exhaustive] +pub enum ErrorKind { + /// Error occured during serialization + SerializeBufferFull, + /// Serialization failed. This indicates an internal error. + /// If encountered, please report + SerializeCustom, + /// The structure failed to deserialize + Deseralization, +} + +/// Error during serialization. +/// This means that the serialization failed, likely +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] +pub struct Error { + kind: ErrorKind, +} /// Structure containing the public part of an RSA key +/// +/// Given how Trussed extensions are implemented, this structure cannot be sent as-is to the backend, +/// and is instead sent as a byte array. +/// You can use [`serialize`](RsaPublicParts::serialize) and [`deserialize`](RsaPublicParts::deserialize) functions +/// to convert to and from tha byte array format #[derive(Serialize, Deserialize)] pub struct RsaPublicParts<'d> { /// big-endian integer representing the modulus of an RSA key @@ -12,6 +39,32 @@ pub struct RsaPublicParts<'d> { pub e: &'d [u8], } +impl<'d> RsaPublicParts<'d> { + pub fn serialize(&self) -> Result, Error> { + use postcard::Error as PError; + let vec = postcard::to_vec(self).map_err(|err| match err { + PError::SerializeBufferFull => Error { + kind: ErrorKind::SerializeBufferFull, + }, + _ => Error { + kind: ErrorKind::SerializeCustom, + }, + })?; + Ok(Bytes::from(vec)) + } + pub fn deserialize(data: &'d [u8]) -> Result { + postcard::from_bytes(data).map_err(|_err| Error { + kind: ErrorKind::Deseralization, + }) + } +} + +/// Format for private RSA key import +/// +/// Given how Trussed extensions are implemented, this structure cannot be sent as-is to the backend, +/// and is instead sent as a byte array. +/// You can use [`serialize`](RsaImportFormat::serialize) and [`deserialize`](RsaImportFormat::deserialize) functions +/// to convert to and from tha byte array format #[derive(Debug, Deserialize, Serialize)] pub struct RsaImportFormat<'d> { /// big-endian integer representing the modulus of an RSA key @@ -21,3 +74,23 @@ pub struct RsaImportFormat<'d> { /// big-endian integer representing the second prime of a private RSA key pub q: &'d [u8], } + +impl<'d> RsaImportFormat<'d> { + pub fn serialize(&self) -> Result, Error> { + use postcard::Error as PError; + let vec = postcard::to_vec(self).map_err(|err| match err { + PError::SerializeBufferFull => Error { + kind: ErrorKind::SerializeBufferFull, + }, + _ => Error { + kind: ErrorKind::SerializeCustom, + }, + })?; + Ok(Bytes::from(vec)) + } + pub fn deserialize(data: &'d [u8]) -> Result { + postcard::from_bytes(data).map_err(|_err| Error { + kind: ErrorKind::Deseralization, + }) + } +} diff --git a/tests/rsa2048.rs b/tests/rsa2048.rs index bd688c0..9e356af 100644 --- a/tests/rsa2048.rs +++ b/tests/rsa2048.rs @@ -6,14 +6,12 @@ use rsa::sha2::Sha256; use rsa::{Pkcs1v15Encrypt, Pkcs1v15Sign, PublicKeyParts}; use trussed::client::CryptoClient; -use trussed::postcard_deserialize; use trussed::syscall; use trussed::types::KeyId; use trussed::types::KeySerialization; use trussed::types::Location::*; use trussed::types::Mechanism; use trussed::types::StorageAttributes; -use trussed::Bytes; use trussed_rsa_alloc::*; @@ -73,7 +71,7 @@ fn rsa2048_deserialize_key() { let sk = syscall!(client.generate_rsa2048pkcs_private_key(Internal)).key; let pk = syscall!(client.derive_rsa2048pkcs_public_key(sk, Volatile)).key; let serialized_key = syscall!(client.serialize_rsa2048_key(pk)).serialized_key; - let public_key = postcard_deserialize(&serialized_key).unwrap(); + let public_key = RsaPublicParts::deserialize(&serialized_key).unwrap(); let location = StorageAttributes::new().set_persistence(Volatile); let deserialized_key_id = @@ -91,7 +89,7 @@ fn rsa2048pkcs_encrypt_decrypt() { let message = [1u8, 2u8, 3u8]; let pk = syscall!(client.derive_rsa2048pkcs_public_key(sk, Volatile)).key; let rs_pks_buffer = syscall!(client.serialize_rsa2048_key(pk)).serialized_key; - let parsed: RsaPublicParts = postcard_deserialize(&rs_pks_buffer).unwrap(); + let parsed = RsaPublicParts::deserialize(&rs_pks_buffer).unwrap(); let pubkey = rsa::RsaPublicKey::new_unchecked( BigUint::from_bytes_be(parsed.n), BigUint::from_bytes_be(parsed.e), @@ -150,7 +148,7 @@ fn rsa2048pkcs_inject() { p: &p1, q: &p2, }; - let data: Bytes<2048> = trussed::postcard_serialize_bytes(&request).unwrap(); + let data = request.serialize().unwrap(); let sk = syscall!(client.unsafe_inject_key( Mechanism::Rsa2048Pkcs1v15, &data, diff --git a/tests/rsa3072.rs b/tests/rsa3072.rs index 6484b6d..d20276b 100644 --- a/tests/rsa3072.rs +++ b/tests/rsa3072.rs @@ -6,14 +6,12 @@ use rsa::sha2::Sha384; use rsa::{Pkcs1v15Encrypt, Pkcs1v15Sign, PublicKeyParts}; use trussed::client::CryptoClient; -use trussed::postcard_deserialize; use trussed::syscall; use trussed::types::KeyId; use trussed::types::KeySerialization; use trussed::types::Location::*; use trussed::types::Mechanism; use trussed::types::StorageAttributes; -use trussed::Bytes; use trussed_rsa_alloc::*; @@ -73,7 +71,7 @@ fn rsa3072_deserialize_key() { let sk = syscall!(client.generate_rsa3072pkcs_private_key(Internal)).key; let pk = syscall!(client.derive_rsa3072pkcs_public_key(sk, Volatile)).key; let serialized_key = syscall!(client.serialize_rsa3072_key(pk)).serialized_key; - let public_key = postcard_deserialize(&serialized_key).unwrap(); + let public_key = RsaPublicParts::deserialize(&serialized_key).unwrap(); let location = StorageAttributes::new().set_persistence(Volatile); let deserialized_key_id = @@ -91,7 +89,7 @@ fn rsa3072pkcs_encrypt_decrypt() { let message = [1u8, 2u8, 3u8]; let pk = syscall!(client.derive_rsa3072pkcs_public_key(sk, Volatile)).key; let rs_pks_buffer = syscall!(client.serialize_rsa3072_key(pk)).serialized_key; - let parsed: RsaPublicParts = postcard_deserialize(&rs_pks_buffer).unwrap(); + let parsed = RsaPublicParts::deserialize(&rs_pks_buffer).unwrap(); let pubkey = rsa::RsaPublicKey::new_unchecked( BigUint::from_bytes_be(parsed.n), BigUint::from_bytes_be(parsed.e), @@ -152,7 +150,7 @@ fn rsa3072pkcs_inject() { p: &p1, q: &p2, }; - let data: Bytes<3072> = trussed::postcard_serialize_bytes(&request).unwrap(); + let data = request.serialize().unwrap(); let sk = syscall!(client.unsafe_inject_key( Mechanism::Rsa3072Pkcs1v15, &data, diff --git a/tests/rsa4096.rs b/tests/rsa4096.rs index e02c4e1..fb06ba1 100644 --- a/tests/rsa4096.rs +++ b/tests/rsa4096.rs @@ -6,14 +6,12 @@ use rsa::sha2::Sha512; use rsa::{Pkcs1v15Encrypt, Pkcs1v15Sign, PublicKeyParts}; use trussed::client::CryptoClient; -use trussed::postcard_deserialize; use trussed::syscall; use trussed::types::KeyId; use trussed::types::KeySerialization; use trussed::types::Location::*; use trussed::types::Mechanism; use trussed::types::StorageAttributes; -use trussed::Bytes; use trussed_rsa_alloc::*; @@ -73,7 +71,7 @@ fn rsa4096_deserialize_key() { let sk = syscall!(client.generate_rsa4096pkcs_private_key(Internal)).key; let pk = syscall!(client.derive_rsa4096pkcs_public_key(sk, Volatile)).key; let serialized_key = syscall!(client.serialize_rsa4096_key(pk)).serialized_key; - let public_key = postcard_deserialize(&serialized_key).unwrap(); + let public_key = RsaPublicParts::deserialize(&serialized_key).unwrap(); let location = StorageAttributes::new().set_persistence(Volatile); let deserialized_key_id = @@ -91,7 +89,7 @@ fn rsa4096pkcs_encrypt_decrypt() { let message = [1u8, 2u8, 3u8]; let pk = syscall!(client.derive_rsa4096pkcs_public_key(sk, Volatile)).key; let rs_pks_buffer = syscall!(client.serialize_rsa4096_key(pk)).serialized_key; - let parsed: RsaPublicParts = postcard_deserialize(&rs_pks_buffer).unwrap(); + let parsed = RsaPublicParts::deserialize(&rs_pks_buffer).unwrap(); let pubkey = rsa::RsaPublicKey::new_unchecked( BigUint::from_bytes_be(parsed.n), BigUint::from_bytes_be(parsed.e), @@ -152,7 +150,7 @@ fn rsa4096pkcs_inject() { p: &p1, q: &p2, }; - let data: Bytes<4096> = trussed::postcard_serialize_bytes(&request).unwrap(); + let data = request.serialize().unwrap(); let sk = syscall!(client.unsafe_inject_key( Mechanism::Rsa4096Pkcs1v15, &data,