e51ba5fde6a8ef4f490867fabafc7bbd572e4eee
[WebKit-https.git] / LayoutTests / http / wpt / webauthn / public-key-credential-create-success-local.https.html
1 <!DOCTYPE html>
2 <title>Web Authentication API: PublicKeyCredential's [[create]] success cases with a mock local authenticator.</title>
3 <script src="/resources/testharness.js"></script>
4 <script src="/resources/testharnessreport.js"></script>
5 <script src="./resources/util.js"></script>
6 <script src="./resources/cbor.js"></script>
7 <script>
8     (async function() {
9         const userhandleBase64 = generateUserhandleBase64();
10         const privateKeyBase64 = await generatePrivateKeyBase64();
11         const credentialID = await calculateCredentialID(privateKeyBase64);
12         // Default mock configuration. Tests need to override if they need different configuration.
13         if (window.testRunner)
14             testRunner.setWebAuthenticationMockConfiguration({
15                 local: {
16                     acceptAuthentication: true,
17                     acceptAttestation: true,
18                     privateKeyBase64: privateKeyBase64,
19                     userCertificateBase64: testAttestationCertificateBase64,
20                     intermediateCACertificateBase64: testAttestationIssuingCACertificateBase64
21                 }
22             });
23
24         function checkResult(credential, isNoneAttestation = true)
25         {
26             // Check keychain
27             if (window.testRunner) {
28                 assert_true(testRunner.keyExistsInKeychain(testRpId, userhandleBase64));
29                 testRunner.cleanUpKeychain(testRpId, userhandleBase64);
30             }
31
32             // Check respond
33             assert_array_equals(Base64URL.parse(credential.id), credentialID);
34             assert_equals(credential.type, 'public-key');
35             assert_array_equals(new Uint8Array(credential.rawId), credentialID);
36             assert_equals(bytesToASCIIString(credential.response.clientDataJSON), '{"type":"webauthn.create","challenge":"MTIzNDU2","origin":"https://localhost:9443"}');
37             assert_not_own_property(credential.getClientExtensionResults(), "appid");
38
39             // Check attestation
40             const attestationObject = CBOR.decode(credential.response.attestationObject);
41             if (isNoneAttestation)
42                 assert_equals(attestationObject.fmt, "none");
43             else
44                 assert_equals(attestationObject.fmt, "Apple");
45             // Check authData
46             const authData = decodeAuthData(attestationObject.authData);
47             assert_equals(bytesToHexString(authData.rpIdHash), "49960de5880e8c687434170f6476605b8fe4aeb9a28632c7995cf3ba831d9763");
48             assert_equals(authData.flags, 69);
49             assert_equals(authData.counter, 0);
50             assert_equals(bytesToHexString(authData.aaguid), "00000000000000000000000000000000");
51             assert_array_equals(authData.credentialID, credentialID);
52             // Check self attestation
53             assert_true(checkPublicKey(authData.publicKey));
54             if (isNoneAttestation)
55                 assert_object_equals(attestationObject.attStmt, { });
56             else {
57                 assert_equals(attestationObject.attStmt.alg, -7);
58                 assert_equals(attestationObject.attStmt.x5c.length, 2);
59                 assert_array_equals(attestationObject.attStmt.x5c[0], Base64URL.parse(testAttestationCertificateBase64));
60                 assert_array_equals(attestationObject.attStmt.x5c[1], Base64URL.parse(testAttestationIssuingCACertificateBase64));
61
62                 // Check signature
63                 let publicKeyData = new Uint8Array(65);
64                 publicKeyData[0] = 0x04;
65                 publicKeyData.set(authData.publicKey['-2'], 1);
66                 publicKeyData.set(authData.publicKey['-3'], 33);
67                 return crypto.subtle.importKey("raw", publicKeyData, {
68                     name: "ECDSA",
69                     namedCurve: "P-256"
70                 }, false, ['verify']).then(publicKey => {
71                     return crypto.subtle.verify({
72                         name: "ECDSA",
73                         hash: "SHA-256"
74                     }, publicKey, extractRawSignature(attestationObject.attStmt.sig), attestationObject.authData).then(verified => {
75                         assert_true(verified);
76                     });
77                 });
78             }
79         }
80
81         promise_test(t => {
82             const options = {
83                 publicKey: {
84                     rp: {
85                         name: "localhost",
86                     },
87                     user: {
88                         name: userhandleBase64,
89                         id: Base64URL.parse(userhandleBase64),
90                         displayName: "Appleseed",
91                     },
92                     challenge: Base64URL.parse("MTIzNDU2"),
93                     pubKeyCredParams: [{ type: "public-key", alg: -7 }],
94                 }
95             };
96
97             return navigator.credentials.create(options).then(credential => {
98                 checkResult(credential);
99             });
100         }, "PublicKeyCredential's [[create]] with minimum options in a mock local authenticator.");
101
102         promise_test(t => {
103             const options = {
104                 publicKey: {
105                     rp: {
106                         name: "localhost",
107                     },
108                     user: {
109                         name: userhandleBase64,
110                         id: Base64URL.parse(userhandleBase64),
111                         displayName: "Appleseed",
112                     },
113                     challenge: Base64URL.parse("MTIzNDU2"),
114                     pubKeyCredParams: [{ type: "public-key", alg: -7 }],
115                     authenticatorSelection: { authenticatorAttachment: "platform" }
116                 }
117             };
118
119             return navigator.credentials.create(options).then(credential => {
120                 checkResult(credential);
121             });
122         }, "PublicKeyCredential's [[create]] with authenticatorSelection { 'platform' } in a mock local authenticator.");
123
124         promise_test(t => {
125             const options = {
126                 publicKey: {
127                     rp: {
128                         name: "example.com"
129                     },
130                     user: {
131                         name: userhandleBase64,
132                         id: Base64URL.parse(userhandleBase64),
133                         displayName: "John",
134                     },
135                     challenge: asciiToUint8Array("123456"),
136                     pubKeyCredParams: [{ type: "public-key", alg: -7 }],
137                     excludeCredentials: [
138                         { type: "public-key", id: credentialID, transports: ["usb"] },
139                         { type: "public-key", id: credentialID, transports: ["nfc"] },
140                         { type: "public-key", id: credentialID, transports: ["ble"] }
141                     ]
142                 }
143             };
144             if (window.testRunner)
145                 testRunner.addTestKeyToKeychain(testES256PrivateKeyBase64, testRpId, userhandleBase64);
146
147             return navigator.credentials.create(options).then(credential => {
148                 checkResult(credential);
149             });
150         }, "PublicKeyCredential's [[create]] with matched exclude credential ids but not transports in a mock local authenticator.");
151
152         promise_test(t => {
153             const options = {
154                 publicKey: {
155                     rp: {
156                         name: "localhost",
157                     },
158                     user: {
159                         name: userhandleBase64,
160                         id: Base64URL.parse(userhandleBase64),
161                         displayName: "Appleseed",
162                     },
163                     challenge: Base64URL.parse("MTIzNDU2"),
164                     pubKeyCredParams: [{ type: "public-key", alg: -7 }],
165                     attestation: "none"
166                 }
167             };
168
169             return navigator.credentials.create(options).then(credential => {
170                 checkResult(credential);
171             });
172         }, "PublicKeyCredential's [[create]] with none attestation in a mock local authenticator.");
173
174         promise_test(t => {
175             const options = {
176                 publicKey: {
177                     rp: {
178                         name: "localhost",
179                     },
180                     user: {
181                         name: userhandleBase64,
182                         id: Base64URL.parse(userhandleBase64),
183                         displayName: "Appleseed",
184                     },
185                     challenge: Base64URL.parse("MTIzNDU2"),
186                     pubKeyCredParams: [{ type: "public-key", alg: -7 }],
187                     attestation: "indirect"
188                 }
189             };
190
191             return navigator.credentials.create(options).then(credential => {
192                 checkResult(credential, false);
193             });
194         }, "PublicKeyCredential's [[create]] with indirect attestation in a mock local authenticator.");
195
196         promise_test(t => {
197             const options = {
198                 publicKey: {
199                     rp: {
200                         name: "localhost",
201                     },
202                     user: {
203                         name: userhandleBase64,
204                         id: Base64URL.parse(userhandleBase64),
205                         displayName: "Appleseed",
206                     },
207                     challenge: Base64URL.parse("MTIzNDU2"),
208                     pubKeyCredParams: [{ type: "public-key", alg: -7 }],
209                     attestation: "direct"
210                 }
211             };
212
213             return navigator.credentials.create(options).then(credential => {
214                 checkResult(credential, false);
215             });
216         }, "PublicKeyCredential's [[create]] with direct attestation in a mock local authenticator.");
217     })();
218 </script>