@@ -30,6 +30,7 @@ use serde::{
30
30
} ;
31
31
use serde_bytes:: ByteBuf ;
32
32
use serde_cbor:: { de:: from_slice, ser, Value } ;
33
+ use std:: collections:: HashMap ;
33
34
use std:: fmt;
34
35
use std:: io:: Cursor ;
35
36
@@ -145,6 +146,8 @@ pub struct GetAssertionExtensions {
145
146
pub cred_blob : Option < bool > ,
146
147
#[ serde( rename = "largeBlobKey" , skip_serializing_if = "Option::is_none" ) ]
147
148
pub large_blob_key : Option < bool > ,
149
+ #[ serde( rename = "thirdPartyPayment" , skip_serializing_if = "Option::is_none" ) ]
150
+ pub third_party_payment : Option < bool > ,
148
151
}
149
152
150
153
impl From < AuthenticationExtensionsClientInputs > for GetAssertionExtensions {
@@ -156,14 +159,18 @@ impl From<AuthenticationExtensionsClientInputs> for GetAssertionExtensions {
156
159
_ => None ,
157
160
} ,
158
161
large_blob_key : input. large_blob_key ,
162
+ third_party_payment : input. third_party_payment ,
159
163
..Default :: default ( )
160
164
}
161
165
}
162
166
}
163
167
164
168
impl GetAssertionExtensions {
165
169
fn has_content ( & self ) -> bool {
166
- self . hmac_secret . is_some ( ) || self . cred_blob . is_some ( ) || self . large_blob_key . is_some ( )
170
+ self . hmac_secret . is_some ( )
171
+ || self . cred_blob . is_some ( )
172
+ || self . large_blob_key . is_some ( )
173
+ || self . third_party_payment . is_some ( )
167
174
}
168
175
}
169
176
@@ -182,6 +189,10 @@ pub struct GetAssertion {
182
189
pub extensions : GetAssertionExtensions ,
183
190
pub options : GetAssertionOptions ,
184
191
pub pin_uv_auth_param : Option < PinUvAuthParam > ,
192
+
193
+ // CTAP 2.2:
194
+ pub enterprise_attestation : Option < u64 > ,
195
+ pub attestation_formats_preference : Option < Vec < String > > ,
185
196
}
186
197
187
198
impl GetAssertion {
@@ -199,6 +210,8 @@ impl GetAssertion {
199
210
extensions,
200
211
options,
201
212
pin_uv_auth_param : None ,
213
+ enterprise_attestation : None ,
214
+ attestation_formats_preference : None ,
202
215
}
203
216
}
204
217
@@ -287,22 +300,34 @@ impl Serialize for GetAssertion {
287
300
if self . pin_uv_auth_param . is_some ( ) {
288
301
map_len += 2 ;
289
302
}
303
+ if self . enterprise_attestation . is_some ( ) {
304
+ map_len += 1 ;
305
+ }
306
+ if self . attestation_formats_preference . is_some ( ) {
307
+ map_len += 1 ;
308
+ }
290
309
291
310
let mut map = serializer. serialize_map ( Some ( map_len) ) ?;
292
- map. serialize_entry ( & 1 , & self . rp . id ) ?;
293
- map. serialize_entry ( & 2 , & self . client_data_hash ) ?;
311
+ map. serialize_entry ( & 0x01 , & self . rp . id ) ?;
312
+ map. serialize_entry ( & 0x02 , & self . client_data_hash ) ?;
294
313
if !self . allow_list . is_empty ( ) {
295
- map. serialize_entry ( & 3 , & self . allow_list ) ?;
314
+ map. serialize_entry ( & 0x03 , & self . allow_list ) ?;
296
315
}
297
316
if self . extensions . has_content ( ) {
298
- map. serialize_entry ( & 4 , & self . extensions ) ?;
317
+ map. serialize_entry ( & 0x04 , & self . extensions ) ?;
299
318
}
300
319
if self . options . has_some ( ) {
301
- map. serialize_entry ( & 5 , & self . options ) ?;
320
+ map. serialize_entry ( & 0x05 , & self . options ) ?;
302
321
}
303
322
if let Some ( pin_uv_auth_param) = & self . pin_uv_auth_param {
304
- map. serialize_entry ( & 6 , & pin_uv_auth_param) ?;
305
- map. serialize_entry ( & 7 , & pin_uv_auth_param. pin_protocol . id ( ) ) ?;
323
+ map. serialize_entry ( & 0x06 , & pin_uv_auth_param) ?;
324
+ map. serialize_entry ( & 0x07 , & pin_uv_auth_param. pin_protocol . id ( ) ) ?;
325
+ }
326
+ if let Some ( enterprise_attestation) = & self . enterprise_attestation {
327
+ map. serialize_entry ( & 0x08 , & enterprise_attestation) ?;
328
+ }
329
+ if let Some ( attestation_formats_preference) = & self . attestation_formats_preference {
330
+ map. serialize_entry ( & 0x09 , & attestation_formats_preference) ?;
306
331
}
307
332
map. end ( )
308
333
}
@@ -551,6 +576,9 @@ pub struct GetAssertionResponse {
551
576
pub number_of_credentials : Option < usize > ,
552
577
pub user_selected : Option < bool > ,
553
578
pub large_blob_key : Option < Vec < u8 > > ,
579
+ pub unsigned_extension_outputs : Option < HashMap < String , serde_cbor:: Value > > ,
580
+ pub ep_attestation : Option < bool > ,
581
+ pub att_stmt : Option < HashMap < String , serde_cbor:: Value > > ,
554
582
}
555
583
556
584
impl CtapResponse for GetAssertionResponse { }
@@ -580,6 +608,9 @@ impl<'de> Deserialize<'de> for GetAssertionResponse {
580
608
let mut number_of_credentials = None ;
581
609
let mut user_selected = None ;
582
610
let mut large_blob_key = None ;
611
+ let mut unsigned_extension_outputs = None ;
612
+ let mut ep_attestation = None ;
613
+ let mut att_stmt = None ;
583
614
584
615
while let Some ( key) = map. next_key ( ) ? {
585
616
match key {
@@ -627,6 +658,26 @@ impl<'de> Deserialize<'de> for GetAssertionResponse {
627
658
let large_blob_key_bytes: ByteBuf = map. next_value ( ) ?;
628
659
large_blob_key = Some ( large_blob_key_bytes. into_vec ( ) ) ;
629
660
}
661
+ 0x08 => {
662
+ if unsigned_extension_outputs. is_some ( ) {
663
+ return Err ( M :: Error :: duplicate_field (
664
+ "unsigned_extension_outputs" ,
665
+ ) ) ;
666
+ }
667
+ unsigned_extension_outputs = Some ( map. next_value ( ) ?) ;
668
+ }
669
+ 0x09 => {
670
+ if ep_attestation. is_some ( ) {
671
+ return Err ( M :: Error :: duplicate_field ( "ep_attestation" ) ) ;
672
+ }
673
+ ep_attestation = Some ( map. next_value ( ) ?) ;
674
+ }
675
+ 0x0A => {
676
+ if att_stmt. is_some ( ) {
677
+ return Err ( M :: Error :: duplicate_field ( "att_stmt" ) ) ;
678
+ }
679
+ att_stmt = Some ( map. next_value ( ) ?) ;
680
+ }
630
681
k => return Err ( M :: Error :: custom ( format ! ( "unexpected key: {k:?}" ) ) ) ,
631
682
}
632
683
}
@@ -642,6 +693,9 @@ impl<'de> Deserialize<'de> for GetAssertionResponse {
642
693
number_of_credentials,
643
694
user_selected,
644
695
large_blob_key,
696
+ unsigned_extension_outputs,
697
+ ep_attestation,
698
+ att_stmt,
645
699
} )
646
700
}
647
701
}
@@ -1228,6 +1282,9 @@ pub mod test {
1228
1282
certifications : None ,
1229
1283
remaining_discoverable_credentials : None ,
1230
1284
vendor_prototype_config_commands : None ,
1285
+ attestation_formats : None ,
1286
+ uv_count_since_last_pin_entry : None ,
1287
+ long_touch_for_reset : None ,
1231
1288
} ) ;
1232
1289
1233
1290
// Sending first GetAssertion with first allow_list-entry, that will return an error
0 commit comments