mirror of
https://github.com/trussed-dev/fido-authenticator.git
synced 2026-06-20 04:16:16 -07:00
credential_management: Implement UpdateUserInformation
This commit is contained in:
@@ -22,6 +22,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
- Extract PIN protocol implementation into separate module ([#62][])
|
||||
- Implement PIN protocol 2 ([#63][])
|
||||
- Implement PIN token permissions ([#63][])
|
||||
- Implement UpdateUserInformation subcommand for CredentialManagement
|
||||
|
||||
[#26]: https://github.com/solokeys/fido-authenticator/issues/26
|
||||
[#28]: https://github.com/solokeys/fido-authenticator/issues/28
|
||||
|
||||
+18
-6
@@ -990,7 +990,19 @@ impl<UP: UserPresence, T: TrussedRequirements> Authenticator for crate::Authenti
|
||||
}
|
||||
|
||||
// 0x7
|
||||
Subcommand::UpdateUserInformation => Err(Error::InvalidParameter),
|
||||
Subcommand::UpdateUserInformation => {
|
||||
let sub_parameters = sub_parameters.as_ref().ok_or(Error::MissingParameter)?;
|
||||
let credential_id = sub_parameters
|
||||
.credential_id
|
||||
.as_ref()
|
||||
.ok_or(Error::MissingParameter)?;
|
||||
let user = sub_parameters
|
||||
.user
|
||||
.as_ref()
|
||||
.ok_or(Error::MissingParameter)?;
|
||||
|
||||
cred_mgmt.update_user_information(credential_id, user)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1338,7 +1350,8 @@ impl<UP: UserPresence, T: TrussedRequirements> crate::Authenticator<UP, T> {
|
||||
sub_command @ Subcommand::GetCredsMetadata
|
||||
| sub_command @ Subcommand::EnumerateRpsBegin
|
||||
| sub_command @ Subcommand::EnumerateCredentialsBegin
|
||||
| sub_command @ Subcommand::DeleteCredential => {
|
||||
| sub_command @ Subcommand::DeleteCredential
|
||||
| sub_command @ Subcommand::UpdateUserInformation => {
|
||||
// check pinProtocol
|
||||
let pin_protocol = parameters
|
||||
// .sub_command_params.as_ref().ok_or(Error::MissingParameter)?
|
||||
@@ -1350,7 +1363,9 @@ impl<UP: UserPresence, T: TrussedRequirements> crate::Authenticator<UP, T> {
|
||||
let mut data: Bytes<{ sizes::MAX_CREDENTIAL_ID_LENGTH_PLUS_256 }> =
|
||||
Bytes::from_slice(&[sub_command as u8]).unwrap();
|
||||
let len = 1 + match sub_command {
|
||||
Subcommand::EnumerateCredentialsBegin | Subcommand::DeleteCredential => {
|
||||
Subcommand::EnumerateCredentialsBegin
|
||||
| Subcommand::DeleteCredential
|
||||
| Subcommand::UpdateUserInformation => {
|
||||
data.resize_to_capacity();
|
||||
// ble, need to reserialize
|
||||
ctap_types::serde::cbor_serialize(
|
||||
@@ -1395,9 +1410,6 @@ impl<UP: UserPresence, T: TrussedRequirements> crate::Authenticator<UP, T> {
|
||||
// of already checked CredMgmt subcommands
|
||||
Subcommand::EnumerateRpsGetNextRp
|
||||
| Subcommand::EnumerateCredentialsGetNextCredential => Ok(()),
|
||||
|
||||
// not implemented
|
||||
Subcommand::UpdateUserInformation => Err(Error::InvalidParameter),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
use core::convert::TryFrom;
|
||||
|
||||
use trussed::{
|
||||
syscall,
|
||||
syscall, try_syscall,
|
||||
types::{DirEntry, Location, Path, PathBuf},
|
||||
};
|
||||
|
||||
@@ -11,7 +11,7 @@ use ctap_types::{
|
||||
cose::PublicKey,
|
||||
ctap2::credential_management::{CredentialProtectionPolicy, Response},
|
||||
heapless_bytes::Bytes,
|
||||
webauthn::PublicKeyCredentialDescriptor,
|
||||
webauthn::{PublicKeyCredentialDescriptor, PublicKeyCredentialUserEntity},
|
||||
Error,
|
||||
};
|
||||
|
||||
@@ -460,22 +460,27 @@ where
|
||||
Ok(response)
|
||||
}
|
||||
|
||||
pub fn delete_credential(
|
||||
&mut self,
|
||||
credential_descriptor: &PublicKeyCredentialDescriptor,
|
||||
) -> Result<Response> {
|
||||
info!("delete credential");
|
||||
let credential_id_hash = self.hash(&credential_descriptor.id[..]);
|
||||
fn find_credential(&mut self, credential: &PublicKeyCredentialDescriptor) -> Option<PathBuf> {
|
||||
let credential_id_hash = self.hash(&credential.id[..]);
|
||||
let mut hex = [b'0'; 16];
|
||||
super::format_hex(&credential_id_hash[..8], &mut hex);
|
||||
let dir = PathBuf::from(b"rk");
|
||||
let filename = PathBuf::from(&hex);
|
||||
|
||||
let rk_path = syscall!(self
|
||||
syscall!(self
|
||||
.trussed
|
||||
.locate_file(Location::Internal, Some(dir), filename,))
|
||||
.path
|
||||
.ok_or(Error::InvalidCredential)?;
|
||||
}
|
||||
|
||||
pub fn delete_credential(
|
||||
&mut self,
|
||||
credential_descriptor: &PublicKeyCredentialDescriptor,
|
||||
) -> Result<Response> {
|
||||
info!("delete credential");
|
||||
let rk_path = self
|
||||
.find_credential(credential_descriptor)
|
||||
.ok_or(Error::InvalidCredential)?;
|
||||
|
||||
// DELETE
|
||||
self.delete_resident_key_by_path(&rk_path)?;
|
||||
@@ -491,4 +496,49 @@ where
|
||||
let response = Default::default();
|
||||
Ok(response)
|
||||
}
|
||||
|
||||
pub fn update_user_information(
|
||||
&mut self,
|
||||
credential_descriptor: &PublicKeyCredentialDescriptor,
|
||||
user: &PublicKeyCredentialUserEntity,
|
||||
) -> Result<Response> {
|
||||
info!("update user information");
|
||||
|
||||
// locate and parse existing credential
|
||||
let rk_path = self
|
||||
.find_credential(credential_descriptor)
|
||||
.ok_or(Error::NoCredentials)?;
|
||||
let serialized = syscall!(self.trussed.read_file(Location::Internal, rk_path.clone())).data;
|
||||
let mut credential =
|
||||
FullCredential::deserialize(&serialized).map_err(|_| Error::InvalidCredential)?;
|
||||
|
||||
// TODO: check remaining space, return KeyStoreFull
|
||||
|
||||
// the updated user ID must match the stored user ID
|
||||
if credential.user.id != user.id {
|
||||
error!("updated user ID does not match original user ID");
|
||||
return Err(Error::InvalidParameter);
|
||||
}
|
||||
|
||||
// update user name and display name unless the values are not set or empty
|
||||
credential.data.user.name = user
|
||||
.name
|
||||
.as_ref()
|
||||
.filter(|s| !s.is_empty())
|
||||
.map(Clone::clone);
|
||||
credential.data.user.display_name = user
|
||||
.display_name
|
||||
.as_ref()
|
||||
.filter(|s| !s.is_empty())
|
||||
.map(Clone::clone);
|
||||
|
||||
// write updated credential
|
||||
let serialized = credential.serialize()?;
|
||||
try_syscall!(self
|
||||
.trussed
|
||||
.write_file(Location::Internal, rk_path, serialized, None))
|
||||
.map_err(|_| Error::KeyStoreFull)?;
|
||||
|
||||
Ok(Default::default())
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user