@@ -111,6 +111,7 @@ where
111111 req
112112 )
113113 } ?;
114+ self . set_cred_mgmt_preview ( req. use_legacy_preview ) ;
114115 Ok ( (
115116 Ctap2RPData :: new (
116117 unwrap_field ! ( resp. rp) ,
@@ -121,7 +122,8 @@ where
121122 }
122123
123124 async fn enumerate_rps_next_rp ( & mut self , timeout : Duration ) -> Result < Ctap2RPData , Error > {
124- let req = Ctap2CredentialManagementRequest :: new_enumerate_rps_next_rp ( ) ;
125+ let mut req = Ctap2CredentialManagementRequest :: new_enumerate_rps_next_rp ( ) ;
126+ req. use_legacy_preview = self . cred_mgmt_preview ( ) ;
125127 let resp = self . ctap2_credential_management ( & req, timeout) . await ?;
126128 Ok ( Ctap2RPData :: new (
127129 unwrap_field ! ( resp. rp) ,
@@ -153,6 +155,7 @@ where
153155 req
154156 )
155157 } ?;
158+ self . set_cred_mgmt_preview ( req. use_legacy_preview ) ;
156159 let cred = Ctap2CredentialData :: new (
157160 unwrap_field ! ( resp. user) ,
158161 unwrap_field ! ( resp. credential_id) ,
@@ -168,7 +171,8 @@ where
168171 & mut self ,
169172 timeout : Duration ,
170173 ) -> Result < Ctap2CredentialData , Error > {
171- let req = Ctap2CredentialManagementRequest :: new_enumerate_credentials_next ( ) ;
174+ let mut req = Ctap2CredentialManagementRequest :: new_enumerate_credentials_next ( ) ;
175+ req. use_legacy_preview = self . cred_mgmt_preview ( ) ;
172176 let resp = self . ctap2_credential_management ( & req, timeout) . await ?;
173177 let cred = Ctap2CredentialData :: new (
174178 unwrap_field ! ( resp. user) ,
@@ -337,7 +341,7 @@ mod test {
337341 Ctap2PublicKeyCredentialType , Ctap2PublicKeyCredentialUserEntity ,
338342 } ;
339343 use crate :: transport:: mock:: channel:: MockChannel ;
340- use std:: collections:: BTreeMap ;
344+ use std:: collections:: { BTreeMap , HashMap } ;
341345
342346 const TIMEOUT : Duration = Duration :: from_secs ( 1 ) ;
343347
@@ -459,4 +463,57 @@ mod test {
459463 assert_eq ! ( cred. cred_protect, 1 ) ;
460464 assert ! ( cred. large_blob_key. is_none( ) ) ;
461465 }
466+
467+ #[ tokio:: test]
468+ async fn get_next_reuses_preview_command_resolved_by_begin ( ) {
469+ let mut channel = MockChannel :: new ( ) ;
470+
471+ // Device advertises credentialMgmtPreview only: Begin must resolve 0x41.
472+ let info = Ctap2GetInfoResponse {
473+ options : Some ( HashMap :: from ( [ ( "credentialMgmtPreview" . to_string ( ) , true ) ] ) ) ,
474+ ..Default :: default ( )
475+ } ;
476+ let info_req = CborRequest :: new ( Ctap2CommandCode :: AuthenticatorGetInfo ) ;
477+ let info_resp = CborResponse :: new_success_from_slice ( & cbor:: to_vec ( & info) . unwrap ( ) ) ;
478+ channel. push_command_pair ( info_req, info_resp) ;
479+
480+ let mut begin_req = Ctap2CredentialManagementRequest :: new_enumerate_rps_begin ( ) ;
481+ begin_req. use_legacy_preview = true ;
482+ let begin_cbor: CborRequest = ( & begin_req) . try_into ( ) . unwrap ( ) ;
483+ assert_eq ! (
484+ begin_cbor. command,
485+ Ctap2CommandCode :: AuthenticatorCredentialManagementPreview
486+ ) ;
487+ let begin_fixture = EnumerateRpsResponse {
488+ rp : Ctap2PublicKeyCredentialRpEntity :: new ( "example.com" , "Example" ) ,
489+ rp_id_hash : ByteBuf :: from ( vec ! [ 0xEF ; 32 ] ) ,
490+ total_rps : 2 ,
491+ } ;
492+ channel. push_command_pair (
493+ begin_cbor,
494+ CborResponse :: new_success_from_slice ( & cbor:: to_vec ( & begin_fixture) . unwrap ( ) ) ,
495+ ) ;
496+
497+ let mut next_req = Ctap2CredentialManagementRequest :: new_enumerate_rps_next_rp ( ) ;
498+ next_req. use_legacy_preview = true ;
499+ let next_cbor: CborRequest = ( & next_req) . try_into ( ) . unwrap ( ) ;
500+ assert_eq ! (
501+ next_cbor. command,
502+ Ctap2CommandCode :: AuthenticatorCredentialManagementPreview
503+ ) ;
504+ assert_eq ! ( next_cbor. encoded_data, vec![ 0xA1 , 0x01 , 0x03 ] ) ;
505+ let next_fixture = EnumerateRpsNextResponse {
506+ rp : Ctap2PublicKeyCredentialRpEntity :: new ( "example.org" , "Example Two" ) ,
507+ rp_id_hash : ByteBuf :: from ( vec ! [ 0x11 ; 32 ] ) ,
508+ } ;
509+ channel. push_command_pair (
510+ next_cbor,
511+ CborResponse :: new_success_from_slice ( & cbor:: to_vec ( & next_fixture) . unwrap ( ) ) ,
512+ ) ;
513+
514+ let ( _, total) = channel. enumerate_rps_begin ( TIMEOUT ) . await . unwrap ( ) ;
515+ assert_eq ! ( total, 2 ) ;
516+ let rp_data = channel. enumerate_rps_next_rp ( TIMEOUT ) . await . unwrap ( ) ;
517+ assert_eq ! ( rp_data. rp_id_hash, vec![ 0x11 ; 32 ] ) ;
518+ }
462519}
0 commit comments