Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 9 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -54,16 +54,18 @@ trussed-hpke = { version = "0.2.0", optional = true }
trussed-manage = { version = "0.2.1", optional = true }
trussed-wrap-key-to-file = { version = "0.2.0", optional = true }
trussed-fs-info = { version = "0.2.0", optional = true }
heapless = { version = "0.9.1", optional = true }
heapless-bytes = { version = "0.5.0", optional = true }

[dev-dependencies]
hex-literal = "0.4.0"
hmac = "0.12.0"
trussed = { version = "0.1.0", default-features = false, features = ["aes256-cbc", "crypto-client", "filesystem-client", "hmac-sha256", "virt", "x255"] }

[features]
default = []
default = ["chunked"]

chunked = ["trussed-chunked", "chacha20poly1305/stream"]
chunked = ["trussed-chunked", "chacha20poly1305/stream", "dep:heapless", "dep:heapless-bytes"]
hkdf = ["trussed-hkdf", "dep:hkdf", "dep:sha2"]
hpke = ["trussed-hpke", "dep:hkdf", "dep:sha2", "dep:hex-literal", "dep:aead", "dep:chacha20poly1305"]
manage = ["trussed-manage"]
Expand All @@ -83,7 +85,11 @@ log-warn = []
log-error = []

[patch.crates-io]
trussed = { git = "https://github.com/trussed-dev/trussed.git", rev = "ac106d63ab5e19021b0e37f0efb4313f8168a110" }
trussed = { git = "https://github.com/trussed-dev/trussed.git", rev = "1e7b09a983dc8ae64a7ad8401ce541a9a77e5939" }
trussed-core = { git = "https://github.com/trussed-dev/trussed.git", rev = "1e7b09a983dc8ae64a7ad8401ce541a9a77e5939"}
littlefs2 = { git = "https://github.com/trussed-dev/littlefs2.git", rev = "e9d3a1ca98f80e92cd20ee9b94707067810b9036" }
littlefs2-core = { git = "https://github.com/trussed-dev/littlefs2.git", rev = "e9d3a1ca98f80e92cd20ee9b94707067810b9036" }
littlefs2-sys = { git = "https://github.com/trussed-dev/littlefs2-sys", rev = "v0.3.1-nitrokey.1" }

trussed-chunked = { path = "extensions/chunked" }
trussed-hkdf = { path = "extensions/hkdf" }
Expand Down
2 changes: 1 addition & 1 deletion extensions/chunked/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,4 @@ license.workspace = true
[dependencies]
serde.workspace = true
serde-byte-array.workspace = true
trussed-core = { workspace = true, features = ["filesystem-client"] }
trussed-core = { workspace = true, features = ["filesystem-client"]}
4 changes: 2 additions & 2 deletions extensions/chunked/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ pub fn write_all(
user_attribute: Option<UserAttribute>,
encryption: Option<EncryptionData>,
) -> Result<(), Error> {
if let (Ok(msg), None) = (Message::from_slice(data), encryption) {
if let (Ok(msg), None) = (Message::try_from(data), encryption) {
// Fast path for small files
try_syscall!(client.write_file(location, path, msg, user_attribute))?;
Ok(())
Expand Down Expand Up @@ -63,7 +63,7 @@ fn write_chunked_inner(
let msg = Message::new();
let chunk_size = msg.capacity();
let chunks = data.chunks(chunk_size).map(|chunk| {
Message::from_slice(chunk).expect("Iteration over chunks yields maximum of chunk_size")
Message::try_from(chunk).expect("Iteration over chunks yields maximum of chunk_size")
});
if let Some(encryption_data) = encryption {
try_syscall!(client.start_encrypted_chunked_write(
Expand Down
2 changes: 1 addition & 1 deletion extensions/wrap-key-to-file/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@ license.workspace = true

[dependencies]
serde.workspace = true
trussed-core = { workspace = true, features = ["filesystem-client"] }
trussed-core.workspace = true
4 changes: 2 additions & 2 deletions extensions/wrap-key-to-file/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ pub trait WrapKeyToFileClient: ExtensionClient<WrapKeyToFileExtension> {
associated_data: &[u8],
) -> WrapKeyToFileResult<'_, reply::WrapKeyToFile, Self> {
let associated_data =
Bytes::from_slice(associated_data).map_err(|_| ClientError::DataTooLarge)?;
Bytes::try_from(associated_data).map_err(|_| ClientError::DataTooLarge)?;
self.extension(request::WrapKeyToFile {
mechanism,
wrapping_key,
Expand All @@ -180,7 +180,7 @@ pub trait WrapKeyToFileClient: ExtensionClient<WrapKeyToFileExtension> {
associated_data: &[u8],
) -> WrapKeyToFileResult<'_, reply::UnwrapKeyFromFile, Self> {
let associated_data =
Bytes::from_slice(associated_data).map_err(|_| ClientError::DataTooLarge)?;
Bytes::try_from(associated_data).map_err(|_| ClientError::DataTooLarge)?;
self.extension(request::UnwrapKeyFromFile {
mechanism,
key,
Expand Down
63 changes: 54 additions & 9 deletions src/chunked/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ mod store;
use store::OpenSeekFrom;

use chacha20poly1305::{
aead,
aead::stream::{DecryptorLE31, EncryptorLE31, Nonce as StreamNonce, StreamLE31},
ChaCha8Poly1305, KeyInit,
};
Expand All @@ -27,6 +28,38 @@ use crate::StagingContext;
const POLY1305_TAG_LEN: usize = 16;
const CHACHA8_KEY_LEN: usize = 32;

struct HeaplessBuffer<'a, LenT: heapless::LenType>(&'a mut heapless_bytes::BytesView<LenT>);

impl<'a, LenT: heapless::LenType, S: heapless_bytes::BytesStorage + ?Sized>
From<&'a mut heapless_bytes::BytesInner<LenT, S>> for HeaplessBuffer<'a, LenT>
{
fn from(value: &'a mut heapless_bytes::BytesInner<LenT, S>) -> Self {
Self(value.as_mut_view())
}
}

impl<'a, LenT: heapless::LenType> AsMut<[u8]> for HeaplessBuffer<'a, LenT> {
fn as_mut(&mut self) -> &mut [u8] {
self.0
}
}

impl<'a, LenT: heapless::LenType> AsRef<[u8]> for HeaplessBuffer<'a, LenT> {
fn as_ref(&self) -> &[u8] {
self.0
}
}

impl<'a, LenT: heapless::LenType> aead::Buffer for HeaplessBuffer<'a, LenT> {
fn extend_from_slice(&mut self, other: &[u8]) -> aead::Result<()> {
self.0.extend_from_slice(other).map_err(|_| aead::Error)
}

fn truncate(&mut self, len: usize) {
self.0.truncate(len);
}
}

#[derive(Debug)]
pub struct ChunkedReadState {
pub path: PathBuf,
Expand Down Expand Up @@ -209,7 +242,7 @@ impl ExtensionImpl<ChunkedExtension> for super::StagingBackend {
let nonce: Bytes<CHACHA8_STREAM_NONCE_LEN> =
filestore.read(&request.path, request.location)?;
let nonce: &StreamNonce<ChaCha8Poly1305, StreamLE31<ChaCha8Poly1305>> =
(&**nonce).into();
(&*nonce).into();
let aead = ChaCha8Poly1305::new((&*key.material).into());
let decryptor = DecryptorLE31::<ChaCha8Poly1305>::from_aead(aead, nonce);
backend_ctx.chunked_io_state =
Expand Down Expand Up @@ -263,10 +296,13 @@ fn write_chunk(
}
Some(ChunkedIoState::EncryptedWrite(ref mut write_state)) => {
let mut data =
Bytes::<{ MAX_MESSAGE_LENGTH + POLY1305_TAG_LEN }>::from_slice(data).unwrap();
Bytes::<{ MAX_MESSAGE_LENGTH + POLY1305_TAG_LEN }>::try_from(&**data).unwrap();
write_state
.encryptor
.encrypt_next_in_place(write_state.path.as_ref().as_bytes(), &mut *data)
.encrypt_next_in_place(
write_state.path.as_ref().as_bytes(),
&mut HeaplessBuffer::from(&mut data),
)
.map_err(|_err| {
error!("Failed to encrypt {:?}", _err);
Error::AeadError
Expand Down Expand Up @@ -303,10 +339,13 @@ fn write_last_chunk(
}
Some(ChunkedIoState::EncryptedWrite(write_state)) => {
let mut data =
Bytes::<{ MAX_MESSAGE_LENGTH + POLY1305_TAG_LEN }>::from_slice(data).unwrap();
Bytes::<{ MAX_MESSAGE_LENGTH + POLY1305_TAG_LEN }>::try_from(&**data).unwrap();
write_state
.encryptor
.encrypt_last_in_place(&[write_state.location as u8], &mut *data)
.encrypt_last_in_place(
&[write_state.location as u8],
&mut HeaplessBuffer::from(&mut data),
)
.map_err(|_err| {
error!("Failed to encrypt {:?}", _err);
Error::AeadError
Expand Down Expand Up @@ -354,12 +393,15 @@ fn read_encrypted_chunk(

read_state
.decryptor
.decrypt_last_in_place(&[read_state.location as u8], &mut *data)
.decrypt_last_in_place(
&[read_state.location as u8],
&mut HeaplessBuffer::from(&mut data),
)
.map_err(|_err| {
error!("Failed to decrypt {:?}", _err);
Error::AeadError
})?;
let data = Bytes::from_slice(&data).expect("decryptor removes the tag");
let data = Bytes::try_from(&*data).expect("decryptor removes the tag");
Ok(reply::ReadChunk {
data,
len: chunked_decrypted_len(len)?,
Expand All @@ -368,12 +410,15 @@ fn read_encrypted_chunk(
} else {
read_state
.decryptor
.decrypt_next_in_place(read_state.path.as_ref().as_bytes(), &mut *data)
.decrypt_next_in_place(
read_state.path.as_ref().as_bytes(),
&mut HeaplessBuffer::from(&mut data),
)
.map_err(|_err| {
error!("Failed to decrypt {:?}", _err);
Error::AeadError
})?;
let data = Bytes::from_slice(&data).expect("decryptor removes the tag");
let data = Bytes::try_from(&*data).expect("decryptor removes the tag");
Ok(reply::ReadChunk {
data,
len: chunked_decrypted_len(len)?,
Expand Down
2 changes: 1 addition & 1 deletion src/chunked/store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ pub fn fs_read_chunk<const N: usize>(
if length > contents.capacity() {
return Err(Error::FilesystemReadFailure);
}
contents.resize_default(length).unwrap();
contents.resize_zero(length).unwrap();
let file_len = fs
.open_file_and_then(path, &mut |file| {
file.seek(pos.into())?;
Expand Down
6 changes: 3 additions & 3 deletions src/hkdf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ fn get_mat<S: Store>(
warn!("Attempt to HKDF on a private key");
return Err(Error::MechanismInvalid);
}
Bytes::from_slice(&key_mat.material).map_err(|_| {
Bytes::try_from(&*key_mat.material).map_err(|_| {
warn!("Attempt to HKDF a too large key");
Error::InternalError
})?
Expand All @@ -65,7 +65,7 @@ fn extract<S: Store>(
.as_ref()
.map(|s| get_mat(s, keystore))
.transpose()?;
let salt_ref = salt.as_deref().map(|d| &**d);
let salt_ref = salt.as_deref();
let (prk, _) = Hkdf::<Sha256>::extract(salt_ref, &ikm);
assert_eq!(prk.len(), 256 / 8);
let key_id = keystore.store_key(
Expand All @@ -91,7 +91,7 @@ fn expand<S: Store>(
Error::InternalError
})?;
let mut okm = ShortData::new();
okm.resize_default(req.len).map_err(|_| {
okm.resize_zero(req.len).map_err(|_| {
error!("Attempt to run HKDF with too large output");
Error::WrongMessageLength
})?;
Expand Down
8 changes: 5 additions & 3 deletions src/hpke.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,8 @@ trait Aead:
TagSize = <ChaCha20Poly1305 as AeadCore>::TagSize,
>
{
// The AEAD_ID is the last 2 bytes of the X25519_HKDF_SHA256_SELF_HPKE_SUITE_ID
#[cfg_attr(not(test), allow(unused))]
const AEAD_ID: u16;
const X25519_HKDF_SHA256_SELF_HPKE_SUITE_ID: &'static [u8];
}
Expand Down Expand Up @@ -364,7 +366,7 @@ impl ExtensionImpl<HpkeExtension> for StagingBackend {
// TODO: need to check both secret and public keys
let serialized_key =
keystore.load_key(key::Secrecy::Secret, None, &req.key_to_seal)?;
let mut message = Message::from_slice(&serialized_key.serialize()).unwrap();
let mut message = Message::try_from(&*serialized_key.serialize()).unwrap();

let public_key = load_public_key(&req.public_key, keystore)?;

Expand All @@ -389,8 +391,8 @@ impl ExtensionImpl<HpkeExtension> for StagingBackend {
// TODO: need to check both secret and public keys
let serialized_key =
keystore.load_key(key::Secrecy::Secret, None, &req.key_to_seal)?;
let mut message = Bytes::<{ MAX_SERIALIZED_KEY_LENGTH + 32 + 16 }>::from_slice(
&serialized_key.serialize(),
let mut message = Bytes::<{ MAX_SERIALIZED_KEY_LENGTH + 32 + 16 }>::try_from(
&*serialized_key.serialize(),
)
.unwrap();

Expand Down
4 changes: 2 additions & 2 deletions src/wrap_key_to_file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,9 @@ fn wrap_key_to_file(

let serialized_key = keystore.load_key(Secrecy::Secret, None, &request.key)?;

let mut data = Bytes::<WRAPPED_TO_FILE_LEN>::from_slice(&serialized_key.serialize()).unwrap();
let mut data = Bytes::<WRAPPED_TO_FILE_LEN>::try_from(&*serialized_key.serialize()).unwrap();
let material_len = data.len();
data.resize_default(material_len + NONCE_LEN).unwrap();
data.resize_zero(material_len + NONCE_LEN).unwrap();
let (material, nonce) = data.split_at_mut(material_len);
keystore.rng().fill_bytes(nonce);
let nonce = (&*nonce).try_into().unwrap();
Expand Down
8 changes: 4 additions & 4 deletions tests/chunked.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ fn filesystem() {
.metadata
.is_none(),);

let data = Bytes::from_slice(b"test data").unwrap();
let data = Bytes::from(b"test data");
syscall!(client.write_file(
Location::Internal,
PathBuf::from(path!("test_file")),
Expand All @@ -82,9 +82,9 @@ fn filesystem() {
assert!(empty_data.data.is_empty());
assert_eq!(empty_data.len, data.len());

let large_data = Bytes::from_slice(&[0; 1024]).unwrap();
let large_data2 = Bytes::from_slice(&[1; 1024]).unwrap();
let more_data = Bytes::from_slice(&[2; 42]).unwrap();
let large_data = Bytes::from(&[0; 1024]);
let large_data2 = Bytes::from(&[1; 1024]);
let more_data = Bytes::from(&[2; 42]);
// ======== CHUNKED WRITES ========
syscall!(client.start_chunked_write(
Location::Internal,
Expand Down
6 changes: 3 additions & 3 deletions tests/encrypted-chunked.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,9 @@ fn encrypted_filesystem() {
.is_none(),
);

let large_data = Bytes::from_slice(&[0; 1024]).unwrap();
let large_data2 = Bytes::from_slice(&[1; 1024]).unwrap();
let more_data = Bytes::from_slice(&[2; 42]).unwrap();
let large_data = Bytes::from(&[0; 1024]);
let large_data2 = Bytes::from(&[1; 1024]);
let more_data = Bytes::from(&[2; 42]);
// ======== CHUNKED WRITES ========
syscall!(client.start_encrypted_chunked_write(
Location::Internal,
Expand Down
6 changes: 3 additions & 3 deletions tests/hkdf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,14 @@ fn hkdf() {
mac.update(MSG);
virt::with_client(StoreConfig::ram(), "hkdf_test", |mut client| {
let prk = syscall!(client.hkdf_extract(
Data(Bytes::from_slice(IKM).unwrap()),
Some(Data(Bytes::from_slice(SALT).unwrap())),
Data(Bytes::try_from(IKM).unwrap()),
Some(Data(Bytes::try_from(SALT).unwrap())),
Location::External,
))
.okm;
let expanded = syscall!(client.hkdf_expand(
prk,
Bytes::from_slice(INFO).unwrap(),
Bytes::try_from(INFO).unwrap(),
16,
Location::Volatile
))
Expand Down
14 changes: 7 additions & 7 deletions tests/hpke.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,9 @@ fn hpke_message() {
let public_key =
syscall!(client.derive_x255_public_key(secret_key, Location::Volatile)).key;

let pl = Bytes::from_slice(b"Plaintext").unwrap();
let aad = Bytes::from_slice(b"AAD").unwrap();
let info = Bytes::from_slice(b"INFO").unwrap();
let pl = Bytes::from(b"Plaintext");
let aad = Bytes::from(b"AAD");
let info = Bytes::from(b"INFO");
let seal = syscall!(client.hpke_seal(
public_key,
pl.clone(),
Expand All @@ -69,8 +69,8 @@ fn hpke_wrap_key() {

let key_to_wrap = syscall!(client.generate_secret_key(32, Location::Volatile)).key;

let aad = Bytes::from_slice(b"AAD").unwrap();
let info = Bytes::from_slice(b"INFO").unwrap();
let aad = Bytes::from(b"AAD");
let info = Bytes::from(b"INFO");
let seal =
syscall!(client.hpke_seal_key(public_key, key_to_wrap, aad.clone(), info.clone()));

Expand All @@ -96,8 +96,8 @@ fn hpke_wrap_key_to_file() {
let key_to_wrap = syscall!(client.generate_secret_key(32, Location::Volatile)).key;

let path = path!("WRAPPED_KEY");
let aad = Bytes::from_slice(b"AAD").unwrap();
let info = Bytes::from_slice(b"INFO").unwrap();
let aad = Bytes::from(b"AAD");
let info = Bytes::from(b"INFO");
syscall!(client.hpke_seal_key_to_file(
path.into(),
Location::Volatile,
Expand Down
Loading