@@ -81,6 +81,7 @@ public Apple()
8181 }
8282 }
8383 }
84+
8485 [ Fact ]
8586 public void TestAppleMissingX5c ( )
8687 {
@@ -89,6 +90,7 @@ public void TestAppleMissingX5c()
8990 var ex = Assert . ThrowsAsync < Fido2VerificationException > ( ( ) => MakeAttestationResponse ( ) ) ;
9091 Assert . Equal ( "Malformed x5c in Apple attestation" , ex . Result . Message ) ;
9192 }
93+
9294 [ Fact ]
9395 public void TestAppleX5cNotArray ( )
9496 {
@@ -97,6 +99,7 @@ public void TestAppleX5cNotArray()
9799 var ex = Assert . ThrowsAsync < Fido2VerificationException > ( ( ) => MakeAttestationResponse ( ) ) ;
98100 Assert . Equal ( "Malformed x5c in Apple attestation" , ex . Result . Message ) ;
99101 }
102+
100103 [ Fact ]
101104 public void TestAppleX5cCountNotOne ( )
102105 {
@@ -106,6 +109,7 @@ public void TestAppleX5cCountNotOne()
106109 var ex = Assert . ThrowsAsync < Fido2VerificationException > ( ( ) => MakeAttestationResponse ( ) ) ;
107110 Assert . Equal ( "Malformed x5c in Apple attestation" , ex . Result . Message ) ;
108111 }
112+
109113 [ Fact ]
110114 public void TestAppleX5cValueNotByteString ( )
111115 {
@@ -114,6 +118,7 @@ public void TestAppleX5cValueNotByteString()
114118 var ex = Assert . ThrowsAsync < Fido2VerificationException > ( ( ) => MakeAttestationResponse ( ) ) ;
115119 Assert . Equal ( "Malformed x5c in Apple attestation" , ex . Result . Message ) ;
116120 }
121+
117122 [ Fact ]
118123 public void TestAppleX5cValueZeroLengthByteString ( )
119124 {
@@ -123,6 +128,50 @@ public void TestAppleX5cValueZeroLengthByteString()
123128 Assert . Equal ( "Malformed x5c in Apple attestation" , ex . Result . Message ) ;
124129 }
125130
131+ [ Fact ]
132+ public void TestAppleCertMissingExtension ( )
133+ {
134+ var invalidX5cStrings = validX5cStrings ;
135+ var invalidCert = Convert . FromBase64String ( invalidX5cStrings [ 0 ] ) ;
136+ invalidCert [ 424 ] = 0x42 ;
137+ invalidX5cStrings [ 0 ] = Convert . ToBase64String ( invalidCert ) ;
138+
139+ var trustPath = invalidX5cStrings
140+ . Select ( x => new X509Certificate2 ( Convert . FromBase64String ( x ) ) )
141+ . ToArray ( ) ;
142+
143+ var x5c = new CborArray {
144+ trustPath [ 0 ] . RawData ,
145+ trustPath [ 1 ] . RawData
146+ } ;
147+ var attStmt = ( CborMap ) _attestationObject [ "attStmt" ] ;
148+ attStmt . Set ( "x5c" , x5c ) ;
149+ var ex = Assert . ThrowsAsync < Fido2VerificationException > ( ( ) => MakeAttestationResponse ( ) ) ;
150+ Assert . Equal ( "Extension with OID 1.2.840.113635.100.8.2 not found on Apple attestation credCert" , ex . Result . Message ) ;
151+ }
152+
153+ [ Fact ]
154+ public void TestAppleCertCorruptExtension ( )
155+ {
156+ var invalidX5cStrings = validX5cStrings ;
157+ var invalidCert = Convert . FromBase64String ( invalidX5cStrings [ 0 ] ) ;
158+ invalidCert [ 429 ] = 0x03 ;
159+ invalidX5cStrings [ 0 ] = Convert . ToBase64String ( invalidCert ) ;
160+
161+ var trustPath = invalidX5cStrings
162+ . Select ( x => new X509Certificate2 ( Convert . FromBase64String ( x ) ) )
163+ . ToArray ( ) ;
164+
165+ var x5c = new CborArray {
166+ trustPath [ 0 ] . RawData ,
167+ trustPath [ 1 ] . RawData
168+ } ;
169+ var attStmt = ( CborMap ) _attestationObject [ "attStmt" ] ;
170+ attStmt . Set ( "x5c" , x5c ) ;
171+ var ex = Assert . ThrowsAsync < Fido2VerificationException > ( ( ) => MakeAttestationResponse ( ) ) ;
172+ Assert . Equal ( "Apple attestation extension has invalid data" , ex . Result . Message ) ;
173+ }
174+
126175 [ Fact ]
127176 public void TestAppleInvalidNonce ( )
128177 {
@@ -145,27 +194,38 @@ public void TestApplePublicKeyMismatch()
145194 {
146195 var cpkBytes = new byte [ ] { 0xa5 , 0x01 , 0x02 , 0x03 , 0x26 , 0x20 , 0x01 , 0x21 , 0x58 , 0x20 , 0x79 , 0xfe , 0x59 , 0x08 , 0xbb , 0x51 , 0x29 , 0xc8 , 0x09 , 0x38 , 0xb7 , 0x54 , 0xc0 , 0x4d , 0x2b , 0x34 , 0x0e , 0xfa , 0x66 , 0x15 , 0xb9 , 0x87 , 0x69 , 0x8b , 0xf5 , 0x9d , 0xa4 , 0xe5 , 0x3e , 0xa3 , 0xe6 , 0xfe , 0x22 , 0x58 , 0x20 , 0xfb , 0x03 , 0xda , 0xa1 , 0x27 , 0x0d , 0x58 , 0x04 , 0xe8 , 0xab , 0x61 , 0xc1 , 0x5a , 0xac , 0xa2 , 0x43 , 0x5c , 0x7d , 0xbf , 0x36 , 0x9d , 0x71 , 0xca , 0x15 , 0xc5 , 0x23 , 0xb0 , 0x00 , 0x4a , 0x1b , 0x75 , 0xb7 } ;
147196 _credentialPublicKey = new CredentialPublicKey ( cpkBytes ) ;
148- var trustPath = validX5cStrings
149- . Select ( x => new X509Certificate2 ( Convert . FromBase64String ( x ) ) )
150- . ToArray ( ) ;
151-
152- var X5c = new CborArray {
153- { trustPath [ 0 ] . RawData } ,
154- { trustPath [ 1 ] . RawData }
155- } ;
156-
157- ( ( CborMap ) _attestationObject [ "attStmt" ] ) . Set ( "x5c" , X5c ) ;
158197
159198 var authData = new AuthenticatorData ( _rpIdHash , _flags , _signCount , _acd , _exts ) . ToByteArray ( ) ;
160199 _attestationObject . Set ( "authData" , new CborByteString ( authData ) ) ;
161200 var clientData = new
162201 {
163202 type = "webauthn.create" ,
164203 challenge = _challenge ,
165- origin = "6cc3c9e7967a.ngrok.io " ,
204+ origin = "https://www.passwordless.dev " ,
166205 } ;
167206 var clientDataJson = JsonSerializer . SerializeToUtf8Bytes ( clientData ) ;
168207
208+ var data = DataHelper . Concat ( authData , SHA256 . HashData ( clientDataJson ) ) ;
209+ Span < byte > dataHash = stackalloc byte [ 32 ] ;
210+ SHA256 . HashData ( data , dataHash ) ;
211+
212+ var invalidX5cStrings = validX5cStrings ;
213+ var invalidCert = Convert . FromBase64String ( invalidX5cStrings [ 0 ] ) ;
214+ Buffer . BlockCopy ( dataHash . ToArray ( ) , 0 , invalidCert , 433 , 32 ) ;
215+ invalidCert [ 485 ] = 0xdb ;
216+ invalidX5cStrings [ 0 ] = Convert . ToBase64String ( invalidCert ) ;
217+
218+ var trustPath = invalidX5cStrings
219+ . Select ( x => new X509Certificate2 ( Convert . FromBase64String ( x ) ) )
220+ . ToArray ( ) ;
221+
222+ var X5c = new CborArray {
223+ { trustPath [ 0 ] . RawData } ,
224+ { trustPath [ 1 ] . RawData }
225+ } ;
226+
227+ ( ( CborMap ) _attestationObject [ "attStmt" ] ) . Set ( "x5c" , X5c ) ;
228+
169229 var attestationResponse = new AuthenticatorAttestationRawResponse
170230 {
171231 Type = PublicKeyCredentialType . PublicKey ,
@@ -193,7 +253,7 @@ public void TestApplePublicKeyMismatch()
193253 {
194254 new PubKeyCredParam ( COSE . Algorithm . ES256 )
195255 } ,
196- Rp = new PublicKeyCredentialRpEntity ( "6cc3c9e7967a.ngrok.io " , "6cc3c9e7967a.ngrok.io" , "" ) ,
256+ Rp = new PublicKeyCredentialRpEntity ( "https://www.passwordless.dev " , "6cc3c9e7967a.ngrok.io" , "" ) ,
197257 Status = "ok" ,
198258 User = new Fido2User
199259 {
@@ -213,7 +273,7 @@ public void TestApplePublicKeyMismatch()
213273 {
214274 ServerDomain = "6cc3c9e7967a.ngrok.io" ,
215275 ServerName = "6cc3c9e7967a.ngrok.io" ,
216- Origins = new HashSet < string > { "https://6cc3c9e7967a.ngrok.io" } ,
276+ Origin = "https://www.passwordless.dev" ,
217277 } ) ;
218278
219279 var credentialMakeResult = lib . MakeNewCredentialAsync ( attestationResponse , origChallenge , callback ) ;
0 commit comments