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
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
default (5)
- Fix the inverted parsing of the touch requirement in SET MANAGEMENT KEY's P2
(0xFF means no touch, 0xFE means touch required)
- Answer `6A80` instead of panicking when the backend does not provide the mechanism
GENERATE ASYMMETRIC or an RSA IMPORT ASYMMETRIC KEY asks for

## [v0.7.0][] (2026-08-17)

Expand Down
16 changes: 13 additions & 3 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -878,14 +878,18 @@ impl<T: Client> LoadedAuthenticator<'_, T> {
parsed_mechanism,
self.trussed,
self.options.storage,
);
)?;

let public_key = syscall!(self.trussed.derive_key(
let public_key = try_syscall!(self.trussed.derive_key(
parsed_mechanism.key_mechanism(),
secret_key,
None,
StorageAttributes::default().set_persistence(Location::Volatile)
))
.map_err(|_err| {
warn!("Failed to derive the public key: {_err:?}");
Status::IncorrectDataParameter
})?
.key;

match parsed_mechanism {
Expand Down Expand Up @@ -1076,7 +1080,9 @@ impl<T: Client> LoadedAuthenticator<'_, T> {
let p = tlv::get_do(&[0x01], data).ok_or(Status::IncorrectDataParameter)?;
let q = tlv::get_do(&[0x02], data).ok_or(Status::IncorrectDataParameter)?;
let e = tlv::get_do(&[0x03], data).ok_or(Status::IncorrectDataParameter)?;
let id = syscall!(self.trussed.unsafe_inject_key(
// The app can be built with `rsa` on a backend without it; that is an
// unsupported algorithm to the client, not a reason to panic
let id = try_syscall!(self.trussed.unsafe_inject_key(
algo.key_mechanism(),
&RsaImportFormat { e, p, q }.serialize().map_err(|_err| {
error!("Failed rsa import serialization: {_err:?}");
Expand All @@ -1085,6 +1091,10 @@ impl<T: Client> LoadedAuthenticator<'_, T> {
AsymmetricKeyReference::PivAuthentication.storage(self.options.storage),
KeySerialization::RsaParts
))
.map_err(|_err| {
warn!("Failed RSA import: {_err:?}");
Status::IncorrectDataParameter
})?
.key;
self.state.persistent.replace_asymmetric_key(
key,
Expand Down
15 changes: 11 additions & 4 deletions src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -802,11 +802,18 @@ impl Persistent {
alg: AsymmetricAlgorithms,
client: &mut impl crate::Client,
storage: Location,
) -> KeyId {
let id = syscall!(client.generate_key(
) -> Result<KeyId, Status> {
// A backend built without the mechanism answers MechanismNotAvailable; to the client
// that is an unsupported algorithm (6A80, like an unknown algorithm byte), not a
// reason to panic
let id = try_syscall!(client.generate_key(
alg.key_mechanism(),
StorageAttributes::default().set_persistence(key.storage(self.storage))
))
.map_err(|_err| {
warn!("Failed to generate a {alg:?} key: {_err:?}");
Status::IncorrectDataParameter
})?
.key;
let old = self.set_asymmetric_key(key, id, alg, storage, client);
self.save(client);
Expand All @@ -820,7 +827,7 @@ impl Persistent {
// Old file was already overwritten
}
}
id
Ok(id)
}

pub fn replace_asymmetric_key(
Expand Down Expand Up @@ -1004,7 +1011,7 @@ impl Persistent {
authentication_alg,
client,
options.storage,
);
)?;

Self::init_pins(client, options)?;
Ok(state)
Expand Down
Loading