Skip to content

Commit

Permalink
Add Clear syscall
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
sosthene-nitrokey committed Aug 25, 2023
1 parent f3c95ab commit c243837
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 0 deletions.
11 changes: 11 additions & 0 deletions src/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -150,6 +155,9 @@ pub mod request {
Delete:
- key: KeyId

Clear:
- key: KeyId

DeleteAllKeys:
- location: Location

Expand Down Expand Up @@ -383,6 +391,9 @@ pub mod reply {
Delete:
- success: bool

Clear:
- success: bool

DeleteAllKeys:
- count: usize

Expand Down
12 changes: 12 additions & 0 deletions src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 })
Expand Down
3 changes: 3 additions & 0 deletions src/key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ pub enum Kind {
Ed255,
P256,
X255,
/// Key that was `cleared`
Tombstone,
}

bitflags::bitflags! {
Expand Down Expand Up @@ -156,6 +158,7 @@ impl Kind {
Kind::Rsa2048 => 7,
Kind::Rsa3072 => 8,
Kind::Rsa4096 => 9,
Kind::Tombstone => 10,
}
}

Expand Down
5 changes: 5 additions & 0 deletions src/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,11 @@ impl<P: Platform> ServiceResources<P> {
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 } ))
Expand Down
19 changes: 19 additions & 0 deletions src/store/keystore.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ pub trait Keystore {
/// Return Header of key, if it exists
fn key_info(&self, secrecy: key::Secrecy, id: &KeyId) -> Option<key::Info>;
fn delete_key(&self, id: &KeyId) -> bool;
fn clear_key(&self, id: &KeyId) -> bool;
fn delete_all(&self, location: Location) -> Result<usize>;
fn load_key(
&self,
Expand Down Expand Up @@ -152,6 +153,24 @@ impl<S: Store> Keystore for ClientKeystore<S> {
})
}

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<usize> {
Expand Down

0 comments on commit c243837

Please sign in to comment.