@@ -397,7 +397,7 @@ impl<UP: UserPresence, T: TrussedRequirements> Authenticator for crate::Authenti
397
397
// then check the maximum number of RK credentials
398
398
if let Some ( max_count) = self . config . max_resident_credential_count {
399
399
let mut cm = credential_management:: CredentialManagement :: new ( self ) ;
400
- let metadata = cm. get_creds_metadata ( ) ;
400
+ let metadata = cm. get_creds_metadata ( ) ? ;
401
401
let count = metadata
402
402
. existing_resident_credentials_count
403
403
. unwrap_or ( max_count) ;
@@ -945,7 +945,7 @@ impl<UP: UserPresence, T: TrussedRequirements> Authenticator for crate::Authenti
945
945
let sub_parameters = & parameters. sub_command_params ;
946
946
match parameters. sub_command {
947
947
// 0x1
948
- Subcommand :: GetCredsMetadata => Ok ( cred_mgmt. get_creds_metadata ( ) ) ,
948
+ Subcommand :: GetCredsMetadata => cred_mgmt. get_creds_metadata ( ) ,
949
949
950
950
// 0x2
951
951
Subcommand :: EnumerateRpsBegin => cred_mgmt. first_relying_party ( ) ,
@@ -1040,7 +1040,7 @@ impl<UP: UserPresence, T: TrussedRequirements> Authenticator for crate::Authenti
1040
1040
// If no allowList is passed, credential is None and the retrieved credentials
1041
1041
// are stored in state.runtime.credential_heap
1042
1042
let ( credential, num_credentials) = self
1043
- . prepare_credentials ( & rp_id_hash, & parameters. allow_list , uv_performed)
1043
+ . prepare_credentials ( & rp_id_hash, & parameters. allow_list , uv_performed) ?
1044
1044
. ok_or ( Error :: NoCredentials ) ?;
1045
1045
1046
1046
info_now ! ( "found {:?} applicable credentials" , num_credentials) ;
@@ -1180,7 +1180,7 @@ impl<UP: UserPresence, T: TrussedRequirements> crate::Authenticator<UP, T> {
1180
1180
rp_id_hash : & Bytes < 32 > ,
1181
1181
allow_list : & Option < ctap2:: get_assertion:: AllowList > ,
1182
1182
uv_performed : bool ,
1183
- ) -> Option < ( Credential , u32 ) > {
1183
+ ) -> Result < Option < ( Credential , u32 ) > > {
1184
1184
debug_now ! ( "remaining stack size: {} bytes" , msp( ) - 0x2000_0000 ) ;
1185
1185
1186
1186
self . state . runtime . clear_credential_cache ( ) ;
@@ -1214,50 +1214,74 @@ impl<UP: UserPresence, T: TrussedRequirements> crate::Authenticator<UP, T> {
1214
1214
continue ;
1215
1215
}
1216
1216
1217
- return Some ( ( credential, 1 ) ) ;
1217
+ return Ok ( Some ( ( credential, 1 ) ) ) ;
1218
1218
}
1219
1219
1220
1220
// we don't recognize any credentials in the allowlist
1221
- return None ;
1221
+ return Ok ( None ) ;
1222
1222
}
1223
1223
}
1224
1224
1225
1225
// we are only dealing with discoverable credentials.
1226
1226
debug_now ! ( "Allowlist not passed, fetching RKs" ) ;
1227
+ self . prepare_cache ( rp_id_hash, uv_performed) ?;
1227
1228
1228
- let mut maybe_path =
1229
- syscall ! ( self
1230
- . trussed
1231
- . read_dir_first( Location :: Internal , rp_rk_dir( rp_id_hash) , None , ) )
1232
- . entry
1233
- . map ( |entry| PathBuf :: from ( entry. path ( ) ) ) ;
1229
+ let num_credentials = self . state . runtime . remaining_credentials ( ) ;
1230
+ let credential = self . state . runtime . pop_credential ( & mut self . trussed ) ;
1231
+ Ok ( credential. map ( |credential| ( Credential :: Full ( credential) , num_credentials) ) )
1232
+ }
1234
1233
1234
+ /// Populate the cache with the RP credentials.
1235
+ ///
1236
+ /// Returns true if legacy credentials are present and therefore prepare_cache_legacy should be called too
1237
+ #[ inline( never) ]
1238
+ fn prepare_cache ( & mut self , rp_id_hash : & Bytes < 32 > , uv_performed : bool ) -> Result < ( ) > {
1235
1239
use crate :: state:: CachedCredential ;
1236
1240
use core:: str:: FromStr ;
1237
1241
1238
- while let Some ( path) = maybe_path {
1239
- let credential_data =
1240
- syscall ! ( self . trussed. read_file( Location :: Internal , path. clone( ) , ) ) . data ;
1242
+ let rp_rk_dir = rp_rk_dir ( rp_id_hash) ;
1243
+ let mut maybe_entry = syscall ! ( self . trussed. read_dir_first_alphabetical(
1244
+ Location :: Internal ,
1245
+ PathBuf :: from( b"rk" ) ,
1246
+ Some ( rp_rk_dir. clone( ) )
1247
+ ) )
1248
+ . entry ;
1249
+
1250
+ while let Some ( entry) = maybe_entry. take ( ) {
1251
+ if !entry. path ( ) . as_ref ( ) . starts_with ( rp_rk_dir. as_ref ( ) ) {
1252
+ // We got past all credentials for the relevant RP
1253
+ break ;
1254
+ }
1241
1255
1242
- let credential = FullCredential :: deserialize ( & credential_data) . ok ( ) ?;
1256
+ if entry. path ( ) == & * rp_rk_dir {
1257
+ debug_assert ! ( entry. metadata( ) . is_dir( ) ) ;
1258
+ error ! ( "Migration missing" ) ;
1259
+ return Err ( Error :: Other ) ;
1260
+ }
1261
+
1262
+ let credential_data = syscall ! ( self
1263
+ . trussed
1264
+ . read_file( Location :: Internal , entry. path( ) . into( ) , ) )
1265
+ . data ;
1266
+
1267
+ let credential = FullCredential :: deserialize ( & credential_data) . map_err ( |_err| {
1268
+ error ! ( "Failed to deserialize credential: {_err:?}" ) ;
1269
+ Error :: Other
1270
+ } ) ?;
1243
1271
let timestamp = credential. creation_time ;
1244
1272
let credential = Credential :: Full ( credential) ;
1245
1273
1246
1274
if self . check_credential_applicable ( & credential, false , uv_performed) {
1247
1275
self . state . runtime . push_credential ( CachedCredential {
1248
1276
timestamp,
1249
- path : String :: from_str ( path. as_str_ref_with_trailing_nul ( ) ) . ok ( ) ?,
1277
+ path : String :: from_str ( entry. path ( ) . as_str_ref_with_trailing_nul ( ) )
1278
+ . map_err ( |_| Error :: Other ) ?,
1250
1279
} ) ;
1251
1280
}
1252
1281
1253
- maybe_path = syscall ! ( self . trussed. read_dir_next( ) )
1254
- . entry
1255
- . map ( |entry| PathBuf :: from ( entry. path ( ) ) ) ;
1282
+ maybe_entry = syscall ! ( self . trussed. read_dir_next( ) ) . entry ;
1256
1283
}
1257
-
1258
- let num_credentials = self . state . runtime . remaining_credentials ( ) ;
1259
- let credential = self . state . runtime . pop_credential ( & mut self . trussed ) ;
1260
- credential. map ( |credential| ( Credential :: Full ( credential) , num_credentials) )
1284
+ Ok ( ( ) )
1261
1285
}
1262
1286
1263
1287
fn decrypt_pin_hash_and_maybe_escalate (
@@ -2001,11 +2025,12 @@ fn rp_rk_dir(rp_id_hash: &Bytes<32>) -> PathBuf {
2001
2025
}
2002
2026
2003
2027
fn rk_path ( rp_id_hash : & Bytes < 32 > , credential_id_hash : & Bytes < 32 > ) -> PathBuf {
2004
- let mut path = rp_rk_dir ( rp_id_hash) ;
2005
-
2006
- let mut hex = [ 0u8 ; 16 ] ;
2007
- format_hex ( & credential_id_hash[ ..8 ] , & mut hex) ;
2008
- path. push ( & PathBuf :: from ( & hex) ) ;
2028
+ let mut buf = [ 0 ; 33 ] ;
2029
+ buf[ 16 ] = b'.' ;
2030
+ format_hex ( & rp_id_hash[ ..8 ] , & mut buf[ ..16 ] ) ;
2031
+ format_hex ( & credential_id_hash[ ..8 ] , & mut buf[ 17 ..] ) ;
2009
2032
2033
+ let mut path = PathBuf :: from ( "rk" ) ;
2034
+ path. push ( & PathBuf :: from ( buf. as_slice ( ) ) ) ;
2010
2035
path
2011
2036
}
0 commit comments