From c2438370ec9794e176b353ed361fc75d06681765 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sosth=C3=A8ne=20Gu=C3=A9don?= Date: Fri, 25 Aug 2023 11:10:23 +0200 Subject: [PATCH] Add `Clear` syscall This syscall does the same as `delete` for a key. The only difference is that it is designed to allow re-import of the key if it was exported with `WrapKey`. With the core trussed backend this does not change anything, as nothing is needed to allow the re-import. However the same mechansim in the SE050 work differently, and being able to differenciate permanent deletion and deletion with intent to re-import is crucial. --- src/api.rs | 11 +++++++++++ src/client.rs | 12 ++++++++++++ src/key.rs | 3 +++ src/service.rs | 5 +++++ src/store/keystore.rs | 19 +++++++++++++++++++ 5 files changed, 50 insertions(+) diff --git a/src/api.rs b/src/api.rs index 0aa59dce6db..40824a1ab61 100644 --- a/src/api.rs +++ b/src/api.rs @@ -31,6 +31,11 @@ generate_enums! { DeserializeKey: 5 Encrypt: 6 Delete: 7 + // Clear private data from the key + // This will not always delete all metadata from storage. + // Other backends can retain metadata required for `unwrap_key` to work properly + // and delete this metadata only once `delete` is called. + Clear: 63 DeleteAllKeys: 25 Exists: 8 // DeriveKeypair: 3 @@ -150,6 +155,9 @@ pub mod request { Delete: - key: KeyId + Clear: + - key: KeyId + DeleteAllKeys: - location: Location @@ -383,6 +391,9 @@ pub mod reply { Delete: - success: bool + Clear: + - success: bool + DeleteAllKeys: - count: usize diff --git a/src/client.rs b/src/client.rs index ce0b950b479..1ff8c1a498d 100644 --- a/src/client.rs +++ b/src/client.rs @@ -347,6 +347,18 @@ pub trait CryptoClient: PollClient { }) } + /// Clear private data from the key + /// + /// This will not delete all metadata from storage. + /// Other backends can retain metadata required for `unwrap_key` to work properly + /// and delete this metadata only once `delete` is called. + fn clear(&mut self, key: KeyId) -> ClientResult<'_, reply::Delete, Self> { + self.request(request::Delete { + key, + // mechanism, + }) + } + /// Skips deleting read-only / manufacture keys (currently, "low ID"). fn delete_all(&mut self, location: Location) -> ClientResult<'_, reply::DeleteAllKeys, Self> { self.request(request::DeleteAllKeys { location }) diff --git a/src/key.rs b/src/key.rs index ccda75c204a..ebb460a7496 100644 --- a/src/key.rs +++ b/src/key.rs @@ -69,6 +69,8 @@ pub enum Kind { Ed255, P256, X255, + /// Key that was `cleared` + Tombstone, } bitflags::bitflags! { @@ -156,6 +158,7 @@ impl Kind { Kind::Rsa2048 => 7, Kind::Rsa3072 => 8, Kind::Rsa4096 => 9, + Kind::Tombstone => 10, } } diff --git a/src/service.rs b/src/service.rs index ecbdbf16abc..668639f1221 100644 --- a/src/service.rs +++ b/src/service.rs @@ -225,6 +225,11 @@ impl ServiceResources

{ Ok(Reply::Delete(reply::Delete { success } )) }, + Request::Clear(request) => { + let success = keystore.clear_key(&request.key); + Ok(Reply::Clear(reply::Clear { success } )) + }, + Request::DeleteAllKeys(request) => { let count = keystore.delete_all(request.location)?; Ok(Reply::DeleteAllKeys(reply::DeleteAllKeys { count } )) diff --git a/src/store/keystore.rs b/src/store/keystore.rs index 4241ec5337a..5f630e2db28 100644 --- a/src/store/keystore.rs +++ b/src/store/keystore.rs @@ -52,6 +52,7 @@ pub trait Keystore { /// Return Header of key, if it exists fn key_info(&self, secrecy: key::Secrecy, id: &KeyId) -> Option; fn delete_key(&self, id: &KeyId) -> bool; + fn clear_key(&self, id: &KeyId) -> bool; fn delete_all(&self, location: Location) -> Result; fn load_key( &self, @@ -152,6 +153,24 @@ impl Keystore for ClientKeystore { }) } + fn clear_key(&self, id: &KeyId) -> bool { + let secrecies = [key::Secrecy::Secret, key::Secrecy::Public]; + + secrecies + .into_iter() + .map(|secrecy| { + // info_now!("loading {:?}", &key_kind); + let path = self.key_path(secrecy, id); + + let location = Location::Volatile; + if !path.exists(self.store.vfs()) { + return Err(Error::InvalidPath); + } + self.overwrite_key(location, secrecy, key::Kind::Tombstone, id, &[]) + }) + .any(|r| r.is_ok()) + } + /// TODO: This uses the predicate "filename.len() >= 4" /// Be more principled :) fn delete_all(&self, location: Location) -> Result {