Title: [245638] trunk
Revision
245638
Author
jiewen_...@apple.com
Date
2019-05-22 12:27:49 -0700 (Wed, 22 May 2019)

Log Message

[WebAuthN] Support Attestation Conveyance Preference
https://bugs.webkit.org/show_bug.cgi?id=192722
<rdar://problem/49939647>

Reviewed by Brent Fulgham.

Source/WebCore:

This patch implements https://www.w3.org/TR/webauthn/#enumdef-attestationconveyancepreference, together with
Step 20 with regard to AttestationConveyancePreference of https://www.w3.org/TR/webauthn/#createCredential.
Few notes with regard to Step 20: 1) We treat indirect attestation as direct attestation as we don't MITM
the attestation process; 2) We won't distinguish self attestation and return it to keep consistency between
the response and the request. If callers want none attestation, they will very likely ignore fmt and attStmt
of the attestation object, and therefore it is meaningless to return self attestation.

Covered by new tests within existing files.

* CMakeLists.txt:
* DerivedSources-input.xcfilelist:
* DerivedSources-output.xcfilelist:
* DerivedSources.make:
* Headers.cmake:
* Modules/webauthn/AttestationConveyancePreference.h: Copied from Source/WebCore/Modules/webauthn/WebAuthenticationUtils.h.
* Modules/webauthn/AttestationConveyancePreference.idl: Copied from Source/WebCore/Modules/webauthn/WebAuthenticationUtils.h.
* Modules/webauthn/PublicKeyCredentialCreationOptions.h:
(WebCore::PublicKeyCredentialCreationOptions::encode const):
(WebCore::PublicKeyCredentialCreationOptions::decode):
* Modules/webauthn/PublicKeyCredentialCreationOptions.idl:
* Modules/webauthn/WebAuthenticationConstants.h:
* Modules/webauthn/WebAuthenticationUtils.cpp:
(WebCore::buildAttestationObject):
* Modules/webauthn/WebAuthenticationUtils.h:
* Modules/webauthn/fido/DeviceResponseConverter.cpp:
(fido::readCTAPMakeCredentialResponse):
* Modules/webauthn/fido/DeviceResponseConverter.h:
* Modules/webauthn/fido/FidoConstants.h:
noneAttestationValue is moved to WebAuthenticationConstants.h.
* Modules/webauthn/fido/U2fResponseConverter.cpp:
(fido::readU2fRegisterResponse):
* Modules/webauthn/fido/U2fResponseConverter.h:
* Sources.txt:
* WebCore.xcodeproj/project.pbxproj:

Source/WebKit:

* UIProcess/WebAuthentication/Cocoa/LocalAuthenticator.mm:
(WebKit::LocalAuthenticator::continueMakeCredentialAfterAttested):
* UIProcess/WebAuthentication/fido/CtapHidAuthenticator.cpp:
(WebKit::CtapHidAuthenticator::continueMakeCredentialAfterResponseReceived const):
* UIProcess/WebAuthentication/fido/U2fHidAuthenticator.cpp:
(WebKit::U2fHidAuthenticator::continueRegisterCommandAfterResponseReceived):

Tools:

* TestWebKitAPI/Tests/WebCore/CtapRequestTest.cpp:
(TestWebKitAPI::TEST):
Updates the test with AttestationConveyancePreference.

LayoutTests:

* http/wpt/webauthn/public-key-credential-create-success-hid.https-expected.txt:
* http/wpt/webauthn/public-key-credential-create-success-hid.https.html:
* http/wpt/webauthn/public-key-credential-create-success-local.https-expected.txt:
* http/wpt/webauthn/public-key-credential-create-success-local.https.html:
* http/wpt/webauthn/public-key-credential-create-success-u2f.https-expected.txt:
* http/wpt/webauthn/public-key-credential-create-success-u2f.https.html:

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (245637 => 245638)


--- trunk/LayoutTests/ChangeLog	2019-05-22 19:13:34 UTC (rev 245637)
+++ trunk/LayoutTests/ChangeLog	2019-05-22 19:27:49 UTC (rev 245638)
@@ -1,3 +1,18 @@
+2019-05-22  Jiewen Tan  <jiewen_...@apple.com>
+
+        [WebAuthN] Support Attestation Conveyance Preference
+        https://bugs.webkit.org/show_bug.cgi?id=192722
+        <rdar://problem/49939647>
+
+        Reviewed by Brent Fulgham.
+
+        * http/wpt/webauthn/public-key-credential-create-success-hid.https-expected.txt:
+        * http/wpt/webauthn/public-key-credential-create-success-hid.https.html:
+        * http/wpt/webauthn/public-key-credential-create-success-local.https-expected.txt:
+        * http/wpt/webauthn/public-key-credential-create-success-local.https.html:
+        * http/wpt/webauthn/public-key-credential-create-success-u2f.https-expected.txt:
+        * http/wpt/webauthn/public-key-credential-create-success-u2f.https.html:
+
 2019-05-22  Jer Noble  <jer.no...@apple.com>
 
         Hide MediaCapabilities.encodingInfo() when the platform does not support it.

Modified: trunk/LayoutTests/http/wpt/webauthn/public-key-credential-create-success-hid.https-expected.txt (245637 => 245638)


--- trunk/LayoutTests/http/wpt/webauthn/public-key-credential-create-success-hid.https-expected.txt	2019-05-22 19:13:34 UTC (rev 245637)
+++ trunk/LayoutTests/http/wpt/webauthn/public-key-credential-create-success-hid.https-expected.txt	2019-05-22 19:27:49 UTC (rev 245638)
@@ -6,4 +6,7 @@
 PASS PublicKeyCredential's [[create]] with userVerification { 'discouraged' } in a mock local authenticator. 
 PASS PublicKeyCredential's [[create]] with mixed options in a mock local authenticator. 
 PASS PublicKeyCredential's [[create]] with two consecutive requests. 
+PASS PublicKeyCredential's [[create]] with none attestation in a mock local authenticator. 
+PASS PublicKeyCredential's [[create]] with direct attestation in a mock local authenticator. 
+PASS PublicKeyCredential's [[create]] with indirect attestation in a mock local authenticator. 
 

Modified: trunk/LayoutTests/http/wpt/webauthn/public-key-credential-create-success-hid.https.html (245637 => 245638)


--- trunk/LayoutTests/http/wpt/webauthn/public-key-credential-create-success-hid.https.html	2019-05-22 19:13:34 UTC (rev 245637)
+++ trunk/LayoutTests/http/wpt/webauthn/public-key-credential-create-success-hid.https.html	2019-05-22 19:27:49 UTC (rev 245638)
@@ -9,7 +9,7 @@
     if (window.testRunner)
         testRunner.setWebAuthenticationMockConfiguration({ hid: { stage: "request", subStage: "msg", error: "success", payloadBase64: [testCreationMessageBase64] } });
 
-    function checkResult(credential)
+    function checkResult(credential, isNoneAttestation = true)
     {
         // Check response
         assert_array_equals(Base64URL.parse(credential.id), Base64URL.parse(testHidCredentialIdBase64));
@@ -20,18 +20,28 @@
 
         // Check attestation
         const attestationObject = CBOR.decode(credential.response.attestationObject);
-        assert_equals(attestationObject.fmt, "packed");
+        if (isNoneAttestation)
+            assert_equals(attestationObject.fmt, "none");
+        else
+            assert_equals(attestationObject.fmt, "packed");
         // Check authData
         const authData = decodeAuthData(attestationObject.authData);
         assert_equals(bytesToHexString(authData.rpIdHash), "46cc7fb9679d55b2db9092e1c8d9e5e1d02b7580f0b4812c770962e1e48f5ad8");
         assert_equals(authData.flags, 65);
         assert_equals(authData.counter, 78);
-        assert_equals(bytesToHexString(authData.aaguid), "f8a011f38c0a4d15800617111f9edc7d");
+        if (isNoneAttestation)
+            assert_equals(bytesToHexString(authData.aaguid), "00000000000000000000000000000000");
+        else
+            assert_equals(bytesToHexString(authData.aaguid), "f8a011f38c0a4d15800617111f9edc7d");
         assert_array_equals(authData.credentialID, Base64URL.parse(testHidCredentialIdBase64));
         // Check packed attestation
-        assert_equals(attestationObject.attStmt.alg, -7);
         assert_true(checkPublicKey(authData.publicKey));
-        assert_equals(attestationObject.attStmt.x5c.length, 1);
+        if (isNoneAttestation)
+            assert_object_equals(attestationObject.attStmt, { });
+        else {
+            assert_equals(attestationObject.attStmt.alg, -7);
+            assert_equals(attestationObject.attStmt.x5c.length, 1);
+        }
     }
 
     promise_test(t => {
@@ -193,4 +203,73 @@
             checkResult(credential);
         });
     }, "PublicKeyCredential's [[create]] with two consecutive requests.");
+
+    promise_test(t => {
+        const options = {
+            publicKey: {
+                rp: {
+                    name: "localhost",
+                },
+                user: {
+                    name: "John Appleseed",
+                    id: Base64URL.parse(testUserhandleBase64),
+                    displayName: "Appleseed",
+                },
+                challenge: Base64URL.parse("MTIzNDU2"),
+                pubKeyCredParams: [{ type: "public-key", alg: -7 }],
+                attestation: "none",
+                timeout: 100
+            }
+        };
+
+        return navigator.credentials.create(options).then(credential => {
+            checkResult(credential);
+        });
+    }, "PublicKeyCredential's [[create]] with none attestation in a mock local authenticator.");
+
+    promise_test(t => {
+        const options = {
+            publicKey: {
+                rp: {
+                    name: "localhost",
+                },
+                user: {
+                    name: "John Appleseed",
+                    id: Base64URL.parse(testUserhandleBase64),
+                    displayName: "Appleseed",
+                },
+                challenge: Base64URL.parse("MTIzNDU2"),
+                pubKeyCredParams: [{ type: "public-key", alg: -7 }],
+                attestation: "direct",
+                timeout: 100
+            }
+        };
+
+        return navigator.credentials.create(options).then(credential => {
+            checkResult(credential, false);
+        });
+    }, "PublicKeyCredential's [[create]] with direct attestation in a mock local authenticator.");
+
+    promise_test(t => {
+        const options = {
+            publicKey: {
+                rp: {
+                    name: "localhost",
+                },
+                user: {
+                    name: "John Appleseed",
+                    id: Base64URL.parse(testUserhandleBase64),
+                    displayName: "Appleseed",
+                },
+                challenge: Base64URL.parse("MTIzNDU2"),
+                pubKeyCredParams: [{ type: "public-key", alg: -7 }],
+                attestation: "indirect",
+                timeout: 100
+            }
+        };
+
+        return navigator.credentials.create(options).then(credential => {
+            checkResult(credential, false);
+        });
+    }, "PublicKeyCredential's [[create]] with indirect attestation in a mock local authenticator.");
 </script>

Modified: trunk/LayoutTests/http/wpt/webauthn/public-key-credential-create-success-local.https-expected.txt (245637 => 245638)


--- trunk/LayoutTests/http/wpt/webauthn/public-key-credential-create-success-local.https-expected.txt	2019-05-22 19:13:34 UTC (rev 245637)
+++ trunk/LayoutTests/http/wpt/webauthn/public-key-credential-create-success-local.https-expected.txt	2019-05-22 19:27:49 UTC (rev 245638)
@@ -2,4 +2,7 @@
 PASS PublicKeyCredential's [[create]] with minimum options in a mock local authenticator. 
 PASS PublicKeyCredential's [[create]] with authenticatorSelection { 'platform' } in a mock local authenticator. 
 PASS PublicKeyCredential's [[create]] with matched exclude credential ids but not transports in a mock local authenticator. 
+PASS PublicKeyCredential's [[create]] with none attestation in a mock local authenticator. 
+PASS PublicKeyCredential's [[create]] with indirect attestation in a mock local authenticator. 
+PASS PublicKeyCredential's [[create]] with direct attestation in a mock local authenticator. 
 

Modified: trunk/LayoutTests/http/wpt/webauthn/public-key-credential-create-success-local.https.html (245637 => 245638)


--- trunk/LayoutTests/http/wpt/webauthn/public-key-credential-create-success-local.https.html	2019-05-22 19:13:34 UTC (rev 245637)
+++ trunk/LayoutTests/http/wpt/webauthn/public-key-credential-create-success-local.https.html	2019-05-22 19:27:49 UTC (rev 245638)
@@ -17,7 +17,7 @@
             }
         });
 
-    function checkResult(credential)
+    function checkResult(credential, isNoneAttestation = true)
     {
         // Check keychain
         if (window.testRunner) {
@@ -34,7 +34,10 @@
 
         // Check attestation
         const attestationObject = CBOR.decode(credential.response.attestationObject);
-        assert_equals(attestationObject.fmt, "Apple");
+        if (isNoneAttestation)
+            assert_equals(attestationObject.fmt, "none");
+        else
+            assert_equals(attestationObject.fmt, "Apple");
         // Check authData
         const authData = decodeAuthData(attestationObject.authData);
         assert_equals(bytesToHexString(authData.rpIdHash), "49960de5880e8c687434170f6476605b8fe4aeb9a28632c7995cf3ba831d9763");
@@ -43,22 +46,32 @@
         assert_equals(bytesToHexString(authData.aaguid), "00000000000000000000000000000000");
         assert_array_equals(authData.credentialID, Base64URL.parse(testCredentialIdBase64));
         // Check self attestation
-        assert_equals(attestationObject.attStmt.alg, -7);
         assert_true(checkPublicKey(authData.publicKey));
-        assert_equals(attestationObject.attStmt.x5c.length, 2);
-        assert_array_equals(attestationObject.attStmt.x5c[0], Base64URL.parse(testAttestationCertificateBase64));
-        assert_array_equals(attestationObject.attStmt.x5c[1], Base64URL.parse(testAttestationIssuingCACertificateBase64));
+        if (isNoneAttestation)
+            assert_object_equals(attestationObject.attStmt, { });
+        else {
+            assert_equals(attestationObject.attStmt.alg, -7);
+            assert_equals(attestationObject.attStmt.x5c.length, 2);
+            assert_array_equals(attestationObject.attStmt.x5c[0], Base64URL.parse(testAttestationCertificateBase64));
+            assert_array_equals(attestationObject.attStmt.x5c[1], Base64URL.parse(testAttestationIssuingCACertificateBase64));
 
-        // Check signature
-        let publicKeyData = new Uint8Array(65);
-        publicKeyData[0] = 0x04;
-        publicKeyData.set(authData.publicKey['-2'], 1);
-        publicKeyData.set(authData.publicKey['-3'], 33);
-        return crypto.subtle.importKey("raw", publicKeyData, { name: "ECDSA", namedCurve: "P-256" }, false, ['verify']).then( publicKey => {
-            return crypto.subtle.verify({name: "ECDSA", hash: "SHA-256"}, publicKey, extractRawSignature(attestationObject.attStmt.sig), attestationObject.authData).then( verified => {
-                assert_true(verified);
+            // Check signature
+            let publicKeyData = new Uint8Array(65);
+            publicKeyData[0] = 0x04;
+            publicKeyData.set(authData.publicKey['-2'], 1);
+            publicKeyData.set(authData.publicKey['-3'], 33);
+            return crypto.subtle.importKey("raw", publicKeyData, {
+                name: "ECDSA",
+                namedCurve: "P-256"
+            }, false, ['verify']).then(publicKey => {
+                return crypto.subtle.verify({
+                    name: "ECDSA",
+                    hash: "SHA-256"
+                }, publicKey, extractRawSignature(attestationObject.attStmt.sig), attestationObject.authData).then(verified => {
+                    assert_true(verified);
+                });
             });
-        });
+        }
     }
 
     promise_test(t => {
@@ -131,4 +144,70 @@
             checkResult(credential);
         });
     }, "PublicKeyCredential's [[create]] with matched exclude credential ids but not transports in a mock local authenticator.");
+
+    promise_test(t => {
+        const options = {
+            publicKey: {
+                rp: {
+                    name: "localhost",
+                },
+                user: {
+                    name: "John Appleseed",
+                    id: Base64URL.parse(testUserhandleBase64),
+                    displayName: "Appleseed",
+                },
+                challenge: Base64URL.parse("MTIzNDU2"),
+                pubKeyCredParams: [{ type: "public-key", alg: -7 }],
+                attestation: "none"
+            }
+        };
+
+        return navigator.credentials.create(options).then(credential => {
+            checkResult(credential);
+        });
+    }, "PublicKeyCredential's [[create]] with none attestation in a mock local authenticator.");
+
+    promise_test(t => {
+        const options = {
+            publicKey: {
+                rp: {
+                    name: "localhost",
+                },
+                user: {
+                    name: "John Appleseed",
+                    id: Base64URL.parse(testUserhandleBase64),
+                    displayName: "Appleseed",
+                },
+                challenge: Base64URL.parse("MTIzNDU2"),
+                pubKeyCredParams: [{ type: "public-key", alg: -7 }],
+                attestation: "indirect"
+            }
+        };
+
+        return navigator.credentials.create(options).then(credential => {
+            checkResult(credential, false);
+        });
+    }, "PublicKeyCredential's [[create]] with indirect attestation in a mock local authenticator.");
+
+    promise_test(t => {
+        const options = {
+            publicKey: {
+                rp: {
+                    name: "localhost",
+                },
+                user: {
+                    name: "John Appleseed",
+                    id: Base64URL.parse(testUserhandleBase64),
+                    displayName: "Appleseed",
+                },
+                challenge: Base64URL.parse("MTIzNDU2"),
+                pubKeyCredParams: [{ type: "public-key", alg: -7 }],
+                attestation: "direct"
+            }
+        };
+
+        return navigator.credentials.create(options).then(credential => {
+            checkResult(credential, false);
+        });
+    }, "PublicKeyCredential's [[create]] with direct attestation in a mock local authenticator.");
 </script>

Modified: trunk/LayoutTests/http/wpt/webauthn/public-key-credential-create-success-u2f.https-expected.txt (245637 => 245638)


--- trunk/LayoutTests/http/wpt/webauthn/public-key-credential-create-success-u2f.https-expected.txt	2019-05-22 19:13:34 UTC (rev 245637)
+++ trunk/LayoutTests/http/wpt/webauthn/public-key-credential-create-success-u2f.https-expected.txt	2019-05-22 19:27:49 UTC (rev 245638)
@@ -3,4 +3,7 @@
 PASS PublicKeyCredential's [[create]] with excludeCredentials in a mock u2f authenticator. 
 PASS PublicKeyCredential's [[create]] with excludeCredentials in a mock u2f authenticator. 2 
 PASS PublicKeyCredential's [[create]] with test of user presence in a mock u2f authenticator. 
+PASS PublicKeyCredential's [[create]] with none attestation in a mock u2f authenticator. 
+PASS PublicKeyCredential's [[create]] with indirect attestation in a mock u2f authenticator. 
+PASS PublicKeyCredential's [[create]] with direct attestation in a mock u2f authenticator. 
 

Modified: trunk/LayoutTests/http/wpt/webauthn/public-key-credential-create-success-u2f.https.html (245637 => 245638)


--- trunk/LayoutTests/http/wpt/webauthn/public-key-credential-create-success-u2f.https.html	2019-05-22 19:13:34 UTC (rev 245637)
+++ trunk/LayoutTests/http/wpt/webauthn/public-key-credential-create-success-u2f.https.html	2019-05-22 19:27:49 UTC (rev 245638)
@@ -5,7 +5,7 @@
 <script src=""
 <script src=""
 <script>
-    function checkResult(credential)
+    function checkResult(credential, isNoneAttestation = true)
     {
         // Check response
         assert_array_equals(Base64URL.parse(credential.id), Base64URL.parse(testU2fCredentialIdBase64));
@@ -16,7 +16,10 @@
 
         // Check attestation
         const attestationObject = CBOR.decode(credential.response.attestationObject);
-        assert_equals(attestationObject.fmt, "fido-u2f");
+        if (isNoneAttestation)
+            assert_equals(attestationObject.fmt, "none");
+        else
+            assert_equals(attestationObject.fmt, "fido-u2f");
         // Check authData
         const authData = decodeAuthData(attestationObject.authData);
         assert_equals(bytesToHexString(authData.rpIdHash), "49960de5880e8c687434170f6476605b8fe4aeb9a28632c7995cf3ba831d9763");
@@ -26,7 +29,10 @@
         assert_array_equals(authData.credentialID, Base64URL.parse(testU2fCredentialIdBase64));
         // Check fido-u2f attestation
         assert_true(checkPublicKey(authData.publicKey));
-        assert_equals(attestationObject.attStmt.x5c.length, 1);
+        if (isNoneAttestation)
+            assert_object_equals(attestationObject.attStmt, { });
+        else
+            assert_equals(attestationObject.attStmt.x5c.length, 1);
     }
 
     promise_test(t => {
@@ -126,4 +132,79 @@
             checkResult(credential);
         });
     }, "PublicKeyCredential's [[create]] with test of user presence in a mock u2f authenticator.");
+
+    promise_test(t => {
+        const options = {
+            publicKey: {
+                rp: {
+                    name: "localhost",
+                },
+                user: {
+                    name: "John Appleseed",
+                    id: Base64URL.parse(testUserhandleBase64),
+                    displayName: "Appleseed",
+                },
+                challenge: Base64URL.parse("MTIzNDU2"),
+                pubKeyCredParams: [{ type: "public-key", alg: -7 }],
+                attestation: "none",
+                timeout: 100
+            }
+        };
+
+        if (window.testRunner)
+            testRunner.setWebAuthenticationMockConfiguration({ hid: { stage: "request", subStage: "msg", error: "success", isU2f: true, payloadBase64: [testU2fRegisterResponse] } });
+        return navigator.credentials.create(options).then(credential => {
+            checkResult(credential);
+        });
+    }, "PublicKeyCredential's [[create]] with none attestation in a mock u2f authenticator.");
+
+    promise_test(t => {
+        const options = {
+            publicKey: {
+                rp: {
+                    name: "localhost",
+                },
+                user: {
+                    name: "John Appleseed",
+                    id: Base64URL.parse(testUserhandleBase64),
+                    displayName: "Appleseed",
+                },
+                challenge: Base64URL.parse("MTIzNDU2"),
+                pubKeyCredParams: [{ type: "public-key", alg: -7 }],
+                attestation: "indirect",
+                timeout: 100
+            }
+        };
+
+        if (window.testRunner)
+            testRunner.setWebAuthenticationMockConfiguration({ hid: { stage: "request", subStage: "msg", error: "success", isU2f: true, payloadBase64: [testU2fRegisterResponse] } });
+        return navigator.credentials.create(options).then(credential => {
+            checkResult(credential, false);
+        });
+    }, "PublicKeyCredential's [[create]] with indirect attestation in a mock u2f authenticator.");
+
+    promise_test(t => {
+        const options = {
+            publicKey: {
+                rp: {
+                    name: "localhost",
+                },
+                user: {
+                    name: "John Appleseed",
+                    id: Base64URL.parse(testUserhandleBase64),
+                    displayName: "Appleseed",
+                },
+                challenge: Base64URL.parse("MTIzNDU2"),
+                pubKeyCredParams: [{ type: "public-key", alg: -7 }],
+                attestation: "direct",
+                timeout: 100
+            }
+        };
+
+        if (window.testRunner)
+            testRunner.setWebAuthenticationMockConfiguration({ hid: { stage: "request", subStage: "msg", error: "success", isU2f: true, payloadBase64: [testU2fRegisterResponse] } });
+        return navigator.credentials.create(options).then(credential => {
+            checkResult(credential, false);
+        });
+    }, "PublicKeyCredential's [[create]] with direct attestation in a mock u2f authenticator.");
 </script>

Modified: trunk/Source/WebCore/CMakeLists.txt (245637 => 245638)


--- trunk/Source/WebCore/CMakeLists.txt	2019-05-22 19:13:34 UTC (rev 245637)
+++ trunk/Source/WebCore/CMakeLists.txt	2019-05-22 19:27:49 UTC (rev 245638)
@@ -441,6 +441,7 @@
     Modules/webaudio/ScriptProcessorNode.idl
     Modules/webaudio/WaveShaperNode.idl
 
+    Modules/webauthn/AttestationConveyancePreference.idl
     Modules/webauthn/AuthenticationExtensionsClientInputs.idl
     Modules/webauthn/AuthenticatorAssertionResponse.idl
     Modules/webauthn/AuthenticatorAttestationResponse.idl

Modified: trunk/Source/WebCore/ChangeLog (245637 => 245638)


--- trunk/Source/WebCore/ChangeLog	2019-05-22 19:13:34 UTC (rev 245637)
+++ trunk/Source/WebCore/ChangeLog	2019-05-22 19:27:49 UTC (rev 245638)
@@ -1,3 +1,46 @@
+2019-05-22  Jiewen Tan  <jiewen_...@apple.com>
+
+        [WebAuthN] Support Attestation Conveyance Preference
+        https://bugs.webkit.org/show_bug.cgi?id=192722
+        <rdar://problem/49939647>
+
+        Reviewed by Brent Fulgham.
+
+        This patch implements https://www.w3.org/TR/webauthn/#enumdef-attestationconveyancepreference, together with
+        Step 20 with regard to AttestationConveyancePreference of https://www.w3.org/TR/webauthn/#createCredential.
+        Few notes with regard to Step 20: 1) We treat indirect attestation as direct attestation as we don't MITM
+        the attestation process; 2) We won't distinguish self attestation and return it to keep consistency between
+        the response and the request. If callers want none attestation, they will very likely ignore fmt and attStmt
+        of the attestation object, and therefore it is meaningless to return self attestation.
+
+        Covered by new tests within existing files.
+
+        * CMakeLists.txt:
+        * DerivedSources-input.xcfilelist:
+        * DerivedSources-output.xcfilelist:
+        * DerivedSources.make:
+        * Headers.cmake:
+        * Modules/webauthn/AttestationConveyancePreference.h: Copied from Source/WebCore/Modules/webauthn/WebAuthenticationUtils.h.
+        * Modules/webauthn/AttestationConveyancePreference.idl: Copied from Source/WebCore/Modules/webauthn/WebAuthenticationUtils.h.
+        * Modules/webauthn/PublicKeyCredentialCreationOptions.h:
+        (WebCore::PublicKeyCredentialCreationOptions::encode const):
+        (WebCore::PublicKeyCredentialCreationOptions::decode):
+        * Modules/webauthn/PublicKeyCredentialCreationOptions.idl:
+        * Modules/webauthn/WebAuthenticationConstants.h:
+        * Modules/webauthn/WebAuthenticationUtils.cpp:
+        (WebCore::buildAttestationObject):
+        * Modules/webauthn/WebAuthenticationUtils.h:
+        * Modules/webauthn/fido/DeviceResponseConverter.cpp:
+        (fido::readCTAPMakeCredentialResponse):
+        * Modules/webauthn/fido/DeviceResponseConverter.h:
+        * Modules/webauthn/fido/FidoConstants.h:
+        noneAttestationValue is moved to WebAuthenticationConstants.h.
+        * Modules/webauthn/fido/U2fResponseConverter.cpp:
+        (fido::readU2fRegisterResponse):
+        * Modules/webauthn/fido/U2fResponseConverter.h:
+        * Sources.txt:
+        * WebCore.xcodeproj/project.pbxproj:
+
 2019-05-22  Zalan Bujtas  <za...@apple.com>
 
         [Paste] Add support for preferred presentation size when pasting an image

Modified: trunk/Source/WebCore/DerivedSources-input.xcfilelist (245637 => 245638)


--- trunk/Source/WebCore/DerivedSources-input.xcfilelist	2019-05-22 19:13:34 UTC (rev 245637)
+++ trunk/Source/WebCore/DerivedSources-input.xcfilelist	2019-05-22 19:27:49 UTC (rev 245638)
@@ -294,6 +294,7 @@
 $(PROJECT_DIR)/Modules/webaudio/PeriodicWave.idl
 $(PROJECT_DIR)/Modules/webaudio/ScriptProcessorNode.idl
 $(PROJECT_DIR)/Modules/webaudio/WaveShaperNode.idl
+$(PROJECT_DIR)/Modules/webauthn/AttestationConveyancePreference.idl
 $(PROJECT_DIR)/Modules/webauthn/AuthenticationExtensionsClientInputs.idl
 $(PROJECT_DIR)/Modules/webauthn/AuthenticatorAssertionResponse.idl
 $(PROJECT_DIR)/Modules/webauthn/AuthenticatorAttestationResponse.idl

Modified: trunk/Source/WebCore/DerivedSources-output.xcfilelist (245637 => 245638)


--- trunk/Source/WebCore/DerivedSources-output.xcfilelist	2019-05-22 19:13:34 UTC (rev 245637)
+++ trunk/Source/WebCore/DerivedSources-output.xcfilelist	2019-05-22 19:27:49 UTC (rev 245638)
@@ -124,6 +124,8 @@
 $(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSApplePayValidateMerchantEvent.h
 $(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSAriaAttributes.cpp
 $(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSAriaAttributes.h
+$(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSAttestationConveyancePreference.cpp
+$(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSAttestationConveyancePreference.h
 $(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSAttr.cpp
 $(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSAttr.h
 $(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSAudioBuffer.cpp

Modified: trunk/Source/WebCore/DerivedSources.make (245637 => 245638)


--- trunk/Source/WebCore/DerivedSources.make	2019-05-22 19:13:34 UTC (rev 245637)
+++ trunk/Source/WebCore/DerivedSources.make	2019-05-22 19:27:49 UTC (rev 245638)
@@ -351,6 +351,7 @@
     $(WebCore)/Modules/webaudio/PeriodicWave.idl \
     $(WebCore)/Modules/webaudio/ScriptProcessorNode.idl \
     $(WebCore)/Modules/webaudio/WaveShaperNode.idl \
+    $(WebCore)/Modules/webauthn/AttestationConveyancePreference.idl \
     $(WebCore)/Modules/webauthn/AuthenticationExtensionsClientInputs.idl \
     $(WebCore)/Modules/webauthn/AuthenticatorAssertionResponse.idl \
     $(WebCore)/Modules/webauthn/AuthenticatorAttestationResponse.idl \

Modified: trunk/Source/WebCore/Headers.cmake (245637 => 245638)


--- trunk/Source/WebCore/Headers.cmake	2019-05-22 19:13:34 UTC (rev 245637)
+++ trunk/Source/WebCore/Headers.cmake	2019-05-22 19:27:49 UTC (rev 245638)
@@ -112,6 +112,7 @@
     Modules/streams/ReadableStreamSink.h
     Modules/streams/ReadableStreamSource.h
 
+    Modules/webauthn/AttestationConveyancePreference.h
     Modules/webauthn/AuthenticationExtensionsClientInputs.h
     Modules/webauthn/AuthenticatorCoordinator.h
     Modules/webauthn/AuthenticatorCoordinatorClient.h

Copied: trunk/Source/WebCore/Modules/webauthn/AttestationConveyancePreference.h (from rev 245637, trunk/Source/WebCore/Modules/webauthn/WebAuthenticationUtils.h) (0 => 245638)


--- trunk/Source/WebCore/Modules/webauthn/AttestationConveyancePreference.h	                        (rev 0)
+++ trunk/Source/WebCore/Modules/webauthn/AttestationConveyancePreference.h	2019-05-22 19:27:49 UTC (rev 245638)
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2019 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#if ENABLE(WEB_AUTHN)
+
+#include <wtf/Forward.h>
+
+namespace WebCore {
+
+enum class AttestationConveyancePreference {
+    None,
+    Indirect,
+    Direct
+};
+
+} // namespace WebCore
+
+namespace WTF {
+
+template<> struct EnumTraits<WebCore::AttestationConveyancePreference> {
+    using values = EnumValues<
+        WebCore::AttestationConveyancePreference,
+        WebCore::AttestationConveyancePreference::None,
+        WebCore::AttestationConveyancePreference::Indirect,
+        WebCore::AttestationConveyancePreference::Direct
+    >;
+};
+
+} // namespace WTF
+
+#endif // ENABLE(WEB_AUTHN)

Copied: trunk/Source/WebCore/Modules/webauthn/AttestationConveyancePreference.idl (from rev 245637, trunk/Source/WebCore/Modules/webauthn/WebAuthenticationUtils.h) (0 => 245638)


--- trunk/Source/WebCore/Modules/webauthn/AttestationConveyancePreference.idl	                        (rev 0)
+++ trunk/Source/WebCore/Modules/webauthn/AttestationConveyancePreference.idl	2019-05-22 19:27:49 UTC (rev 245638)
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2019 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+[
+    Conditional=WEB_AUTHN,
+] enum AttestationConveyancePreference {
+    "none",
+    "indirect",
+    "direct"
+};

Modified: trunk/Source/WebCore/Modules/webauthn/PublicKeyCredentialCreationOptions.h (245637 => 245638)


--- trunk/Source/WebCore/Modules/webauthn/PublicKeyCredentialCreationOptions.h	2019-05-22 19:13:34 UTC (rev 245637)
+++ trunk/Source/WebCore/Modules/webauthn/PublicKeyCredentialCreationOptions.h	2019-05-22 19:27:49 UTC (rev 245638)
@@ -27,6 +27,7 @@
 
 #if ENABLE(WEB_AUTHN)
 
+#include "AttestationConveyancePreference.h"
 #include "AuthenticationExtensionsClientInputs.h"
 #include "BufferSource.h"
 #include "PublicKeyCredentialDescriptor.h"
@@ -84,6 +85,7 @@
     Optional<unsigned> timeout;
     Vector<PublicKeyCredentialDescriptor> excludeCredentials;
     Optional<AuthenticatorSelectionCriteria> authenticatorSelection;
+    AttestationConveyancePreference attestation;
     Optional<AuthenticationExtensionsClientInputs> extensions; // A place holder, but never used.
 
     template<class Encoder> void encode(Encoder&) const;
@@ -142,7 +144,7 @@
     encoder << rp.id << rp.name << rp.icon;
     encoder << static_cast<uint64_t>(user.id.length());
     encoder.encodeFixedLengthData(user.id.data(), user.id.length(), 1);
-    encoder << user.displayName << user.name << user.icon << pubKeyCredParams << timeout << excludeCredentials << authenticatorSelection;
+    encoder << user.displayName << user.name << user.icon << pubKeyCredParams << timeout << excludeCredentials << authenticatorSelection << attestation;
 }
 
 template<class Decoder>
@@ -181,6 +183,12 @@
         return WTF::nullopt;
     result.authenticatorSelection = WTFMove(*authenticatorSelection);
 
+    Optional<AttestationConveyancePreference> attestation;
+    decoder >> attestation;
+    if (!attestation)
+        return WTF::nullopt;
+    result.attestation = WTFMove(*attestation);
+
     return result;
 }
 

Modified: trunk/Source/WebCore/Modules/webauthn/PublicKeyCredentialCreationOptions.idl (245637 => 245638)


--- trunk/Source/WebCore/Modules/webauthn/PublicKeyCredentialCreationOptions.idl	2019-05-22 19:13:34 UTC (rev 245637)
+++ trunk/Source/WebCore/Modules/webauthn/PublicKeyCredentialCreationOptions.idl	2019-05-22 19:27:49 UTC (rev 245638)
@@ -37,8 +37,7 @@
     unsigned long timeout;
     sequence<PublicKeyCredentialDescriptor> excludeCredentials = [];
     AuthenticatorSelectionCriteria authenticatorSelection;
-    // Always "direct" for us.
-    // AttestationConveyancePreference attestation = "none";
+    AttestationConveyancePreference attestation = "none";
     AuthenticationExtensionsClientInputs extensions;
 };
 

Modified: trunk/Source/WebCore/Modules/webauthn/WebAuthenticationConstants.h (245637 => 245638)


--- trunk/Source/WebCore/Modules/webauthn/WebAuthenticationConstants.h	2019-05-22 19:13:34 UTC (rev 245637)
+++ trunk/Source/WebCore/Modules/webauthn/WebAuthenticationConstants.h	2019-05-22 19:27:49 UTC (rev 245638)
@@ -67,4 +67,7 @@
 // Per Section 2.3.5 of http://www.secg.org/sec1-v2.pdf
 const size_t ES256FieldElementLength = 32;
 
+// https://www.w3.org/TR/webauthn/#none-attestation
+const char noneAttestationValue[] = "none";
+
 } // namespace WebCore

Modified: trunk/Source/WebCore/Modules/webauthn/WebAuthenticationUtils.cpp (245637 => 245638)


--- trunk/Source/WebCore/Modules/webauthn/WebAuthenticationUtils.cpp	2019-05-22 19:13:34 UTC (rev 245637)
+++ trunk/Source/WebCore/Modules/webauthn/WebAuthenticationUtils.cpp	2019-05-22 19:27:49 UTC (rev 245638)
@@ -110,9 +110,20 @@
     return authData;
 }
 
-Vector<uint8_t> buildAttestationObject(Vector<uint8_t>&& authData, String&& format, cbor::CBORValue::MapValue&& statementMap)
+Vector<uint8_t> buildAttestationObject(Vector<uint8_t>&& authData, String&& format, cbor::CBORValue::MapValue&& statementMap, const AttestationConveyancePreference& attestation)
 {
     cbor::CBORValue::MapValue attestationObjectMap;
+    // The following implements Step 20 with regard to AttestationConveyancePreference
+    // of https://www.w3.org/TR/webauthn/#createCredential as of 4 March 2019.
+    // None attestation is always returned if it is requested to keep consistency, and therefore skip the
+    // step to return self attestation.
+    if (attestation == AttestationConveyancePreference::None) {
+        const size_t aaguidOffset = rpIdHashLength + flagsLength + signCounterLength;
+        if (authData.size() >= aaguidOffset + aaguidLength)
+            memset(authData.data() + aaguidOffset, 0, aaguidLength);
+        format = noneAttestationValue;
+        statementMap.clear();
+    }
     attestationObjectMap[cbor::CBORValue("authData")] = cbor::CBORValue(WTFMove(authData));
     attestationObjectMap[cbor::CBORValue("fmt")] = cbor::CBORValue(WTFMove(format));
     attestationObjectMap[cbor::CBORValue("attStmt")] = cbor::CBORValue(WTFMove(statementMap));

Modified: trunk/Source/WebCore/Modules/webauthn/WebAuthenticationUtils.h (245637 => 245638)


--- trunk/Source/WebCore/Modules/webauthn/WebAuthenticationUtils.h	2019-05-22 19:13:34 UTC (rev 245637)
+++ trunk/Source/WebCore/Modules/webauthn/WebAuthenticationUtils.h	2019-05-22 19:27:49 UTC (rev 245638)
@@ -27,6 +27,7 @@
 
 #if ENABLE(WEB_AUTHN)
 
+#include "AttestationConveyancePreference.h"
 #include "CBORValue.h"
 #include <wtf/Forward.h>
 
@@ -46,7 +47,7 @@
 WEBCORE_EXPORT Vector<uint8_t> buildAuthData(const String& rpId, const uint8_t flags, const uint32_t counter, const Vector<uint8_t>& optionalAttestedCredentialData);
 
 // https://www.w3.org/TR/webauthn/#attestation-object
-WEBCORE_EXPORT Vector<uint8_t> buildAttestationObject(Vector<uint8_t>&& authData, String&& format, cbor::CBORValue::MapValue&& statementMap);
+WEBCORE_EXPORT Vector<uint8_t> buildAttestationObject(Vector<uint8_t>&& authData, String&& format, cbor::CBORValue::MapValue&& statementMap, const AttestationConveyancePreference&);
 
 } // namespace WebCore
 

Modified: trunk/Source/WebCore/Modules/webauthn/fido/DeviceResponseConverter.cpp (245637 => 245638)


--- trunk/Source/WebCore/Modules/webauthn/fido/DeviceResponseConverter.cpp	2019-05-22 19:13:34 UTC (rev 245637)
+++ trunk/Source/WebCore/Modules/webauthn/fido/DeviceResponseConverter.cpp	2019-05-22 19:27:49 UTC (rev 245638)
@@ -36,6 +36,7 @@
 #include "CBORReader.h"
 #include "CBORWriter.h"
 #include "WebAuthenticationConstants.h"
+#include "WebAuthenticationUtils.h"
 #include <wtf/StdSet.h>
 #include <wtf/Vector.h>
 
@@ -84,7 +85,7 @@
 
 // Decodes byte array response from authenticator to CBOR value object and
 // checks for correct encoding format.
-Optional<PublicKeyCredentialData> readCTAPMakeCredentialResponse(const Vector<uint8_t>& inBuffer)
+Optional<PublicKeyCredentialData> readCTAPMakeCredentialResponse(const Vector<uint8_t>& inBuffer, const WebCore::AttestationConveyancePreference& attestation)
 {
     if (inBuffer.size() <= kResponseCodeLength)
         return WTF::nullopt;
@@ -115,11 +116,19 @@
         return WTF::nullopt;
     auto attStmt = it->second.clone();
 
-    CBOR::MapValue attestationObjectMap;
-    attestationObjectMap[CBOR("authData")] = WTFMove(authenticatorData);
-    attestationObjectMap[CBOR("fmt")] = WTFMove(format);
-    attestationObjectMap[CBOR("attStmt")] = WTFMove(attStmt);
-    auto attestationObject = cbor::CBORWriter::write(CBOR(WTFMove(attestationObjectMap)));
+    Optional<Vector<uint8_t>> attestationObject;
+    if (attestation == AttestationConveyancePreference::None) {
+        // The reason why we can't directly pass authenticatorData/format/attStmt to buildAttestationObject
+        // is that they are CBORValue instead of the raw type.
+        // Also, format and attStmt are omitted as they are not useful in none attestation.
+        attestationObject = buildAttestationObject(Vector<uint8_t>(authenticatorData.getByteString()), "", { }, attestation);
+    } else {
+        CBOR::MapValue attestationObjectMap;
+        attestationObjectMap[CBOR("authData")] = WTFMove(authenticatorData);
+        attestationObjectMap[CBOR("fmt")] = WTFMove(format);
+        attestationObjectMap[CBOR("attStmt")] = WTFMove(attStmt);
+        attestationObject = cbor::CBORWriter::write(CBOR(WTFMove(attestationObjectMap)));
+    }
 
     return PublicKeyCredentialData { ArrayBuffer::create(credentialId.data(), credentialId.size()), true, nullptr, ArrayBuffer::create(attestationObject.value().data(), attestationObject.value().size()), nullptr, nullptr, nullptr, WTF::nullopt };
 }

Modified: trunk/Source/WebCore/Modules/webauthn/fido/DeviceResponseConverter.h (245637 => 245638)


--- trunk/Source/WebCore/Modules/webauthn/fido/DeviceResponseConverter.h	2019-05-22 19:13:34 UTC (rev 245637)
+++ trunk/Source/WebCore/Modules/webauthn/fido/DeviceResponseConverter.h	2019-05-22 19:27:49 UTC (rev 245638)
@@ -31,6 +31,7 @@
 
 #if ENABLE(WEB_AUTHN)
 
+#include "AttestationConveyancePreference.h"
 #include "AuthenticatorGetInfoResponse.h"
 #include "FidoConstants.h"
 #include "PublicKeyCredentialData.h"
@@ -48,7 +49,7 @@
 // and converts response to AuthenticatorMakeCredentialResponse object with
 // CBOR map keys that conform to format of attestation object defined by the
 // WebAuthN spec : https://w3c.github.io/webauthn/#fig-attStructs
-WEBCORE_EXPORT Optional<WebCore::PublicKeyCredentialData> readCTAPMakeCredentialResponse(const Vector<uint8_t>&);
+WEBCORE_EXPORT Optional<WebCore::PublicKeyCredentialData> readCTAPMakeCredentialResponse(const Vector<uint8_t>&, const WebCore::AttestationConveyancePreference& attestation = WebCore::AttestationConveyancePreference::Direct);
 
 // De-serializes CBOR encoded response to AuthenticatorGetAssertion /
 // AuthenticatorGetNextAssertion request to AuthenticatorGetAssertionResponse

Modified: trunk/Source/WebCore/Modules/webauthn/fido/FidoConstants.h (245637 => 245638)


--- trunk/Source/WebCore/Modules/webauthn/fido/FidoConstants.h	2019-05-22 19:13:34 UTC (rev 245637)
+++ trunk/Source/WebCore/Modules/webauthn/fido/FidoConstants.h	2019-05-22 19:27:49 UTC (rev 245638)
@@ -207,7 +207,6 @@
 const char kFormatKey[] = "fmt";
 const char kAttestationStatementKey[] = "attStmt";
 const char kAuthDataKey[] = "authData";
-const char kNoneAttestationValue[] = "none";
 
 // String representation of public key credential enum.
 // https://w3c.github.io/webauthn/#credentialType

Modified: trunk/Source/WebCore/Modules/webauthn/fido/U2fResponseConverter.cpp (245637 => 245638)


--- trunk/Source/WebCore/Modules/webauthn/fido/U2fResponseConverter.cpp	2019-05-22 19:13:34 UTC (rev 245637)
+++ trunk/Source/WebCore/Modules/webauthn/fido/U2fResponseConverter.cpp	2019-05-22 19:27:49 UTC (rev 245638)
@@ -147,7 +147,7 @@
 
 } // namespace
 
-Optional<PublicKeyCredentialData> readU2fRegisterResponse(const String& rpId, const Vector<uint8_t>& u2fData)
+Optional<PublicKeyCredentialData> readU2fRegisterResponse(const String& rpId, const Vector<uint8_t>& u2fData, const AttestationConveyancePreference& attestation)
 {
     auto publicKey = extractECPublicKeyFromU2fRegistrationResponse(u2fData);
     if (publicKey.isEmpty())
@@ -168,7 +168,7 @@
     if (fidoAttestationStatement.empty())
         return WTF::nullopt;
 
-    auto attestationObject = buildAttestationObject(WTFMove(authData), "fido-u2f", WTFMove(fidoAttestationStatement));
+    auto attestationObject = buildAttestationObject(WTFMove(authData), "fido-u2f", WTFMove(fidoAttestationStatement), attestation);
 
     return PublicKeyCredentialData { ArrayBuffer::create(credentialId.data(), credentialId.size()), true, nullptr, ArrayBuffer::create(attestationObject.data(), attestationObject.size()), nullptr, nullptr, nullptr, WTF::nullopt };
 }

Modified: trunk/Source/WebCore/Modules/webauthn/fido/U2fResponseConverter.h (245637 => 245638)


--- trunk/Source/WebCore/Modules/webauthn/fido/U2fResponseConverter.h	2019-05-22 19:13:34 UTC (rev 245637)
+++ trunk/Source/WebCore/Modules/webauthn/fido/U2fResponseConverter.h	2019-05-22 19:27:49 UTC (rev 245638)
@@ -31,6 +31,7 @@
 
 #if ENABLE(WEB_AUTHN)
 
+#include "AttestationConveyancePreference.h"
 #include "PublicKeyCredentialData.h"
 #include <wtf/Forward.h>
 
@@ -38,7 +39,7 @@
 
 // Converts a U2F register response to WebAuthN makeCredential response.
 // https://fidoalliance.org/specs/fido-v2.0-id-20180227/fido-client-to-authenticator-protocol-v2.0-id-20180227.html#u2f-authenticatorMakeCredential-interoperability
-WEBCORE_EXPORT Optional<WebCore::PublicKeyCredentialData> readU2fRegisterResponse(const String& rpId, const Vector<uint8_t>& u2fData);
+WEBCORE_EXPORT Optional<WebCore::PublicKeyCredentialData> readU2fRegisterResponse(const String& rpId, const Vector<uint8_t>& u2fData, const WebCore::AttestationConveyancePreference& attestation = WebCore::AttestationConveyancePreference::Direct);
 
 // Converts a U2F authentication response to WebAuthN getAssertion response.
 // https://fidoalliance.org/specs/fido-v2.0-id-20180227/fido-client-to-authenticator-protocol-v2.0-id-20180227.html#u2f-authenticatorGetAssertion-interoperability

Modified: trunk/Source/WebCore/Sources.txt (245637 => 245638)


--- trunk/Source/WebCore/Sources.txt	2019-05-22 19:13:34 UTC (rev 245637)
+++ trunk/Source/WebCore/Sources.txt	2019-05-22 19:27:49 UTC (rev 245638)
@@ -2518,6 +2518,7 @@
 JSAudioNode.cpp
 JSAudioParam.cpp
 JSAudioProcessingEvent.cpp
+JSAttestationConveyancePreference.cpp
 JSAuthenticationExtensionsClientInputs.cpp
 JSAuthenticatorAssertionResponse.cpp
 JSAuthenticatorAttestationResponse.cpp

Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (245637 => 245638)


--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2019-05-22 19:13:34 UTC (rev 245637)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2019-05-22 19:27:49 UTC (rev 245638)
@@ -1810,6 +1810,9 @@
 		57C7A68C1E56967500C67D71 /* BasicCredential.h in Headers */ = {isa = PBXBuildFile; fileRef = 57C7A68B1E56967500C67D71 /* BasicCredential.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		57C7A69F1E57917800C67D71 /* JSBasicCredential.h in Headers */ = {isa = PBXBuildFile; fileRef = 57C7A69D1E57910D00C67D71 /* JSBasicCredential.h */; };
 		57D0018D1DD5413200ED19D9 /* JSCryptoKeyUsage.h in Headers */ = {isa = PBXBuildFile; fileRef = 57D0018C1DD5413200ED19D9 /* JSCryptoKeyUsage.h */; };
+		57D135252294A33C00827401 /* AttestationConveyancePreference.h in Headers */ = {isa = PBXBuildFile; fileRef = 57D135212294973400827401 /* AttestationConveyancePreference.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		57D1352A2294AA3900827401 /* JSAuthenticationExtensionsClientInputs.h in Headers */ = {isa = PBXBuildFile; fileRef = 57DA47AD224032DD002A4612 /* JSAuthenticationExtensionsClientInputs.h */; };
+		57D1352C2294AA3D00827401 /* JSAttestationConveyancePreference.h in Headers */ = {isa = PBXBuildFile; fileRef = 57D135262294A7A700827401 /* JSAttestationConveyancePreference.h */; };
 		57D8462E1FEAF69900CA3682 /* PublicKeyCredential.h in Headers */ = {isa = PBXBuildFile; fileRef = 57D8462B1FEAF68F00CA3682 /* PublicKeyCredential.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		57D846351FEAFCD300CA3682 /* JSPublicKeyCredential.h in Headers */ = {isa = PBXBuildFile; fileRef = 57D846301FEAFC2F00CA3682 /* JSPublicKeyCredential.h */; };
 		57DA47B0224034E4002A4612 /* AuthenticationExtensionsClientInputs.h in Headers */ = {isa = PBXBuildFile; fileRef = 57DA47A522401E0F002A4612 /* AuthenticationExtensionsClientInputs.h */; settings = {ATTRIBUTES = (Private, ); }; };
@@ -8691,6 +8694,10 @@
 		57D0018B1DD3DBA400ED19D9 /* CryptoKeyUsage.idl */ = {isa = PBXFileReference; lastKnownFileType = text; path = CryptoKeyUsage.idl; sourceTree = "<group>"; };
 		57D0018C1DD5413200ED19D9 /* JSCryptoKeyUsage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSCryptoKeyUsage.h; sourceTree = "<group>"; };
 		57D0018E1DD5415300ED19D9 /* JSCryptoKeyUsage.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSCryptoKeyUsage.cpp; sourceTree = "<group>"; };
+		57D135212294973400827401 /* AttestationConveyancePreference.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AttestationConveyancePreference.h; sourceTree = "<group>"; };
+		57D135232294973400827401 /* AttestationConveyancePreference.idl */ = {isa = PBXFileReference; lastKnownFileType = text; path = AttestationConveyancePreference.idl; sourceTree = "<group>"; };
+		57D135262294A7A700827401 /* JSAttestationConveyancePreference.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSAttestationConveyancePreference.h; sourceTree = "<group>"; };
+		57D135272294A7A800827401 /* JSAttestationConveyancePreference.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSAttestationConveyancePreference.cpp; sourceTree = "<group>"; };
 		57D846241FE895F500CA3682 /* NavigatorCredentials.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NavigatorCredentials.cpp; sourceTree = "<group>"; };
 		57D846251FE895F600CA3682 /* NavigatorCredentials.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = NavigatorCredentials.idl; sourceTree = "<group>"; };
 		57D846261FE895F800CA3682 /* NavigatorCredentials.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NavigatorCredentials.h; sourceTree = "<group>"; };
@@ -19532,6 +19539,8 @@
 				57152B5321CB2CE3000C37CA /* apdu */,
 				57303BB32006C6ED00355965 /* cbor */,
 				578A4BFA2166AE0000D08F34 /* fido */,
+				57D135212294973400827401 /* AttestationConveyancePreference.h */,
+				57D135232294973400827401 /* AttestationConveyancePreference.idl */,
 				57DA47A522401E0F002A4612 /* AuthenticationExtensionsClientInputs.h */,
 				57DA47A722401E0F002A4612 /* AuthenticationExtensionsClientInputs.idl */,
 				57303C272009B2FC00355965 /* AuthenticatorAssertionResponse.h */,
@@ -19570,6 +19579,8 @@
 		57D8462F1FEAFB0500CA3682 /* WebAuthN */ = {
 			isa = PBXGroup;
 			children = (
+				57D135272294A7A800827401 /* JSAttestationConveyancePreference.cpp */,
+				57D135262294A7A700827401 /* JSAttestationConveyancePreference.h */,
 				57DA47AC224032DC002A4612 /* JSAuthenticationExtensionsClientInputs.cpp */,
 				57DA47AD224032DD002A4612 /* JSAuthenticationExtensionsClientInputs.h */,
 				57303C2E2009B7DA00355965 /* JSAuthenticatorAssertionResponse.cpp */,
@@ -28187,6 +28198,7 @@
 				FD5686CA13AC180200B69C68 /* AsyncAudioDecoder.h in Headers */,
 				E1CDE9221501916900862CC5 /* AsyncFileStream.h in Headers */,
 				0FFD4D6118651FA300512F6E /* AsyncScrollingCoordinator.h in Headers */,
+				57D135252294A33C00827401 /* AttestationConveyancePreference.h in Headers */,
 				A8C4A80D09D563270003AC8D /* Attr.h in Headers */,
 				A8C4A80B09D563270003AC8D /* Attribute.h in Headers */,
 				E4A814DA1C70E10D00BF85AC /* AttributeChangeInvalidation.h in Headers */,
@@ -29551,6 +29563,7 @@
 				7C6579F41E00856600E3A27A /* JSApplePayShippingMethod.h in Headers */,
 				1AE96A931D1A0DDD00B86768 /* JSApplePayShippingMethodSelectedEvent.h in Headers */,
 				A12C59FE20360B4A0012236B /* JSApplePayShippingMethodUpdate.h in Headers */,
+				57D1352C2294AA3D00827401 /* JSAttestationConveyancePreference.h in Headers */,
 				65DF31DB09D1C123000BE325 /* JSAttr.h in Headers */,
 				FDA15E9E12B03EE1003A583A /* JSAudioBuffer.h in Headers */,
 				FDF7E9C413AC21DB00A51EAC /* JSAudioBufferCallback.h in Headers */,
@@ -29563,6 +29576,7 @@
 				FDA15EB612B03EE1003A583A /* JSAudioProcessingEvent.h in Headers */,
 				BE8EF043171C8FF9009B48C3 /* JSAudioTrack.h in Headers */,
 				BE8EF045171C8FF9009B48C3 /* JSAudioTrackList.h in Headers */,
+				57D1352A2294AA3900827401 /* JSAuthenticationExtensionsClientInputs.h in Headers */,
 				57303C2F2009B7E100355965 /* JSAuthenticatorAssertionResponse.h in Headers */,
 				57303C222009AF0300355965 /* JSAuthenticatorAttestationResponse.h in Headers */,
 				57303BE120095D6100355965 /* JSAuthenticatorResponse.h in Headers */,

Modified: trunk/Source/WebKit/ChangeLog (245637 => 245638)


--- trunk/Source/WebKit/ChangeLog	2019-05-22 19:13:34 UTC (rev 245637)
+++ trunk/Source/WebKit/ChangeLog	2019-05-22 19:27:49 UTC (rev 245638)
@@ -1,3 +1,18 @@
+2019-05-22  Jiewen Tan  <jiewen_...@apple.com>
+
+        [WebAuthN] Support Attestation Conveyance Preference
+        https://bugs.webkit.org/show_bug.cgi?id=192722
+        <rdar://problem/49939647>
+
+        Reviewed by Brent Fulgham.
+
+        * UIProcess/WebAuthentication/Cocoa/LocalAuthenticator.mm:
+        (WebKit::LocalAuthenticator::continueMakeCredentialAfterAttested):
+        * UIProcess/WebAuthentication/fido/CtapHidAuthenticator.cpp:
+        (WebKit::CtapHidAuthenticator::continueMakeCredentialAfterResponseReceived const):
+        * UIProcess/WebAuthentication/fido/U2fHidAuthenticator.cpp:
+        (WebKit::U2fHidAuthenticator::continueRegisterCommandAfterResponseReceived):
+
 2019-05-22  Zalan Bujtas  <za...@apple.com>
 
         [Paste] Add support for preferred presentation size when pasting an image

Modified: trunk/Source/WebKit/UIProcess/WebAuthentication/Cocoa/LocalAuthenticator.mm (245637 => 245638)


--- trunk/Source/WebKit/UIProcess/WebAuthentication/Cocoa/LocalAuthenticator.mm	2019-05-22 19:13:34 UTC (rev 245637)
+++ trunk/Source/WebKit/UIProcess/WebAuthentication/Cocoa/LocalAuthenticator.mm	2019-05-22 19:27:49 UTC (rev 245638)
@@ -324,7 +324,7 @@
             cborArray.append(cbor::CBORValue(toVector((NSData *)adoptCF(SecCertificateCopyData((__bridge SecCertificateRef)certificates[i])).get())));
         attestationStatementMap[cbor::CBORValue("x5c")] = cbor::CBORValue(WTFMove(cborArray));
     }
-    auto attestationObject = buildAttestationObject(WTFMove(authData), "Apple", WTFMove(attestationStatementMap));
+    auto attestationObject = buildAttestationObject(WTFMove(authData), "Apple", WTFMove(attestationStatementMap), requestData().creationOptions.attestation);
 
     receiveRespond(PublicKeyCredentialData { ArrayBuffer::create(credentialId.data(), credentialId.size()), true, nullptr, ArrayBuffer::create(attestationObject.data(), attestationObject.size()), nullptr, nullptr, nullptr, WTF::nullopt });
 #endif // !PLATFORM(IOS_FAMILY)

Modified: trunk/Source/WebKit/UIProcess/WebAuthentication/fido/CtapHidAuthenticator.cpp (245637 => 245638)


--- trunk/Source/WebKit/UIProcess/WebAuthentication/fido/CtapHidAuthenticator.cpp	2019-05-22 19:13:34 UTC (rev 245637)
+++ trunk/Source/WebKit/UIProcess/WebAuthentication/fido/CtapHidAuthenticator.cpp	2019-05-22 19:27:49 UTC (rev 245638)
@@ -62,7 +62,7 @@
 
 void CtapHidAuthenticator::continueMakeCredentialAfterResponseReceived(Vector<uint8_t>&& data) const
 {
-    auto response = readCTAPMakeCredentialResponse(data);
+    auto response = readCTAPMakeCredentialResponse(data, requestData().creationOptions.attestation);
     if (!response) {
         auto error = getResponseCode(data);
         if (error == CtapDeviceResponseCode::kCtap2ErrCredentialExcluded)

Modified: trunk/Source/WebKit/UIProcess/WebAuthentication/fido/U2fHidAuthenticator.cpp (245637 => 245638)


--- trunk/Source/WebKit/UIProcess/WebAuthentication/fido/U2fHidAuthenticator.cpp	2019-05-22 19:13:34 UTC (rev 245637)
+++ trunk/Source/WebKit/UIProcess/WebAuthentication/fido/U2fHidAuthenticator.cpp	2019-05-22 19:27:49 UTC (rev 245638)
@@ -152,7 +152,7 @@
 {
     switch (apduResponse.status()) {
     case ApduResponse::Status::SW_NO_ERROR: {
-        auto response = readU2fRegisterResponse(requestData().creationOptions.rp.id, apduResponse.data());
+        auto response = readU2fRegisterResponse(requestData().creationOptions.rp.id, apduResponse.data(), requestData().creationOptions.attestation);
         if (!response) {
             receiveRespond(ExceptionData { UnknownError, "Couldn't parse the U2F register response."_s });
             return;

Modified: trunk/Tools/ChangeLog (245637 => 245638)


--- trunk/Tools/ChangeLog	2019-05-22 19:13:34 UTC (rev 245637)
+++ trunk/Tools/ChangeLog	2019-05-22 19:27:49 UTC (rev 245638)
@@ -1,3 +1,15 @@
+2019-05-22  Jiewen Tan  <jiewen_...@apple.com>
+
+        [WebAuthN] Support Attestation Conveyance Preference
+        https://bugs.webkit.org/show_bug.cgi?id=192722
+        <rdar://problem/49939647>
+
+        Reviewed by Brent Fulgham.
+
+        * TestWebKitAPI/Tests/WebCore/CtapRequestTest.cpp:
+        (TestWebKitAPI::TEST):
+        Updates the test with AttestationConveyancePreference.
+
 2019-05-22  Zalan Bujtas  <za...@apple.com>
 
         [Paste] Add support for preferred presentation size when pasting an image

Modified: trunk/Tools/TestWebKitAPI/Tests/WebCore/CtapRequestTest.cpp (245637 => 245638)


--- trunk/Tools/TestWebKitAPI/Tests/WebCore/CtapRequestTest.cpp	2019-05-22 19:13:34 UTC (rev 245637)
+++ trunk/Tools/TestWebKitAPI/Tests/WebCore/CtapRequestTest.cpp	2019-05-22 19:27:49 UTC (rev 245638)
@@ -59,7 +59,7 @@
     Vector<PublicKeyCredentialCreationOptions::Parameters> params { { PublicKeyCredentialType::PublicKey, 7 }, { PublicKeyCredentialType::PublicKey, 257 } };
     PublicKeyCredentialCreationOptions::AuthenticatorSelectionCriteria selection { PublicKeyCredentialCreationOptions::AuthenticatorAttachment::Platform, true, UserVerificationRequirement::Preferred };
 
-    PublicKeyCredentialCreationOptions options { rp, user, { }, params, WTF::nullopt, { }, selection, WTF::nullopt };
+    PublicKeyCredentialCreationOptions options { rp, user, { }, params, WTF::nullopt, { }, selection, AttestationConveyancePreference::None, WTF::nullopt };
     Vector<uint8_t> hash;
     hash.append(TestData::kClientDataHash, sizeof(TestData::kClientDataHash));
     auto serializedData = encodeMakeCredenitalRequestAsCBOR(hash, options, AuthenticatorSupportedOptions::UserVerificationAvailability::kSupportedButNotConfigured);
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to