Add reading of large data objects

This commit is contained in:
Sosthène Guédon
2023-04-13 10:17:38 +02:00
parent 2af596d466
commit e249f2f2c6
3 changed files with 72 additions and 9 deletions
+1 -1
View File
@@ -74,7 +74,7 @@ log-warn = []
log-error = []
[patch.crates-io]
trussed = { git = "https://github.com/Nitrokey/trussed", tag = "v0.1.0-nitrokey.8"}
trussed = { git = "https://github.com/sosthene-nitrokey/trussed", rev = "25ae084251b76bacfa8919eb8"}
trussed-auth = { git = "https://github.com/trussed-dev/trussed-auth", tag = "v0.2.1"}
littlefs2 = { git = "https://github.com/Nitrokey/littlefs2", tag = "v0.3.2-nitrokey-2" }
+9 -4
View File
@@ -910,10 +910,15 @@ impl<'a, T: trussed::Client + AuthClient + trussed::client::Ed255> LoadedAuthent
let offset = reply.len();
match container {
Container::KeyHistoryObject => self.get_key_history_object(reply.lend())?,
_ => match ContainerStorage(container).load(self.trussed, self.options.storage)? {
Some(data) => reply.expand(&data)?,
None => return Err(Status::NotFound),
},
_ => {
if !ContainerStorage(container).load(
self.trussed,
self.options.storage,
reply.lend(),
)? {
return Err(Status::NotFound);
}
}
}
reply.prepend_len(offset)?;
+62 -4
View File
@@ -8,6 +8,7 @@ use flexiber::EncodableHeapless;
use heapless::Vec;
use heapless_bytes::Bytes;
use iso7816::Status;
use trussed::types::OpenSeekFrom;
use trussed::{
api::reply::Metadata,
config::MAX_MESSAGE_LENGTH,
@@ -17,6 +18,7 @@ use trussed::{
use trussed_auth::AuthClient;
use crate::piv_types::CardHolderUniqueIdentifier;
use crate::reply::Reply;
use crate::{constants::*, piv_types::AsymmetricAlgorithms};
use crate::{
container::{AsymmetricKeyReference, Container, ReadAccessRule, SecurityCondition},
@@ -617,6 +619,53 @@ fn load_if_exists(
}
}
/// Returns false if the file does not exist
fn load_if_exists_streaming<const R: usize>(
client: &mut impl trussed::Client,
location: Location,
path: &PathBuf,
mut buffer: Reply<'_, R>,
) -> Result<bool, Status> {
let mut read_len = 0;
let file_len;
match try_syscall!(client.read_file_chunk(location, path.clone(), OpenSeekFrom::Start(0))) {
Ok(r) => {
read_len += r.data.len();
file_len = r.len;
buffer.expand(&r.data)?;
}
Err(_) => match try_syscall!(client.entry_metadata(location, path.clone())) {
Ok(Metadata { metadata: None }) => return Ok(false),
Ok(Metadata {
metadata: Some(_metadata),
}) => {
error!("File {path} exists but couldn't be read: {_metadata:?}");
return Err(Status::UnspecifiedPersistentExecutionError);
}
Err(_err) => {
error!("File {path} couldn't be read: {_err:?}");
return Err(Status::UnspecifiedPersistentExecutionError);
}
},
}
while read_len < file_len {
match try_syscall!(client.read_file_chunk(
location,
path.clone(),
OpenSeekFrom::Start(read_len as u32)
)) {
Ok(r) => {
read_len += r.data.len();
buffer.expand(&r.data)?;
}
Err(_err) => error!("Failed to read chunk: {:?}", _err),
}
}
Ok(true)
}
#[derive(Clone, Copy, Debug)]
pub struct ContainerStorage(pub Container);
@@ -703,13 +752,22 @@ impl ContainerStorage {
}
}
pub fn load(
pub fn load<const R: usize>(
self,
client: &mut impl trussed::Client,
storage: Location,
) -> Result<Option<Bytes<MAX_MESSAGE_LENGTH>>, Status> {
load_if_exists(client, storage, &self.path())
.map(|data| data.or_else(|| self.default().map(Bytes::from)))
mut reply: Reply<'_, R>,
) -> Result<bool, Status> {
if load_if_exists_streaming(client, storage, &self.path(), reply.lend())? {
return Ok(true);
}
if let Some(data) = self.default() {
reply.expand(&data)?;
Ok(true)
} else {
Ok(false)
}
}
pub fn save(