@@ -392,7 +392,7 @@ impl<UP: UserPresence, T: TrussedRequirements> Authenticator for crate::Authenti
392
392
. ok ( ) ;
393
393
394
394
let mut key_store_full = self . can_fit ( serialized_credential. len ( ) ) == Some ( false )
395
- || CredentialManagement :: new ( self ) . count_credentials ( )
395
+ || CredentialManagement :: new ( self ) . count_credentials ( ) ?
396
396
>= self
397
397
. config
398
398
. max_resident_credential_count
@@ -914,7 +914,7 @@ impl<UP: UserPresence, T: TrussedRequirements> Authenticator for crate::Authenti
914
914
// TODO: use custom enum of known commands
915
915
match parameters. sub_command {
916
916
// 0x1
917
- Subcommand :: GetCredsMetadata => Ok ( cred_mgmt. get_creds_metadata ( ) ) ,
917
+ Subcommand :: GetCredsMetadata => cred_mgmt. get_creds_metadata ( ) ,
918
918
919
919
// 0x2
920
920
Subcommand :: EnumerateRpsBegin => cred_mgmt. first_relying_party ( ) ,
@@ -1011,7 +1011,7 @@ impl<UP: UserPresence, T: TrussedRequirements> Authenticator for crate::Authenti
1011
1011
// If no allowList is passed, credential is None and the retrieved credentials
1012
1012
// are stored in state.runtime.credential_heap
1013
1013
let ( credential, num_credentials) = self
1014
- . prepare_credentials ( & rp_id_hash, & parameters. allow_list , uv_performed)
1014
+ . prepare_credentials ( & rp_id_hash, & parameters. allow_list , uv_performed) ?
1015
1015
. ok_or ( Error :: NoCredentials ) ?;
1016
1016
1017
1017
info_now ! ( "found {:?} applicable credentials" , num_credentials) ;
@@ -1152,7 +1152,7 @@ impl<UP: UserPresence, T: TrussedRequirements> crate::Authenticator<UP, T> {
1152
1152
rp_id_hash : & [ u8 ; 32 ] ,
1153
1153
allow_list : & Option < ctap2:: get_assertion:: AllowList > ,
1154
1154
uv_performed : bool ,
1155
- ) -> Option < ( Credential , u32 ) > {
1155
+ ) -> Result < Option < ( Credential , u32 ) > > {
1156
1156
debug_now ! ( "remaining stack size: {} bytes" , msp( ) - 0x2000_0000 ) ;
1157
1157
1158
1158
self . state . runtime . clear_credential_cache ( ) ;
@@ -1186,50 +1186,74 @@ impl<UP: UserPresence, T: TrussedRequirements> crate::Authenticator<UP, T> {
1186
1186
continue ;
1187
1187
}
1188
1188
1189
- return Some ( ( credential, 1 ) ) ;
1189
+ return Ok ( Some ( ( credential, 1 ) ) ) ;
1190
1190
}
1191
1191
1192
1192
// we don't recognize any credentials in the allowlist
1193
- return None ;
1193
+ return Ok ( None ) ;
1194
1194
}
1195
1195
}
1196
1196
1197
1197
// we are only dealing with discoverable credentials.
1198
1198
debug_now ! ( "Allowlist not passed, fetching RKs" ) ;
1199
+ self . prepare_cache ( rp_id_hash, uv_performed) ?;
1199
1200
1200
- let mut maybe_path =
1201
- syscall ! ( self
1202
- . trussed
1203
- . read_dir_first( Location :: Internal , rp_rk_dir( rp_id_hash) , None , ) )
1204
- . entry
1205
- . map ( |entry| PathBuf :: from ( entry. path ( ) ) ) ;
1201
+ let num_credentials = self . state . runtime . remaining_credentials ( ) ;
1202
+ let credential = self . state . runtime . pop_credential ( & mut self . trussed ) ;
1203
+ Ok ( credential. map ( |credential| ( Credential :: Full ( credential) , num_credentials) ) )
1204
+ }
1206
1205
1206
+ /// Populate the cache with the RP credentials.
1207
+ ///
1208
+ /// Returns true if legacy credentials are present and therefore prepare_cache_legacy should be called too
1209
+ #[ inline( never) ]
1210
+ fn prepare_cache ( & mut self , rp_id_hash : & [ u8 ; 32 ] , uv_performed : bool ) -> Result < ( ) > {
1207
1211
use crate :: state:: CachedCredential ;
1208
1212
use core:: str:: FromStr ;
1209
1213
1210
- while let Some ( path) = maybe_path {
1211
- let credential_data =
1212
- syscall ! ( self . trussed. read_file( Location :: Internal , path. clone( ) , ) ) . data ;
1214
+ let rp_rk_dir = rp_rk_dir ( rp_id_hash) ;
1215
+ let mut maybe_entry = syscall ! ( self . trussed. read_dir_first_alphabetical(
1216
+ Location :: Internal ,
1217
+ PathBuf :: from( RK_DIR ) ,
1218
+ Some ( rp_rk_dir. clone( ) )
1219
+ ) )
1220
+ . entry ;
1221
+
1222
+ while let Some ( entry) = maybe_entry. take ( ) {
1223
+ if !entry. path ( ) . as_ref ( ) . starts_with ( rp_rk_dir. as_ref ( ) ) {
1224
+ // We got past all credentials for the relevant RP
1225
+ break ;
1226
+ }
1213
1227
1214
- let credential = FullCredential :: deserialize ( & credential_data) . ok ( ) ?;
1228
+ if entry. path ( ) == & * rp_rk_dir {
1229
+ debug_assert ! ( entry. metadata( ) . is_dir( ) ) ;
1230
+ error ! ( "Migration missing" ) ;
1231
+ return Err ( Error :: Other ) ;
1232
+ }
1233
+
1234
+ let credential_data = syscall ! ( self
1235
+ . trussed
1236
+ . read_file( Location :: Internal , entry. path( ) . into( ) , ) )
1237
+ . data ;
1238
+
1239
+ let credential = FullCredential :: deserialize ( & credential_data) . map_err ( |_err| {
1240
+ error ! ( "Failed to deserialize credential: {_err:?}" ) ;
1241
+ Error :: Other
1242
+ } ) ?;
1215
1243
let timestamp = credential. creation_time ;
1216
1244
let credential = Credential :: Full ( credential) ;
1217
1245
1218
1246
if self . check_credential_applicable ( & credential, false , uv_performed) {
1219
1247
self . state . runtime . push_credential ( CachedCredential {
1220
1248
timestamp,
1221
- path : String :: from_str ( path. as_str_ref_with_trailing_nul ( ) ) . ok ( ) ?,
1249
+ path : String :: from_str ( entry. path ( ) . as_str_ref_with_trailing_nul ( ) )
1250
+ . map_err ( |_| Error :: Other ) ?,
1222
1251
} ) ;
1223
1252
}
1224
1253
1225
- maybe_path = syscall ! ( self . trussed. read_dir_next( ) )
1226
- . entry
1227
- . map ( |entry| PathBuf :: from ( entry. path ( ) ) ) ;
1254
+ maybe_entry = syscall ! ( self . trussed. read_dir_next( ) ) . entry ;
1228
1255
}
1229
-
1230
- let num_credentials = self . state . runtime . remaining_credentials ( ) ;
1231
- let credential = self . state . runtime . pop_credential ( & mut self . trussed ) ;
1232
- credential. map ( |credential| ( Credential :: Full ( credential) , num_credentials) )
1256
+ Ok ( ( ) )
1233
1257
}
1234
1258
1235
1259
fn decrypt_pin_hash_and_maybe_escalate (
@@ -2078,11 +2102,12 @@ fn rp_rk_dir(rp_id_hash: &[u8; 32]) -> PathBuf {
2078
2102
}
2079
2103
2080
2104
fn rk_path ( rp_id_hash : & [ u8 ; 32 ] , credential_id_hash : & [ u8 ; 32 ] ) -> PathBuf {
2081
- let mut path = rp_rk_dir ( rp_id_hash) ;
2082
-
2083
- let mut hex = [ 0u8 ; 16 ] ;
2084
- format_hex ( & credential_id_hash[ ..8 ] , & mut hex) ;
2085
- path. push ( & PathBuf :: try_from ( & hex) . unwrap ( ) ) ;
2105
+ let mut buf = [ 0 ; 33 ] ;
2106
+ buf[ 16 ] = b'.' ;
2107
+ format_hex ( & rp_id_hash[ ..8 ] , & mut buf[ ..16 ] ) ;
2108
+ format_hex ( & credential_id_hash[ ..8 ] , & mut buf[ 17 ..] ) ;
2086
2109
2110
+ let mut path = PathBuf :: from ( RK_DIR ) ;
2111
+ path. push ( & PathBuf :: try_from ( buf. as_slice ( ) ) . unwrap ( ) ) ;
2087
2112
path
2088
2113
}
0 commit comments