@@ -17,10 +17,11 @@ use super::customization::{MAX_CREDENTIAL_COUNT_IN_LIST, MAX_LARGE_BLOB_ARRAY_SI
1717use super :: data_formats:: {
1818 extract_array, extract_bool, extract_byte_string, extract_map, extract_text_string,
1919 extract_unsigned, ok_or_missing, ClientPinSubCommand , ConfigSubCommand , ConfigSubCommandParams ,
20- CoseKey , CredentialManagementSubCommand , CredentialManagementSubCommandParameters ,
21- GetAssertionExtensions , GetAssertionOptions , MakeCredentialExtensions , MakeCredentialOptions ,
22- PinUvAuthProtocol , PublicKeyCredentialDescriptor , PublicKeyCredentialParameter ,
23- PublicKeyCredentialRpEntity , PublicKeyCredentialUserEntity , SetMinPinLengthParams ,
20+ CoseKey , CoseSignature , CredentialManagementSubCommand ,
21+ CredentialManagementSubCommandParameters , GetAssertionExtensions , GetAssertionOptions ,
22+ MakeCredentialExtensions , MakeCredentialOptions , PinUvAuthProtocol ,
23+ PublicKeyCredentialDescriptor , PublicKeyCredentialParameter , PublicKeyCredentialRpEntity ,
24+ PublicKeyCredentialUserEntity , SetMinPinLengthParams ,
2425} ;
2526use super :: key_material;
2627use super :: status_code:: Ctap2StatusCode ;
@@ -49,6 +50,8 @@ pub enum Command {
4950 AuthenticatorConfig ( AuthenticatorConfigParameters ) ,
5051 // Vendor specific commands
5152 AuthenticatorVendorConfigure ( AuthenticatorVendorConfigureParameters ) ,
53+ AuthenticatorVendorUpgrade ( AuthenticatorVendorUpgradeParameters ) ,
54+ AuthenticatorVendorUpgradeInfo ,
5255}
5356
5457impl Command {
@@ -66,6 +69,8 @@ impl Command {
6669 const AUTHENTICATOR_CONFIG : u8 = 0x0D ;
6770 const _AUTHENTICATOR_VENDOR_FIRST: u8 = 0x40 ;
6871 const AUTHENTICATOR_VENDOR_CONFIGURE : u8 = 0x40 ;
72+ const AUTHENTICATOR_VENDOR_UPGRADE : u8 = 0x41 ;
73+ const AUTHENTICATOR_VENDOR_UPGRADE_INFO : u8 = 0x42 ;
6974 const _AUTHENTICATOR_VENDOR_LAST: u8 = 0xBF ;
7075
7176 pub fn deserialize ( bytes : & [ u8 ] ) -> Result < Command , Ctap2StatusCode > {
@@ -134,6 +139,16 @@ impl Command {
134139 AuthenticatorVendorConfigureParameters :: try_from ( decoded_cbor) ?,
135140 ) )
136141 }
142+ Command :: AUTHENTICATOR_VENDOR_UPGRADE => {
143+ let decoded_cbor = cbor_read ( & bytes[ 1 ..] ) ?;
144+ Ok ( Command :: AuthenticatorVendorUpgrade (
145+ AuthenticatorVendorUpgradeParameters :: try_from ( decoded_cbor) ?,
146+ ) )
147+ }
148+ Command :: AUTHENTICATOR_VENDOR_UPGRADE_INFO => {
149+ // Parameters are ignored.
150+ Ok ( Command :: AuthenticatorVendorUpgradeInfo )
151+ }
137152 _ => Err ( Ctap2StatusCode :: CTAP1_ERR_INVALID_COMMAND ) ,
138153 }
139154 }
@@ -573,11 +588,47 @@ impl TryFrom<cbor::Value> for AuthenticatorVendorConfigureParameters {
573588 }
574589}
575590
591+ #[ derive( Debug , PartialEq ) ]
592+ pub struct AuthenticatorVendorUpgradeParameters {
593+ pub address : Option < usize > ,
594+ pub data : Vec < u8 > ,
595+ pub hash : Vec < u8 > ,
596+ pub signature : Option < CoseSignature > ,
597+ }
598+
599+ impl TryFrom < cbor:: Value > for AuthenticatorVendorUpgradeParameters {
600+ type Error = Ctap2StatusCode ;
601+
602+ fn try_from ( cbor_value : cbor:: Value ) -> Result < Self , Ctap2StatusCode > {
603+ destructure_cbor_map ! {
604+ let {
605+ 0x01 => address,
606+ 0x02 => data,
607+ 0x03 => hash,
608+ 0x04 => signature,
609+ } = extract_map( cbor_value) ?;
610+ }
611+ let address = address
612+ . map ( extract_unsigned)
613+ . transpose ( ) ?
614+ . map ( |u| u as usize ) ;
615+ let data = extract_byte_string ( ok_or_missing ( data) ?) ?;
616+ let hash = extract_byte_string ( ok_or_missing ( hash) ?) ?;
617+ let signature = signature. map ( CoseSignature :: try_from) . transpose ( ) ?;
618+ Ok ( AuthenticatorVendorUpgradeParameters {
619+ address,
620+ data,
621+ hash,
622+ signature,
623+ } )
624+ }
625+ }
626+
576627#[ cfg( test) ]
577628mod test {
578629 use super :: super :: data_formats:: {
579630 AuthenticatorTransport , PublicKeyCredentialRpEntity , PublicKeyCredentialType ,
580- PublicKeyCredentialUserEntity ,
631+ PublicKeyCredentialUserEntity , SignatureAlgorithm ,
581632 } ;
582633 use super :: super :: ES256_CRED_PARAM ;
583634 use super :: * ;
@@ -997,7 +1048,7 @@ mod test {
9971048 0x02 => cbor_map! {
9981049 0x01 => dummy_cert,
9991050 0x02 => dummy_pkey
1000- }
1051+ } ,
10011052 } ;
10021053 assert_eq ! (
10031054 AuthenticatorVendorConfigureParameters :: try_from( cbor_value) ,
@@ -1006,8 +1057,81 @@ mod test {
10061057 attestation_material: Some ( AuthenticatorAttestationMaterial {
10071058 certificate: dummy_cert. to_vec( ) ,
10081059 private_key: dummy_pkey
1009- } )
1060+ } ) ,
10101061 } )
10111062 ) ;
10121063 }
1064+
1065+ #[ test]
1066+ fn test_vendor_upgrade ( ) {
1067+ // Incomplete command
1068+ let cbor_bytes = vec ! [ Command :: AUTHENTICATOR_VENDOR_UPGRADE ] ;
1069+ let command = Command :: deserialize ( & cbor_bytes) ;
1070+ assert_eq ! ( command, Err ( Ctap2StatusCode :: CTAP2_ERR_INVALID_CBOR ) ) ;
1071+
1072+ // Missing data
1073+ let cbor_value = cbor_map ! {
1074+ 0x01 => 0x1000 ,
1075+ 0x03 => [ 0x44 ; 32 ] ,
1076+ } ;
1077+ assert_eq ! (
1078+ AuthenticatorVendorUpgradeParameters :: try_from( cbor_value) ,
1079+ Err ( Ctap2StatusCode :: CTAP2_ERR_MISSING_PARAMETER )
1080+ ) ;
1081+
1082+ // Missing hash
1083+ let cbor_value = cbor_map ! {
1084+ 0x01 => 0x1000 ,
1085+ 0x02 => [ 0xFF ; 0x100 ] ,
1086+ } ;
1087+ assert_eq ! (
1088+ AuthenticatorVendorUpgradeParameters :: try_from( cbor_value) ,
1089+ Err ( Ctap2StatusCode :: CTAP2_ERR_MISSING_PARAMETER )
1090+ ) ;
1091+
1092+ // Valid without address
1093+ let cbor_value = cbor_map ! {
1094+ 0x02 => [ 0xFF ; 0x100 ] ,
1095+ 0x03 => [ 0x44 ; 32 ] ,
1096+ 0x04 => cbor_map! {
1097+ "alg" => -7 ,
1098+ "signature" => [ 0x55 ; 64 ] ,
1099+ } ,
1100+ } ;
1101+ assert_eq ! (
1102+ AuthenticatorVendorUpgradeParameters :: try_from( cbor_value) ,
1103+ Ok ( AuthenticatorVendorUpgradeParameters {
1104+ address: None ,
1105+ data: vec![ 0xFF ; 0x100 ] ,
1106+ hash: vec![ 0x44 ; 32 ] ,
1107+ signature: Some ( CoseSignature {
1108+ algorithm: SignatureAlgorithm :: ES256 ,
1109+ bytes: [ 0x55 ; 64 ] ,
1110+ } ) ,
1111+ } )
1112+ ) ;
1113+
1114+ // Valid without signature
1115+ let cbor_value = cbor_map ! {
1116+ 0x01 => 0x1000 ,
1117+ 0x02 => [ 0xFF ; 0x100 ] ,
1118+ 0x03 => [ 0x44 ; 32 ] ,
1119+ } ;
1120+ assert_eq ! (
1121+ AuthenticatorVendorUpgradeParameters :: try_from( cbor_value) ,
1122+ Ok ( AuthenticatorVendorUpgradeParameters {
1123+ address: Some ( 0x1000 ) ,
1124+ data: vec![ 0xFF ; 0x100 ] ,
1125+ hash: vec![ 0x44 ; 32 ] ,
1126+ signature: None ,
1127+ } )
1128+ ) ;
1129+ }
1130+
1131+ #[ test]
1132+ fn test_deserialize_vendor_upgrade_info ( ) {
1133+ let cbor_bytes = [ Command :: AUTHENTICATOR_VENDOR_UPGRADE_INFO ] ;
1134+ let command = Command :: deserialize ( & cbor_bytes) ;
1135+ assert_eq ! ( command, Ok ( Command :: AuthenticatorVendorUpgradeInfo ) ) ;
1136+ }
10131137}
0 commit comments